All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.nedap.archie.serializer.adl.constraints.CComplexObjectSerializer Maven / Gradle / Ivy

package com.nedap.archie.serializer.adl.constraints;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Joiner;
import com.nedap.archie.aom.*;
import com.nedap.archie.base.Cardinality;
import com.nedap.archie.base.OpenEHRBase;
import com.nedap.archie.rminfo.RMObjectMapperProvider;
import com.nedap.archie.serializer.adl.ADLDefinitionSerializer;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.nedap.archie.serializer.adl.ArchetypeSerializeUtils.buildOccurrences;


/**
 * @author Marko Pipan
 */
public class CComplexObjectSerializer extends ConstraintSerializer {
    public CComplexObjectSerializer(ADLDefinitionSerializer serializer) {
        super(serializer);
    }

    @Override
    public void serialize(T cobj) {
        builder.indent().newline();
        appendSiblingOrder(cobj);
        builder.append(cobj.getRmTypeName());
        if (cobj.getNodeId() != null) {
            builder.append("[").append(cobj.getNodeId()).append("]");
        }
        builder.append(" ");
        appendOccurrences(cobj);
        if (cobj.getAttributes().isEmpty() && cobj.getAttributeTuples().isEmpty() && cobj.getDefaultValue() == null) {
            builder.lineComment(serializer.getTermText(cobj));
        } else {
            builder.append("matches {");
            builder.lineComment(serializer.getTermText(cobj));
            buildAttributesAndTuples(cobj);

            builder.append("}");
        }
        builder.unindent();
    }

    protected void buildAttributesAndTuples(T cobj) {
        builder.indent().newline();
        Set tupleAttributes = getTupleAttributeNames(cobj);

        cobj.getAttributes().stream()
                .filter(a -> !tupleAttributes.contains(a.getRmAttributeName()))
                .forEach(this::buildAttribute);

        cobj.getAttributeTuples().forEach(this::buildTuple);
        buildDefaultValue(cobj);

        builder.unindent().newline();
    }

    protected void buildDefaultValue(T cobj) {
        if(cobj.getDefaultValue() != null) {
            if(cobj.getDefaultValue() instanceof DefaultValueContainer) {
                serializeDefaultValueContainer((DefaultValueContainer) cobj.getDefaultValue());
            } else {
                RMObjectMapperProvider rmObjectMapperProvider = serializer.getRmObjectMapperProvider();
                if (rmObjectMapperProvider == null ||
                        (rmObjectMapperProvider.getOutputOdinObjectMapper() == null && rmObjectMapperProvider.getJsonObjectMapper() == null)) {
                    //fallback: serialize generic ODIN. This will likely be non-standard!
                    builder.append("_default = ");
                    builder.newIndentedLine();
                    builder.odin(cobj.getDefaultValue());
                    builder.newUnindentedLine();
                } else {
                    try {
                        String format;
                        String content;
                        if (rmObjectMapperProvider.getJsonObjectMapper() != null) {
                            format = DefaultValueContainer.JSON;
                            //the writerFor here makes sure type info gets output even for the root type
                            content = rmObjectMapperProvider.getJsonObjectMapper().writerFor(OpenEHRBase.class).writeValueAsString(cobj.getDefaultValue());
                        } else {
                            format = DefaultValueContainer.ODIN;
                            //the writerFor here makes sure type info gets output even for the root type
                            content = rmObjectMapperProvider.getOutputOdinObjectMapper().writerFor(OpenEHRBase.class).writeValueAsString(cobj.getDefaultValue());
                        }

                        serializeDefaultValueContainer(new DefaultValueContainer(format, content));
                    } catch (JsonProcessingException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    }

    protected void serializeDefaultValueContainer(DefaultValueContainer container) {
        builder.tryNewLine();
        if(container.getFormat() == null || container.getFormat().equalsIgnoreCase(DefaultValueContainer.ODIN)) {
            builder.append("_default = ");
            builder.newIndentedLine();
            builder.appendMultipleLines(container.getContent());
            builder.unindent();
        } else {
            builder.append("_default = (");
            builder.append(container.getFormat());
            builder.append(") <#");
            if(container.getFormat().equalsIgnoreCase(DefaultValueContainer.JSON)) {
                builder.newIndentedLine();
                builder.appendMultipleLines(container.getContent());
                builder.unindent();
            } else {
                //don't apply indentation - we have no idea of knowing whether this should indent or not for unknown formats
                builder.append(container.getContent());
            }
            builder.append("#>");
        }
    }

    private Set getTupleAttributeNames(T cobj) {
        return cobj.getAttributeTuples().stream()
                    .flatMap(cat -> cat.getMembers().stream())
                    .map(CAttribute::getRmAttributeName)
                    .collect(Collectors.toSet());
    }


    private void buildAttribute(CAttribute cattr) {
        builder.tryNewLine();
        if (cattr.getDifferentialPath() == null) {
            builder.append(cattr.getRmAttributeName());
        } else {
            builder.append(cattr.getDifferentialPath());
        }
        if (cattr.getExistence() != null) {
            builder.append(" existence matches {");
            buildOccurrences(builder, cattr.getExistence());
            builder.append("}");
        }
        if (cattr.getCardinality() != null) {
            builder.append(" cardinality matches {");
            appendCardinality(cattr.getCardinality());
            builder.append("}");
        }
        if (!cattr.getChildren().isEmpty()) {
            buildAttributeChildConstraints(cattr);
        }
    }


    private void buildTuple(CAttributeTuple cAttributeTuple) {
        builder.tryNewLine();
        builder.append("[");
        List members = cAttributeTuple.getMembers().stream()
                .map(CAttribute::getRmAttributeName)
                .collect(Collectors.toList());
        builder.append(Joiner.on(", ").join(members));
        builder.append("] matches {");
        builder.indent();
        for (int i = 0; i < cAttributeTuple.getTuples().size(); i++) {
            CPrimitiveTuple cObjectTuple = cAttributeTuple.getTuples().get(i);
            builder.newline();
            builder.append("[");
            for (int j = 0; j < cObjectTuple.getMembers().size(); j++) {
                builder.append("{");
                serializer.appendCObject(cObjectTuple.getMembers().get(j));
                builder.append("}");
                if (j < cObjectTuple.getMembers().size() - 1) {
                    builder.append(", ");
                }
            }
            builder.append("]");
            if (i < cAttributeTuple.getTuples().size() - 1) {
                builder.append(",");
            }

        }
        builder.unindent().newline();
        builder.append("}");
    }

    private void buildAttributeChildConstraints(CAttribute cattr) {
        List children = filterNonEmptyChildren(cattr.getChildren());
        if(children.isEmpty()) {
            return;
        }

        builder.append(" matches ");
        boolean indent = !children.isEmpty() &&
                (children.size() > 1 || !(children.get(0) instanceof CPrimitiveObject));
        builder.append("{");
        children.forEach(serializer::appendCObject);

        if (indent) {
            builder.newline();
        }

        builder.append("}");

        if (!indent && !children.isEmpty()) {
            String commentText = serializer.getSimpleCommentText(children.get(0));
            if (commentText != null) {
                builder.lineComment(commentText);
            }
        }
    }

    private List filterNonEmptyChildren(List children) {
        return children.stream()
                .filter(child -> !serializer.isEmpty(child))
                .collect(Collectors.toList());
    }

    private void appendCardinality(Cardinality card) {
        buildOccurrences(builder, card.getInterval());
        List tags = new ArrayList<>();
        //TODO: this should compare against the RM and only serialize if different, OR we should make ordered nullable
        //and add a preprocessor that removes all default values
        if (!card.isOrdered()) {
            tags.add("unordered");
        }
        //TODO: this should compare against the RM and only serialize if different, OR we should make unique nullable
        //and add a preprocessor that removes all default values
        if (card.isUnique()) {
            tags.add("unique");
        }
        if (!tags.isEmpty()) {
            builder.append("; ").append(Joiner.on("; ").join(tags));
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy