Java tutorial
package se.liu.imt.mi.eee.validation.json; import java.io.BufferedOutputStream; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.StringWriter; import java.io.Writer; import java.lang.reflect.Type; import java.nio.charset.Charset; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.codehaus.jackson.map.AnnotationIntrospector; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.PropertyNamingStrategy; import org.codehaus.jackson.map.SerializationConfig.Feature; import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector; import org.openehr.am.archetype.Archetype; import org.openehr.am.archetype.assertion.Assertion; import org.openehr.am.archetype.constraintmodel.ArchetypeInternalRef; import org.openehr.am.archetype.constraintmodel.ArchetypeSlot; import org.openehr.am.archetype.constraintmodel.CAttribute; import org.openehr.am.archetype.constraintmodel.CComplexObject; import org.openehr.am.archetype.constraintmodel.CDomainType; import org.openehr.am.archetype.constraintmodel.CMultipleAttribute; import org.openehr.am.archetype.constraintmodel.CObject; import org.openehr.am.archetype.constraintmodel.CPrimitiveObject; import org.openehr.am.archetype.constraintmodel.Cardinality; import org.openehr.am.archetype.constraintmodel.ConstraintRef; import org.openehr.am.archetype.constraintmodel.primitive.CBoolean; import org.openehr.am.archetype.constraintmodel.primitive.CDate; import org.openehr.am.archetype.constraintmodel.primitive.CDateTime; import org.openehr.am.archetype.constraintmodel.primitive.CDuration; import org.openehr.am.archetype.constraintmodel.primitive.CInteger; import org.openehr.am.archetype.constraintmodel.primitive.CPrimitive; import org.openehr.am.archetype.constraintmodel.primitive.CReal; import org.openehr.am.archetype.constraintmodel.primitive.CString; import org.openehr.am.archetype.constraintmodel.primitive.CTime; import org.openehr.am.archetype.ontology.ArchetypeOntology; import org.openehr.am.archetype.ontology.ArchetypeTerm; import org.openehr.am.archetype.ontology.OntologyBinding; import org.openehr.am.archetype.ontology.OntologyDefinitions; import org.openehr.am.archetype.ontology.QueryBindingItem; import org.openehr.am.archetype.ontology.TermBindingItem; import org.openehr.am.openehrprofile.datatypes.quantity.CDvOrdinal; import org.openehr.am.openehrprofile.datatypes.quantity.CDvQuantity; import org.openehr.am.openehrprofile.datatypes.quantity.CDvQuantityItem; import org.openehr.am.openehrprofile.datatypes.quantity.Ordinal; import org.openehr.am.openehrprofile.datatypes.text.CCodePhrase; import org.openehr.rm.common.resource.AuthoredResource; import org.openehr.rm.common.resource.ResourceDescription; import org.openehr.rm.common.resource.ResourceDescriptionItem; import org.openehr.rm.common.resource.TranslationDetails; import org.openehr.rm.datatypes.quantity.DvQuantity; import org.openehr.rm.datatypes.quantity.datetime.DvDateTime; import org.openehr.rm.datatypes.text.CodePhrase; import org.openehr.rm.support.basic.Interval; import org.openehr.rm.support.identification.ArchetypeID; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.DumperOptions.FlowStyle; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.nodes.Tag; import sun.reflect.generics.reflectiveObjects.NotImplementedException; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonParseException; import com.google.gson.JsonPrimitive; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; /** * YAML serializer based on the ADL serializer from the openEHR Java kernel * * @author Based on code by Rong Chen, Mattias Forss, Johan Hjalmarsson, * Sebastian Garde * @author Modified by Erik Sundvall * * @version 0.1 */ public class JacksonBasedAOMtoJSONandYAML { protected ObjectMapper mapper; private Gson gson; private Yaml yaml; /** * Create an outputter with default encoding, indent and lineSeparator TODO: * fix node_i_d --> node_id */ public JacksonBasedAOMtoJSONandYAML() { this.encoding = UTF8; this.indent = " "; // 4 white space characters this.lineSeparator = "\r\n"; //// Jackson JSON Configuration mapper = new ObjectMapper(); AnnotationIntrospector introspector = new JacksonAnnotationIntrospector(); mapper.getSerializationConfig().setAnnotationIntrospector(introspector); mapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); mapper.getSerializationConfig().addMixInAnnotations(Archetype.class, ArchetypeJacksonMixIn.class); mapper.getSerializationConfig().addMixInAnnotations(CObject.class, CObjectJsonMixIn.class); mapper.getDeserializationConfig().addMixInAnnotations(Archetype.class, ArchetypeJacksonMixIn.class); //mapper.getVisibilityChecker(). // ON mapper.enable(Feature.INDENT_OUTPUT); // OFF mapper.disable(Feature.WRITE_NULL_MAP_VALUES); mapper.disable(Feature.WRITE_EMPTY_JSON_ARRAYS); //// YAML post-processing of JSON doYaml = true; ////////// Google gson //////////////// // gson = new GsonBuilder() // .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) // .setExclusionStrategies(new ExclusionStrategy() { // public boolean shouldSkipClass(Class<?> clazz) { // if (clazz == Archetype.class) return true; // Avoid circular reference // return false; // } // /* Custom field exclusion goes here */ // public boolean shouldSkipField(FieldAttributes f) { // //System.out.println("---> "+f.getName()); // if (f.getName().equalsIgnoreCase("termDefinitionMap")) return true; // if (f.getName().equalsIgnoreCase("constraintDefinitionMap")) return true; // if (f.getName().equalsIgnoreCase("hiddenOnForm")) return true; // if (f.getName().equalsIgnoreCase("existence")) return true; // // if (f.getName().equalsIgnoreCase("existence")) { // System.out.println(" ==> " +f.getDeclaredClass().getCanonicalName()); // } // // System.out.println(f.getDeclaredClass()); // // return (f.getName().equalsIgnoreCase("code") && f.getDeclaredClass().equals(ArchetypeTerm.class)); // //return (f.getName().equalsIgnoreCase("code")); //TODO: check that no other fields named "code" are there // return false; // } // }) // .registerTypeAdapter(CodePhrase.class, new CodePhraseConverter()) // .registerTypeAdapter(DvDateTime.class, new DvDateTimeConverter()) // .registerTypeAdapter(Interval.class, new IntervalConverterSequenceFormat()) // //.setDateFormat("yyyy-MM-dd'T'HH:mm:ss") // TODO: Check what to do with timezones (probably yoda stuff if DvDateTimeConverter does not suffice) // .create(); /// YAML (SnakeYAML) DumperOptions dumperOptions = new DumperOptions(); //dumperOptions.setDefaultFlowStyle(FlowStyle.BLOCK); //dumperOptions.setLineBreak(LineBreak.WIN); dumperOptions.setWidth(120); //dumperOptions.setDefaultFlowStyle(FlowStyle.FLOW); //dumperOptions.setPrettyFlow(true); //dumperOptions.setDefaultScalarStyle(ScalarStyle.DOUBLE_QUOTED); yaml = new Yaml(dumperOptions); // Yaml(new SyntaxSugarRepresenter()); //yaml.setBeanAccess(BeanAccess.PROPERTY); } // class SyntaxSugarRepresenter extends Representer { // public SyntaxSugarRepresenter() { // this.representers.put(CodePhrase.class, new RepresentCodePhrase()); // } // // private class RepresentCodePhrase implements Represent { // public Node representData(Object data) { // CodePhrase c = (CodePhrase) data; // String value = c.getTerminologyId() +"::"+c.getCodeString(); // return representScalar(new Tag("!CODE_PHRASE"), value); // } // } // } class CodePhraseConverter implements JsonSerializer<CodePhrase>, JsonDeserializer<CodePhrase> { public JsonElement serialize(CodePhrase src, Type typeOfSrc, JsonSerializationContext context) { return new JsonPrimitive(src.getTerminologyId().getValue() + "::" + src.getCodeString()); } // TODO: finish and test this... public CodePhrase deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { String[] split = json.getAsJsonPrimitive().getAsString().split("::"); return new CodePhrase(split[0], split[1]); } } /** * This is an ugly temporary hack (possibly wrongfully) assuming that Interval<Integer> is only used * for multiplicity in the archetype objects. Based on this the interval is converted to a string on the * format lower..upper, e.g. 0..5 or 1..*. If lower and upper are equal then only one number * and no dots are output, e.g. 1 * When using the MULTIPLICITY_INTERVAL in ADL/AOM1.5 instead of Interval<Integer>, then this assumption * will not be needed and the converter can operate safely. */ class IntervalConverterDotFormat implements JsonSerializer<Interval<Integer>>, JsonDeserializer<Interval<Integer>> { public JsonElement serialize(Interval<Integer> src, Type typeOfSrc, JsonSerializationContext context) { String low = src.getLower().toString(); String high = src.getUpper().toString(); if (src.isUpperUnbounded()) high = "*"; if (src.getLower().equals(src.getUpper())) { return new JsonPrimitive(low); } else { return new JsonPrimitive(low + ".." + high); } } // FIXME: finish and test this... public Interval<Integer> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { String multiplicityString = json.getAsJsonPrimitive().getAsString(); throw new NotImplementedException(); //return new Interval<Integer>() ; } } /** * This is another ugly temporary hack (possibly wrongfully) assuming that Interval<Integer> is only used * for multiplicity in the archetype objects. Based on this the interval is converted to a Sequence on the * format [lower, upper], e.g. [0,5] or [1,*]. Even if lower and upper are equal both are output, e.g. [1,1] * When using the MULTIPLICITY_INTERVAL in ADL/AOM1.5 instead of Interval<Integer>, then this assumption * will not be needed and the converter can operate safely. */ class IntervalConverterSequenceFormat implements JsonSerializer<Interval<Integer>>, JsonDeserializer<Interval<Integer>> { public JsonElement serialize(Interval<Integer> src, Type typeOfSrc, JsonSerializationContext context) { JsonArray ja = new JsonArray(); ja.add(new JsonPrimitive(src.getLower())); if (src.isUpperUnbounded()) { ja.add(new JsonPrimitive('*')); } else { ja.add(new JsonPrimitive(src.getUpper())); } return ja; } // FIXME: finish and test this... public Interval<Integer> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonArray multiplicityArray = json.getAsJsonArray(); throw new NotImplementedException(); //return new Interval<Integer>() ; } } class DvDateTimeConverter implements JsonSerializer<DvDateTime>, JsonDeserializer<DvDateTime> { public JsonElement serialize(DvDateTime src, Type typeOfSrc, JsonSerializationContext context) { return new JsonPrimitive(src.getDateTime().toDateTimeISO().toString()); } // TODO: finish and test this... public DvDateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { String timestring = json.getAsJsonPrimitive().getAsString(); return new DvDateTime(timestring); } } // class ArchetypeTermConverter implements JsonSerializer<ArchetypeTerm>{ //, JsonDeserializer<ArchetypeTerm> { // public JsonElement serialize(ArchetypeTerm src, Type typeOfSrc, JsonSerializationContext context) { // return new JsonPrimitive(src.getItems()); // } // //// // TODO: finish and test this... //// public CodePhrase deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) //// throws JsonParseException { //// String[] split = json.getAsJsonPrimitive().getAsString().split("::"); //// return new CodePhrase(split[0],split[1]); //// } // } /** * Output given archetype as string in ADL format * * @param archetype * @return a string in ADL format * @throws IOException */ public String output(Archetype archetype, boolean cADLforDefinition, FlowStyle flowstyle) throws IOException { StringWriter writer = new StringWriter(); output(archetype, writer, cADLforDefinition, flowstyle); return writer.toString(); } /** * Output archetype DEFINITION as string in ADL format * * @param archetype * @return a string in ADL format * @throws IOException */ public String outputDefinitionOnly(Archetype archetype) throws IOException { StringWriter writer = new StringWriter(); printDefinition(archetype.getDefinition(), writer); return writer.toString(); } /** * Output given archetype to outputStream * * @param archetype * @param out * @throws IOException */ public void output(Archetype archetype, OutputStream out, boolean cADLforDefinition) throws IOException { Writer writer = new BufferedWriter(new OutputStreamWriter(new BufferedOutputStream(out), encoding)); output(archetype, writer, cADLforDefinition, FlowStyle.BLOCK); } /** * Output given archetype to writer * * @param archetype * @param out * @param flowstyle TODO * @throws IOException */ public void output(Archetype archetype, Writer out, boolean cADLforDefinition, FlowStyle flowstyle) throws IOException { Map<String, Object> archetypeAsMap = new LinkedHashMap<String, Object>(); //Linked to preserve ordering archetypeAsMap.put("adl_version", archetype.getAdlVersion()); archetypeAsMap.put("archetype_id", archetype.getArchetypeId().getValue()); if (archetype.getUid() != null) archetypeAsMap.put("uid", archetype.getUid().getValue()); archetypeAsMap.put("concept", archetype.getConcept()); archetypeAsMap.put("original_language", archetype.getOriginalLanguage()); archetypeAsMap.put("translations", archetype.getTranslations()); if (archetype.getParentArchetypeId() != null) { archetypeAsMap.put("parent_archetype_id", archetype.getParentArchetypeId()); } /* archetypeAsMap.put("description", archetype.getDescription()); */ if (cADLforDefinition) { StringWriter sw = new StringWriter(); //lineSeparator = "\n"; printCComplexObject(archetype.getDefinition(), 1, sw); String swStr = sw.toString(); //.replace("\n", ""+'\n'); // System.out.println("AOMtoYAMLSerializer.output()---------------"); // System.out.println(swStr); // System.out.println("AOMtoYAMLSerializer.output()---------------"); archetypeAsMap.put("definition", swStr); } else { archetypeAsMap.put("definition", archetype.getDefinition()); } archetypeAsMap.put("ontology", archetype.getOntology()); archetypeAsMap.put("invariants", archetype.getInvariants()); archetypeAsMap.put("is_controlled", archetype.isControlled()); /// GSON //String archetypeAsJsonString = gson.toJson(archetypeAsMap).replace("node_i_d:", "node_id:"); /// Jackson //String archetypeAsJsonString = mapper.writeValueAsString(archetype); //String archetypeAsJsonString = mapper.writeValueAsString(archetype.getDefinition()); String archetypeAsJsonString = mapper.writeValueAsString(archetypeAsMap); System.out.println("*** JacksonBasedAOMtoJSONandYAML.output() - using Jackson! ***"); if (doYaml) { // Without YAML typing: Object niceObjectTree = yaml.load(archetypeAsJsonString); //yaml.dump(niceObjectTree, out); // With experimental YAML typing: Tag rootTag = new Tag("http://www.openehr.org/releases/1.0.2/class/openehr.am.archetype.ARCHETYPE"); //TODO: Define real tag out.append(yaml.dumpAs(niceObjectTree, rootTag, flowstyle)); // yaml.dump(archetypeAsMap, out); } else { out.append(archetypeAsJsonString); } out.flush(); out.close(); } protected String convert(Object input) { return gson.toJson(input); } protected void printHeader(String adlVersion, ArchetypeID id, ArchetypeID parentId, String conceptCode, Writer out) throws IOException { out.write("archetype"); if (StringUtils.isNotEmpty(adlVersion)) { out.write(" (adl_version="); out.write(adlVersion); out.write(")"); } newline(out); indent(1, out); out.write(id.toString()); newline(out); if (parentId != null) { out.write("specialize"); newline(out); indent(1, out); out.write(parentId.toString()); newline(out); } newline(out); out.write("concept"); newline(out); indent(1, out); out.write("[" + conceptCode + "]"); newline(out); } protected void printLanguage(AuthoredResource authored, Writer out) throws IOException { out.write("language"); newline(out); indent(1, out); out.write("original_language = <"); out.write("["); out.write(authored.getOriginalLanguage().getTerminologyId().getValue()); out.write("::"); out.write(authored.getOriginalLanguage().getCodeString()); out.write("]"); out.write(">"); newline(out); if (authored.getTranslations() != null) { indent(1, out); out.write("translations = <"); newline(out); Map<String, TranslationDetails> translations = authored.getTranslations(); for (String lang : translations.keySet()) { TranslationDetails td = translations.get(lang); indent(2, out); out.write("[\""); out.write(lang); out.write("\"] = <"); newline(out); indent(3, out); out.write("language = <"); out.write("["); out.write(td.getLanguage().getTerminologyId().getValue()); out.write("::"); out.write(td.getLanguage().getCodeString()); out.write("]"); out.write(">"); newline(out); indent(3, out); out.write("author = <"); newline(out); printMap(td.getAuthor(), out, 4); indent(3, out); out.write(">"); newline(out); if (td.getAccreditation() != null) { indent(3, out); out.write("accreditation = <\""); out.write(td.getAccreditation()); out.write("\">"); newline(out); } if (td.getOtherDetails() != null) { indent(3, out); out.write("other_details = <"); newline(out); printMap(td.getOtherDetails(), out, 4); indent(3, out); out.write(">"); newline(out); } indent(2, out); out.write(">"); newline(out); } indent(1, out); out.write(">"); newline(out); } } protected void printMap(Map<String, String> map, Writer out, int indent) throws IOException { if (map == null || map.size() == 0) { return; } for (String key : map.keySet()) { indent(indent, out); out.write("[\""); out.write(key); out.write("\"] = <\""); out.write(map.get(key)); out.write("\">"); newline(out); } } protected void printDescription(ResourceDescription description, Writer out) throws IOException { if (description == null) { return; } out.write("description"); newline(out); indent(1, out); out.write("original_author = <"); newline(out); Map<String, String> map = description.getOriginalAuthor(); for (String key : map.keySet()) { indent(2, out); out.write("[\"" + key + "\"] = <\"" + map.get(key) + "\">"); newline(out); } indent(1, out); out.write(">"); newline(out); indent(1, out); out.write("lifecycle_state = <\""); out.write(description.getLifecycleState()); out.write("\">"); newline(out); indent(1, out); out.write("details = <"); newline(out); for (ResourceDescriptionItem item : description.getDetails()) { printDescriptionItem(item, 2, out); } indent(1, out); out.write(">"); newline(out); } protected void printDescriptionItem(ResourceDescriptionItem item, int indent, Writer out) throws IOException { indent(indent, out); out.write("[\""); out.write(item.getLanguage().getCodeString()); out.write("\"] = <"); newline(out); indent(indent + 1, out); out.write("language = <"); out.write("["); out.write(item.getLanguage().getTerminologyId().getValue()); out.write("::"); out.write(item.getLanguage().getCodeString()); out.write("]>"); newline(out); printNoneEmptyString("purpose", item.getPurpose(), indent + 1, out); printNoneEmptyStringList("keywords", item.getKeywords(), indent + 1, out); printNoneEmptyString("copyright", item.getCopyright(), indent + 1, out); printNoneEmptyString("use", item.getUse(), indent + 1, out); printNoneEmptyString("misuse", item.getMisuse(), indent + 1, out); printNoneEmptyStringMap("original_resource_uri", item.getOriginalResourceUri(), indent + 1, out); // other details not printed indent(indent, out); out.write(">"); newline(out); } private void printNoneEmptyString(String label, String value, int indent, Writer out) throws IOException { if (StringUtils.isEmpty(value)) { return; } indent(indent, out); out.write(label); out.write(" = <\""); out.write(value); out.write("\">"); newline(out); } private void printNoneEmptyStringList(String label, List<String> list, int indent, Writer out) throws IOException { if (list == null || list.isEmpty()) { return; } indent(indent, out); out.write(label); out.write(" = <"); for (int i = 0, j = list.size(); i < j; i++) { out.write("\""); out.write(list.get(i)); out.write("\""); if (i != j - 1) { out.write(","); } } out.write(">"); newline(out); } private void printNoneEmptyStringMap(String label, Map<String, String> map, int indent, Writer out) throws IOException { if (map == null || map.isEmpty()) { return; } indent(indent, out); out.write(label); out.write(" = <"); newline(out); for (String key : map.keySet()) { indent(2, out); out.write("[\"" + key + "\"] = <\"" + map.get(key) + "\">"); newline(out); } indent(indent, out); out.write(">"); newline(out); } protected void printDefinition(CComplexObject definition, Writer out) throws IOException { out.write("definition"); newline(out); printCComplexObject(definition, 1, out); } protected void printCComplexObject(CComplexObject ccobj, int indent, Writer out) throws IOException { // TODO skip c_obj with [0,0] occurrences Interval<Integer> occurrences = ccobj.getOccurrences(); if (occurrences != null && (Integer.valueOf(0).equals(occurrences.getLower())) && (Integer.valueOf(0).equals(occurrences.getUpper()))) { return; } // print rmTypeName and nodeId indent(indent, out); out.write(ccobj.getRmTypeName()); if (StringUtils.isNotEmpty(ccobj.getNodeId())) { out.write("[" + ccobj.getNodeId() + "]"); } printOccurrences(ccobj.getOccurrences(), out); out.write(" matches {"); // print all attributes if (!ccobj.isAnyAllowed()) { for (CAttribute cattribute : ccobj.getAttributes()) { printCAttribute(cattribute, indent + 1, out); } newline(out); indent(indent, out); } else { out.write("*"); } out.write("}"); newline(out); } protected void printOccurrences(Interval<Integer> occurrences, Writer out) throws IOException { Interval<Integer> defaultOccurrences = new Interval<Integer>(1, 1); if (occurrences == null || defaultOccurrences.equals(occurrences)) { return; } if (occurrences != null) { out.write(" occurrences matches {"); if (occurrences.getLower() == null) { out.write("*"); } else { out.write(Integer.toString(occurrences.getLower())); } out.write(".."); if (occurrences.getUpper() == null) { out.write("*"); } else { out.write(Integer.toString(occurrences.getUpper())); } out.write("}"); } } protected void printArchetypeInternalRef(ArchetypeInternalRef ref, int indent, Writer out) throws IOException { indent(indent, out); out.write("use_node "); out.write(ref.getRmTypeName()); printOccurrences(ref.getOccurrences(), out); out.write(" "); out.write(ref.getTargetPath()); newline(out); } protected void printArchetypeSlot(ArchetypeSlot slot, int indent, Writer out) throws IOException { indent(indent, out); out.write("allow_archetype "); out.write(slot.getRmTypeName()); if (StringUtils.isNotEmpty(slot.getNodeId())) { out.write("[" + slot.getNodeId() + "]"); } printOccurrences(slot.getOccurrences(), out); out.write(" matches {"); if (slot.isAnyAllowed()) { out.write("*}"); } else { if (slot.getIncludes() != null) { printAssertions(slot.getIncludes(), "include", indent, out); } if (slot.getExcludes() != null) { printAssertions(slot.getExcludes(), "exclude", indent, out); } newline(out); indent(indent, out); out.write("}"); } newline(out); } private void printAssertions(Set<Assertion> assertions, String purpose, int indent, Writer out) throws IOException { if (assertions == null) { return; } newline(out); indent(indent + 1, out); out.write(purpose); for (Assertion assertion : assertions) { if (assertion.getStringExpression() == null) { continue; } newline(out); indent(indent + 2, out); // FIXME: The string expression is null when an archetype is parsed, but after the archetype is recreated in the archetype // editor, the string expression exists. Please provide a valid string expression from the parser since it's _much_ easier to // maintain this line of code instead of adding hundreds of lines just to output some expressions, operators etc. // Opening an archetype directly in the ADL format view will show the output of the parsed archetype in this way: // // include // null out.write(assertion.getStringExpression()); } } protected void printCAttribute(CAttribute cattribute, int indent, Writer out) throws IOException { newline(out); indent(indent, out); out.write(cattribute.getRmAttributeName()); if (!CAttribute.Existence.REQUIRED.equals(cattribute.getExistence())) { out.write(" "); } printExistence(cattribute.getExistence(), out); if (cattribute instanceof CMultipleAttribute) { CMultipleAttribute cma = (CMultipleAttribute) cattribute; if (cma.getCardinality() != null) { out.write(" "); printCardinality(cma.getCardinality(), out); } } List<CObject> children = cattribute.getChildren(); out.write(" matches {"); if (children == null || children.size() == 0) { out.write("*"); } else if (children.size() != 1 || !(children.get(0) instanceof CPrimitiveObject)) { newline(out); for (CObject cobject : cattribute.getChildren()) { printCObject(cobject, indent + 1, out); } indent(indent, out); } else { CObject child = children.get(0); printCPrimitiveObject((CPrimitiveObject) child, out); } out.write("}"); } protected void printExistence(CAttribute.Existence existence, Writer out) throws IOException { if (CAttribute.Existence.REQUIRED.equals(existence)) { return; } out.write("existence matches "); if (CAttribute.Existence.OPTIONAL.equals(existence)) { out.write("{0..1}"); } else { out.write("{0}"); } } protected void printCObject(CObject cobj, int indent, Writer out) throws IOException { // print specialised types if (cobj instanceof CDomainType) { printCDomainType((CDomainType) cobj, indent, out); } else if (cobj instanceof CPrimitiveObject) { printCPrimitiveObject((CPrimitiveObject) cobj, out); } else if (cobj instanceof CComplexObject) { printCComplexObject((CComplexObject) cobj, indent, out); } else if (cobj instanceof ArchetypeInternalRef) { printArchetypeInternalRef((ArchetypeInternalRef) cobj, indent, out); } else if (cobj instanceof ArchetypeSlot) { printArchetypeSlot((ArchetypeSlot) cobj, indent, out); } else if (cobj instanceof ConstraintRef) { printConstraintRef((ConstraintRef) cobj, indent, out); } } protected void printConstraintRef(ConstraintRef ref, int indent, Writer out) throws IOException { indent(indent, out); out.write("["); out.write(ref.getReference()); out.write("]"); newline(out); } protected void printCardinality(Cardinality cardinality, Writer out) throws IOException { out.write("cardinality matches {"); Interval<Integer> interval = cardinality.getInterval(); if (interval != null) { if (interval.isLowerUnbounded()) { out.write("*"); } else { out.write(interval.getLower().toString()); } out.write(".."); if (interval.isUpperUnbounded()) { out.write("*"); } else { out.write(interval.getUpper().toString()); } } else { out.write("*"); } out.write("; "); if (cardinality.isOrdered()) { out.write("ordered"); } else { out.write("unordered"); } if (cardinality.isUnique()) { out.write("; unique"); } out.write("}"); } protected void printCDomainType(CDomainType cdomain, int indent, Writer out) throws IOException { if (cdomain instanceof CDvOrdinal) { printCDvOrdinal((CDvOrdinal) cdomain, indent, out); } else if (cdomain instanceof CDvQuantity) { printCDvQuantity((CDvQuantity) cdomain, indent, out); } else if (cdomain instanceof CCodePhrase) { printCCodePhrase((CCodePhrase) cdomain, indent, out); } // unknow CDomainType } protected void printCCodePhrase(CCodePhrase ccoded, int indent, Writer out) throws IOException { indent(indent, out); if (ccoded.isAnyAllowed()) { out.write("C_CODE_PHRASE <"); newline(out); indent(indent, out); out.write(">"); newline(out); return; } if (ccoded.getTerminologyId() != null) { out.write("[" + ccoded.getTerminologyId().getValue() + "::"); } if (ccoded.getCodeList() != null) { if (ccoded.getCodeList().size() > 1) { newline(out); for (int i = 0, j = ccoded.getCodeList().size(); i < j; i++) { if (j > 1) { indent(indent, out); } out.write(ccoded.getCodeList().get(i)); if (i != j - 1) { out.write(","); } else { if (ccoded.hasAssumedValue()) { out.write(";"); newline(out); indent(indent, out); out.write(ccoded.getAssumedValue().getCodeString()); } out.write("]"); } newline(out); } } else { out.write(ccoded.getCodeList().get(0)); if (ccoded.hasAssumedValue()) { out.write(";" + ccoded.getAssumedValue().getCodeString()); } out.write("]"); newline(out); } } else { out.write("]"); newline(out); } } protected void printCDvOrdinal(CDvOrdinal cordinal, int indent, Writer out) throws IOException { // if the list is null, the CDvOrdinal is not further constrained // (other than that it is a CDvOrdinal) if (cordinal.isAnyAllowed()) { indent(indent, out); out.write("C_DV_ORDINAL <"); newline(out); indent(indent, out); out.write(">"); newline(out); } else { for (Iterator<Ordinal> it = cordinal.getList().iterator(); it.hasNext();) { Ordinal ordinal = it.next(); indent(indent, out); printOrdinal(ordinal, out); if (it.hasNext()) { out.write(","); } else if (cordinal.hasAssumedValue()) { out.write(";"); } newline(out); } if (cordinal.hasAssumedValue()) { printOrdinal(cordinal.getAssumedValue(), out); newline(out); } } } protected void printOrdinal(Ordinal ordinal, Writer out) throws IOException { CodePhrase symbol = ordinal.getSymbol(); out.write(Integer.toString(ordinal.getValue())); out.write("|["); out.write(symbol.getTerminologyId().getValue()); out.write("::"); out.write(symbol.getCodeString()); out.write("]"); } protected void printCDvQuantity(CDvQuantity cquantity, int indent, Writer out) throws IOException { indent(indent, out); out.write("C_DV_QUANTITY <"); newline(out); indent(indent + 1, out); CodePhrase property = cquantity.getProperty(); if (property != null) { out.write("property = <["); out.write(property.getTerminologyId().getValue()); out.write("::"); out.write(property.getCodeString()); out.write("]>"); } List<CDvQuantityItem> list = cquantity.getList(); if (list != null) { newline(out); indent(indent + 1, out); out.write("list = <"); newline(out); int index = 1; for (CDvQuantityItem item : list) { indent(indent + 2, out); out.write("[\""); out.write(Integer.toString(index)); out.write("\"] = <"); newline(out); indent(indent + 3, out); out.write("units = <\""); out.write(item.getUnits()); out.write("\">"); newline(out); Interval<Double> value = item.getMagnitude(); if (value != null) { indent(indent + 3, out); out.write("magnitude = <"); printInterval(value, out); out.write(">"); newline(out); } Interval<Integer> precision = item.getPrecision(); if (precision != null) { indent(indent + 3, out); out.write("precision = <"); printInterval(precision, out); out.write(">"); newline(out); } index++; indent(indent + 2, out); out.write(">"); newline(out); } indent(indent + 1, out); out.write(">"); newline(out); } if (cquantity.getAssumedValue() != null) { newline(out); indent(indent + 1, out); out.write("assumed_value = <"); newline(out); printDvQuantity(cquantity.getAssumedValue(), indent + 1, out); indent(indent + 1, out); out.write(">"); newline(out); } indent(indent, out); out.write(">"); newline(out); } protected void printDvQuantity(DvQuantity quantity, int indent, Writer out) throws IOException { indent(indent + 1, out); printUnits(quantity.getUnits(), out); newline(out); if (quantity.getMagnitude() != null) { indent(indent + 1, out); out.write("magnitude = <"); out.write(quantity.getMagnitude().toString()); out.write(">"); newline(out); } indent(indent + 1, out); out.write("precision = <"); out.write(Integer.toString(quantity.getPrecision())); out.write(">"); newline(out); } protected void printUnits(String units, Writer out) throws IOException { out.write("units = <\""); out.write(units); out.write("\">"); } protected void printOntology(ArchetypeOntology ontology, Writer out) throws IOException { out.write("ontology"); newline(out); if (ontology.getTerminologies() != null) { indent(1, out); out.write("terminologies_available = <"); for (String terminology : ontology.getTerminologies()) { out.write("\""); out.write(terminology); out.write("\", "); } out.write("...>"); newline(out); } // *** Term definition section *** (ADL 1.4 spec 8.6.3) indent(1, out); out.write("term_definitions = <"); newline(out); List<OntologyDefinitions> termDefinitionsList = ontology.getTermDefinitionsList(); printDefinitionList(out, termDefinitionsList); indent(1, out); out.write(">"); newline(out); // *** Constraint definition section *** (ADL 1.4 spec 8.6.4) List<OntologyDefinitions> constraintDefinitionsList = ontology.getConstraintDefinitionsList(); if (constraintDefinitionsList != null) { indent(1, out); out.write("constraint_definitions = <"); newline(out); printDefinitionList(out, constraintDefinitionsList); indent(1, out); out.write(">"); newline(out); } // *** Term binding section *** (ADL 1.4 spec 8.6.5) if (ontology.getTermBindingList() != null) { indent(1, out); out.write("term_binding = <"); newline(out); for (int i = 0; i < ontology.getTermBindingList().size(); i++) { OntologyBinding bind = ontology.getTermBindingList().get(i); indent(2, out); out.write("[\""); out.write(bind.getTerminology()); out.write("\"] = <"); newline(out); indent(3, out); out.write("items = <"); newline(out); for (int j = 0; j < ontology.getTermBindingList().get(i).getBindingList().size(); j++) { TermBindingItem item = (TermBindingItem) ontology.getTermBindingList().get(i).getBindingList() .get(j); indent(4, out); out.write("[\""); out.write(item.getCode()); out.write("\"] = <"); out.write(item.getTerms().get(0)); if (item.getTerms().size() > 1) { for (int k = 1; k < item.getTerms().size(); k++) out.write("," + item.getTerms().get(k)); } out.write(">"); newline(out); } for (int l = 3; l > 1; l--) { indent(l, out); out.write(">"); newline(out); } } indent(1, out); out.write(">"); newline(out); } // *** Constraint binding section *** (ADL 1.4 spec 8.6.6) if (ontology.getConstraintBindingList() != null) { indent(1, out); out.write("constraint_binding = <"); newline(out); for (int i = 0; i < ontology.getConstraintBindingList().size(); i++) { OntologyBinding bind = ontology.getConstraintBindingList().get(i); indent(2, out); out.write("[\""); out.write(bind.getTerminology()); out.write("\"] = <"); newline(out); indent(3, out); out.write("items = <"); newline(out); for (int j = 0; j < ontology.getConstraintBindingList().get(i).getBindingList().size(); j++) { QueryBindingItem item = (QueryBindingItem) ontology.getConstraintBindingList().get(i) .getBindingList().get(j); indent(4, out); out.write("[\""); out.write(item.getCode()); out.write("\"] = <"); out.write(item.getQuery().getUrl()); out.write(">"); newline(out); } for (int l = 3; l > 1; l--) { indent(l, out); out.write(">"); newline(out); } } indent(1, out); out.write(">"); newline(out); } } private void printDefinitionList(Writer out, List<OntologyDefinitions> termDefinitionsList) throws IOException { for (OntologyDefinitions defs : termDefinitionsList) { indent(2, out); out.write("[\""); out.write(defs.getLanguage()); out.write("\"] = <"); newline(out); indent(3, out); out.write("items = <"); newline(out); for (ArchetypeTerm term : defs.getDefinitions()) { indent(4, out); out.write("[\""); out.write(term.getCode()); out.write("\"] = <"); newline(out); for (Map.Entry<String, String> entry : term.getItems().entrySet()) { indent(5, out); out.write(entry.getKey()); out.write(" = <\""); out.write(entry.getValue()); out.write("\">"); newline(out); } newline(out); indent(4, out); out.write(">"); newline(out); } for (int i = 3; i > 1; i--) { indent(i, out); out.write(">"); newline(out); } } } protected void printCPrimitiveObject(CPrimitiveObject cpo, Writer out) throws IOException { CPrimitive cp = cpo.getItem(); if (cp instanceof CBoolean) { printCBoolean((CBoolean) cp, out); } else if (cp instanceof CDate) { printCDate((CDate) cp, out); } else if (cp instanceof CDateTime) { printCDateTime((CDateTime) cp, out); } else if (cp instanceof CTime) { printCTime((CTime) cp, out); } else if (cp instanceof CDuration) { printCDuration((CDuration) cp, out); } else if (cp instanceof CInteger) { printCInteger((CInteger) cp, out); } else if (cp instanceof CReal) { printCReal((CReal) cp, out); } else if (cp instanceof CString) { printCString((CString) cp, out); } // unknow CPrimitive type } protected void printCBoolean(CBoolean cboolean, Writer out) throws IOException { if (cboolean.isTrueValid()) { out.write("true"); if (cboolean.isFalseValid()) { out.write(", false"); } } else { out.write("false"); } if (cboolean.hasAssumedValue()) { out.write("; "); if (cboolean.assumedValue().booleanValue()) { out.write("true"); } else { out.write("false"); } } } protected void printCDate(CDate cdate, Writer out) throws IOException { if (cdate.getPattern() != null) { out.write(cdate.getPattern()); } else if (cdate.getList() != null) { out.write(cdate.getList().get(0).toString()); } else { printInterval(cdate.getInterval(), out); } if (cdate.hasAssumedValue()) { out.write("; "); out.write(cdate.assumedValue().toString()); } } protected void printCDateTime(CDateTime cdatetime, Writer out) throws IOException { if (cdatetime.getPattern() != null) { out.write(cdatetime.getPattern()); } else if (cdatetime.getList() != null) { out.write(cdatetime.getList().get(0).toString()); } else { printInterval(cdatetime.getInterval(), out); } if (cdatetime.hasAssumedValue()) { out.write("; "); out.write(cdatetime.assumedValue().toString()); } } protected void printCTime(CTime ctime, Writer out) throws IOException { if (ctime.getPattern() != null) { out.write(ctime.getPattern()); } else if (ctime.getList() != null) { out.write(ctime.getList().get(0).toString()); } else { printInterval(ctime.getInterval(), out); } if (ctime.hasAssumedValue()) { out.write("; "); out.write(ctime.assumedValue().toString()); } } protected void printCDuration(CDuration cduration, Writer out) throws IOException { if (cduration.getValue() != null) { out.write(cduration.getValue().toString()); } else if (cduration.getPattern() != null) { out.write(cduration.getPattern()); } else { printInterval(cduration.getInterval(), out); } if (cduration.assumedValue() != null) { out.write("; "); out.write(cduration.assumedValue().toString()); } } protected void printCInteger(CInteger cinteger, Writer out) throws IOException { if (cinteger.getList() != null) { printList(cinteger.getList(), out); } else { printInterval(cinteger.getInterval(), out); } if (cinteger.assumedValue() != null) { out.write("; "); out.write(cinteger.assumedValue().toString()); } } protected void printCReal(CReal creal, Writer out) throws IOException { if (creal.getList() != null) { printList(creal.getList(), out); } else { printInterval(creal.getInterval(), out); } if (creal.assumedValue() != null) { out.write("; "); out.write(creal.assumedValue().toString()); } } protected void printCString(CString cstring, Writer out) throws IOException { if (cstring.getPattern() != null) { out.write("/" + cstring.getPattern() + "/"); } else if (cstring.getList() != null) { printList(cstring.getList(), out, true); } else if (cstring.defaultValue() != null) { out.write("\""); out.write(cstring.defaultValue()); out.write("\""); } if (cstring.hasAssumedValue()) { out.write("; "); out.write("\"" + cstring.assumedValue() + "\""); } } protected void printList(List list, Writer out) throws IOException { printList(list, out, false); } protected void printList(List list, Writer out, boolean string) throws IOException { for (int i = 0, j = list.size(); i < j; i++) { if (i != 0) { out.write(","); } if (string) { out.write("\""); } out.write(list.get(i).toString()); if (string) { out.write("\""); } } } protected void printInterval(Interval interval, Writer out) throws IOException { out.write("|"); if (interval.getLower() != null && interval.getUpper() != null) { if (interval.getLower().equals(interval.getUpper()) && interval.isLowerIncluded() && interval.isUpperIncluded()) { out.write(interval.getLower().toString()); } else { out.write(interval.getLower().toString()); out.write(".."); out.write(interval.getUpper().toString()); } } else if (interval.getLower() == null) { out.write("<"); if (interval.isUpperIncluded()) { out.write("="); } out.write(interval.getUpper().toString()); } else { out.write(">"); if (interval.isLowerIncluded()) { out.write("="); } out.write(interval.getLower().toString()); } out.write("|"); } private void newline(Writer out) throws IOException { out.write(lineSeparator); } private void indent(int level, Writer out) throws IOException { for (int i = 0; i < level; i++) { out.write(indent); } } /* charset encodings */ public static final Charset UTF8 = Charset.forName("UTF-8"); public static final Charset LATIN1 = Charset.forName("ISO-8859-1"); /* fields */ private Charset encoding; private String lineSeparator; private String indent; protected boolean doYaml; } /* * ***** BEGIN LICENSE BLOCK ***** Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the 'License'); you may not use this file except in compliance with the * License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an 'AS IS' basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for * the specific language governing rights and limitations under the License. * * The Original Code is ADLSerializer.java * * The Initial Developer of the Original Code is Rong Chen. Portions created by * the Initial Developer are Copyright (C) 2004-2007 the Initial Developer. All * Rights Reserved. * * Contributor(s): Mattias Forss, Johan Hjalmarsson, Erik Sundvall, * Sebastian Garde * * Software distributed under the License is distributed on an 'AS IS' basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for * the specific language governing rights and limitations under the License. * * ***** END LICENSE BLOCK ***** */