package com.nedap.archie.adlparser.modelconstraints;

import com.nedap.archie.aom.CAttribute;
import com.nedap.archie.aom.CComplexObject;
import com.nedap.archie.aom.Cardinality;
import com.nedap.archie.rminfo.ModelInfoLookup;
import com.nedap.archie.rminfo.RMAttributeInfo;
import com.nedap.archie.rminfo.RMTypeInfo;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * ModelConstraintImposer that checks the constraint with java-reflection. javax.annotation.NonNull is implemented
 * as being NonNull. Other attributes are assumed to be non-null. Collection attributes are assumed to be 0..*
 *
 * Fully thread-safe, but rather expensive to create. Caching in a static field is encouraged.
 *
 * Created by pieter.bos on 04/11/15.
 */
public class ReflectionConstraintImposer implements ModelConstraintImposer {

    /** Contains complex object structure of the specified model. Attributes NEVER will have children. Sorry bout that :)*/
    private Map<String, CComplexObject> objects = new ConcurrentHashMap<>();

    public ReflectionConstraintImposer(ModelInfoLookup classLookup) {
        List<RMTypeInfo> rmTypes = classLookup.getAllTypes();

        for(RMTypeInfo typeInfo:rmTypes) {
            CComplexObject object = new CComplexObject();
            object.setRmTypeName(typeInfo.getRmName());

            for(RMAttributeInfo attributeInfo:typeInfo.getAttributes().values()) {
                CAttribute attribute = new CAttribute();
                attribute.setCardinality(new Cardinality(1,1));
                attribute.setMultiple(false);
                attribute.setRmAttributeName(attributeInfo.getRmName());

                if(attributeInfo.isNullable()) {
                    //TODO: not correct. Should be existence?
                    attribute.setCardinality(new Cardinality(0,1));
                }

                if(attributeInfo.isMultipleValued()) {
                    attribute.setCardinality(Cardinality.unbounded());
                    attribute.setMultiple(true);
                }
                object.addAttribute(attribute);
            }
            objects.put(object.getRmTypeName(), object);

        }
    }

    @Override
    public CAttribute getDefaultAttribute(String typeId, String attribute) {
        CComplexObject object = objects.get(typeId);
        if(object == null) {
            return null;
        }
        return object.getAttribute(attribute);
    }
}

@@ -310,16 +310,58 @@
 ypeInfo;
+%0Aimport org.jetbrains.annotations.NotNull;
 %0A%0Aimport
@@ -1022,16 +1022,17 @@
 at :)*/%0A
+%0A
     priv
@@ -1040,70 +1040,29 @@
 te M
-ap%3CString, CComplexObject%3E objects = new ConcurrentHashMap%3C%3E()
+odelInfoLookup lookup
 ;%0A%0A 
@@ -1142,312 +1142,128 @@
     
-List%3CRMTypeInfo%3E rmTypes = classLookup.getAllTypes();%0A
+this.lookup = classLookup;
 %0A    
+%7D%0A%0A
     
-for(RMTypeInfo typeInfo:rmTypes) %7B%0A            CComplexObject object = new CComplexObject();%0A            object.setRmTypeName(typeInfo.getRmName());%0A%0A            for(RMAttributeInfo attributeInfo:typeInfo.getAttributes().values()) %7B%0A        
+@NotNull%0A    private CAttribute createCAttribute(RMAttributeInfo attributeInfo) %7B%0A
     
@@ -1307,24 +1307,16 @@
 bute();%0A
-        
         
@@ -1359,32 +1359,24 @@
 lity(1,1));%0A
-        
         attr
@@ -1397,32 +1397,24 @@
 ple(false);%0A
-        
         attr
@@ -1471,32 +1471,24 @@
 );%0A%0A        
-   
-     
 if(attribute
@@ -1504,32 +1504,24 @@
 llable()) %7B%0A
-        
             
@@ -1570,32 +1570,24 @@
             
-       
- 
 attribute.se
@@ -1618,32 +1618,24 @@
 lity(0,1));%0A
-        
         %7D%0A%0A 
@@ -1641,24 +1641,16 @@
         
- 
-       
 if(attri
@@ -1688,32 +1688,24 @@
             
-  
-      
 attribute.se
@@ -1751,32 +1751,24 @@
             
-        
 attribute.se
@@ -1788,32 +1788,24 @@
 e);%0A        
-      
-  
 %7D%0A          
@@ -1806,36 +1806,15 @@
     
-        object.addAttribute(
+return 
 attr
@@ -1822,93 +1822,10 @@
 bute
-)
 ;%0A
-            %7D%0A            objects.put(object.getRmTypeName(), object);%0A%0A        %7D%0A
     
@@ -1930,50 +1930,72 @@
     
-CComplexObject object = objects.get(typeId
+RMAttributeInfo info = lookup.getAttributeInfo(typeId, attribute
 );%0A 
@@ -2004,22 +2004,20 @@
      if(
-object
+info
  == null
@@ -2074,18 +2074,15 @@
 urn 
-object.get
+createC
 Attr
@@ -2087,25 +2087,20 @@
 tribute(
-attribute
+info
 );%0A    %7D
@@ -2100,10 +2100,12 @@
 ;%0A    %7D%0A
+%0A%0A
 %7D%0A

Make constraintimposer return new CAttribute objects for safety reasons