package com.nedap.archie.serializer.adl;

import com.nedap.archie.aom.*;
import com.nedap.archie.aom.primitives.*;
import com.nedap.archie.aom.terminology.ArchetypeTerm;
import com.nedap.archie.serializer.adl.constraints.*;

import java.util.HashMap;
import java.util.Map;

/**
 * @author markopi
 */
public class ADLDefinitionSerializer {
    protected final ADLStringBuilder builder;

    private final Map<Class, ConstraintSerializer> constraintSerializers;

    public ADLDefinitionSerializer(ADLStringBuilder builder) {
        this.builder = builder;

        constraintSerializers = new HashMap<>();
        constraintSerializers.put(ArchetypeSlot.class, new ArchetypeSlotSerializer(this));
        constraintSerializers.put(CArchetypeRoot.class, new CArchetypeRootSerializer(this));
        constraintSerializers.put(CBoolean.class, new CBooleanSerializer(this));
        constraintSerializers.put(CComplexObject.class, new CComplexObjectSerializer(this));
        constraintSerializers.put(CComplexObjectProxy.class, new CComplexObjectProxySerializer(this));
        constraintSerializers.put(CDate.class, new CDateSerializer(this));
        constraintSerializers.put(CDateTime.class, new CDateTimeSerializer(this));
        constraintSerializers.put(CDuration.class, new CDurationSerializer(this));
        constraintSerializers.put(CInteger.class, new CIntegerSerializer(this));
        constraintSerializers.put(CReal.class, new CRealSerializer(this));
        constraintSerializers.put(CString.class, new CStringSerializer(this));
        constraintSerializers.put(CTerminologyCode.class, new CTerminologyCodeSerializer(this));
        constraintSerializers.put(CTime.class, new CTimeSerializer(this));
    }


    public ADLStringBuilder getBuilder() {
        return builder;
    }

    public String getTermText(CObject cobj) {
        ArchetypeTerm term = cobj.getArchetype().getTerm(cobj, cobj.getArchetype().getOriginalLanguage().getCodeString());
        if (term == null) return null;
        return term.getText();
    }

    public void appendCObject(CObject cobj) {
        ConstraintSerializer<CObject> serializer = getSerializer(cobj);
        if (serializer != null) {
            serializer.serialize(cobj);
        } else {
            throw new AssertionError("Unsupported constraint: " + cobj.getClass().getName());
        }
    }

    public boolean isEmpty(CObject cobj) {
        ConstraintSerializer<CObject> serializer = getSerializer(cobj);
        return serializer != null && serializer.isEmpty(cobj);
    }

    public String getSimpleCommentText(CObject cobj) {
        ConstraintSerializer<CObject> serializer = getSerializer(cobj);
        if (serializer == null) return null;
        return serializer.getSimpleCommentText(cobj);
    }

    @SuppressWarnings("unchecked")
    private ConstraintSerializer<CObject> getSerializer(CObject cobj) {
        return constraintSerializers.get(cobj.getClass());
    }

    public static String serialize(CObject cons) {
        final ADLStringBuilder builder = new ADLStringBuilder();
        ADLDefinitionSerializer serializer = new ADLDefinitionSerializer(builder);
        serializer.appendCObject(cons);
        return builder.toString();
    }

}

@@ -163,16 +163,74 @@
 peTerm;%0A
+import com.nedap.archie.base.terminology.TerminologyCode;%0A
 import c
@@ -325,16 +325,62 @@
 l.Map;%0A%0A
+import static java.util.Optional.ofNullable;%0A%0A
 /**%0A * @
@@ -1824,191 +1824,751 @@
  %7D%0A%0A
-%0A    public ADLStringBuilder getBuilder() %7B%0A        return builder;%0A    %7D%0A%0A    public String getTermText(CObject cobj) %7B%0A        ArchetypeTerm term = cobj.getArchetype().getTerm(cobj,
+    public static String serialize(CObject cons) %7B%0A        final ADLStringBuilder builder = new ADLStringBuilder();%0A        ADLDefinitionSerializer serializer = new ADLDefinitionSerializer(builder);%0A        serializer.appendCObject(cons);%0A        return builder.toString();%0A    %7D%0A%0A    public ADLStringBuilder getBuilder() %7B%0A        return builder;%0A    %7D%0A%0A    public String getTermText(CObject cobj) %7B%0A        String originalLanguage = ofNullable(cobj)%0A                .flatMap(c -%3E ofNullable(c.getArchetype()))%0A                .flatMap(a -%3E ofNullable(a.getOriginalLanguage()))%0A                .map(TerminologyCode::getCodeString)%0A                .orElse(null);%0A        if (originalLanguage == null) return null;%0A%0A        ArchetypeTerm term =
  cob
@@ -2583,25 +2583,36 @@
 hetype().get
-O
+Term(cobj, o
 riginalLangu
@@ -2618,26 +2618,8 @@
 uage
-().getCodeString()
 );%0A 
@@ -3609,287 +3609,6 @@
  %7D%0A%0A
-    public static String serialize(CObject cons) %7B%0A        final ADLStringBuilder builder = new ADLStringBuilder();%0A        ADLDefinitionSerializer serializer = new ADLDefinitionSerializer(builder);%0A        serializer.appendCObject(cons);%0A        return builder.toString();%0A    %7D%0A%0A
 %7D%0A

Fix NPE when serializing templates with no original language