1 package org.simantics.xml.sax;
\r
3 import java.io.FileNotFoundException;
\r
4 import java.io.PrintWriter;
\r
5 import java.io.StringWriter;
\r
6 import java.util.ArrayList;
\r
7 import java.util.LinkedHashSet;
\r
8 import java.util.List;
\r
9 import java.util.Set;
\r
11 import javax.xml.namespace.QName;
\r
13 import org.simantics.utils.datastructures.BijectionMap;
\r
14 import org.simantics.xml.sax.configuration.AttributeComposition;
\r
15 import org.simantics.xml.sax.configuration.Configuration;
\r
16 import org.simantics.xml.sax.configuration.IDReference;
\r
17 import org.w3._2001.xmlschema.Annotated;
\r
18 import org.w3._2001.xmlschema.Attribute;
\r
19 import org.w3._2001.xmlschema.AttributeGroup;
\r
20 import org.w3._2001.xmlschema.Element;
\r
21 import org.w3._2001.xmlschema.LocalComplexType;
\r
22 import org.w3._2001.xmlschema.LocalSimpleType;
\r
23 import org.w3._2001.xmlschema.NamedAttributeGroup;
\r
24 import org.w3._2001.xmlschema.OpenAttrs;
\r
25 import org.w3._2001.xmlschema.Restriction;
\r
26 import org.w3._2001.xmlschema.Schema;
\r
27 import org.w3._2001.xmlschema.SimpleType;
\r
28 import org.w3._2001.xmlschema.TopLevelAttribute;
\r
30 public class OntologyGenerator extends SchemaConversionBase {
\r
32 public OntologyGenerator(Configuration configuration) {
\r
33 super(configuration);
\r
36 String ontRoot = "ONT.";
\r
37 String commentTag = "//";
\r
40 String ontologyName;
\r
43 SchemaConverter converter;
\r
45 PrintWriter writer = null;
\r
51 public void createOntology(Schema schema, String ontologyName, String className, SchemaConverter converter) throws FileNotFoundException {
\r
52 this.schema = schema;
\r
53 this.converter = converter;
\r
54 this.ontologyName = ontologyName;
\r
55 this.className = className;
\r
57 // for (OpenAttrs attrs : schema.getIncludeOrImportOrRedefine()) {
\r
58 // if (attrs instanceof Annotation) {
\r
59 // Annotation ann = (Annotation)attrs;
\r
60 // for (Object o : ann.getAppinfoOrDocumentation()) {
\r
61 // if (o instanceof Documentation) {
\r
62 // Documentation doc = (Documentation)o;
\r
63 // } else if (o instanceof Appinfo) {
\r
64 // Appinfo info = (Appinfo)o;
\r
71 StringWriter stringWriter = null;
\r
72 if (converter.getOntologyFile() == null) {
\r
73 stringWriter = new StringWriter();
\r
74 writer = new PrintWriter(stringWriter);
\r
76 writer = new PrintWriter(converter.getOntologyFile());
\r
83 if (stringWriter != null)
\r
84 System.out.println(stringWriter.toString());
\r
87 protected void handle(Schema schema) {
\r
88 String parts[] = ontologyName.split("/");
\r
89 String name = parts[parts.length-1];
\r
90 ontRoot = name.substring(0, Math.min(3, name.length())).toUpperCase();
\r
91 String version = schema.getVersion();
\r
92 if (version == null)
\r
96 for (String s : converter.getHeader()) {
\r
97 writer.println(commentTag + " " + s);
\r
100 writer.println("L0 = <http://www.simantics.org/Layer0-1.1>");
\r
101 writer.println("XML = <http://www.simantics.org/XML-1.0>");
\r
103 writer.println(ontRoot + " = <" + ontologyName +"-"+ version+"> : L0.Ontology");
\r
104 writer.println(" @L0.new");
\r
105 writer.println(" L0.HasResourceClass \"" + className +"\"");
\r
110 // TODO : these could be created in separate base ontology.
\r
111 // writer.println(commentTag + " Built-in types");
\r
112 // writer.println();
\r
113 // writer.println(ontRoot+"XML : L0.Library");
\r
114 // writer.println(ontRoot+"XML.hasAttribute <R L0.HasProperty");
\r
115 // writer.println(ontRoot+"XML.hasID <R "+ontRoot+"XML.hasAttribute : L0.FunctionalRelation");
\r
116 // writer.println(" --> L0.String");
\r
117 // writer.println(ontRoot+"XML.ComplexType <T L0.Entity");
\r
118 // writer.println(ontRoot+"XML.hasComplexType <R L0.IsComposedOf");
\r
119 // writer.println(ontRoot+"XML.AttributeGroup <T L0.Entity");
\r
120 // writer.println(ontRoot+"XML.Element <T L0.Entity");
\r
121 // writer.println(ontRoot+"XML.hasElement <R L0.IsComposedOf");
\r
122 // writer.println(ontRoot+"XML.ElementList <T L0.List");
\r
123 // writer.println(ontRoot+"XML.hasElementList <R L0.IsComposedOf");
\r
124 // writer.println(ontRoot+"XML.hasOriginalElementList <R " + ontRoot+"XML.hasElementList");
\r
125 // writer.println(ontRoot+"XML.hasReference <R L0.IsRelatedTo");
\r
126 // writer.println(ontRoot+"XML.hasExternalReference <R L0.IsRelatedTo");
\r
127 // writer.println(" L0.InverseOf " + ontRoot+"XML.externalReferenceOf <R L0.IsRelatedTo");
\r
128 // writer.println();
\r
129 writer.println(ontRoot+"ComplexTypes : L0.Library");
\r
130 writer.println(ontRoot+"AttributeGroups : L0.Library");
\r
132 writer.println(commentTag + " Interpreted from schema");
\r
135 super.handle(schema);
\r
138 protected String getType(QName qtype) {
\r
139 String ontType = getL0TypeFromPrimitiveType(qtype);
\r
140 if (ontType != null)
\r
142 else if (isComplexTypeRef(qtype.getLocalPart()))
\r
143 return ontRoot+getComplexTypePrefix()+qtype.getLocalPart();
\r
144 else if (isElementRef(qtype.getLocalPart()))
\r
145 return ontRoot+qtype.getLocalPart();
\r
146 else if (qtype.getPrefix() != null && qtype.getPrefix().length() > 0) {
\r
147 return ontRoot+qtype.getPrefix()+qtype.getLocalPart();
\r
149 throw new RuntimeException("Reference to unknown type " + qtype.getLocalPart());
\r
153 protected void handle(TopLevelAttribute topLevelAttribute) {
\r
154 super.handle(topLevelAttribute);
\r
159 protected void handleSimpleType(SchemaObject topLevelSimpleType) {
\r
160 super.handleSimpleType(topLevelSimpleType);
\r
165 public static String getComplexTypePrefix() {
\r
166 return "ComplexTypes.";
\r
169 public static String getAttributeGroupPrefix() {
\r
170 return "AttributeGroups.";
\r
174 protected void handle(SchemaObject parent, SchemaElement indicator, List<SchemaElement> elements) {
\r
175 if (indicator.getType() == SchemaElement.ElementType.SEQUENCE || (indicator.getType() == SchemaElement.ElementType.CHOICE && indicator.getRestriction().many())) {
\r
176 for (SchemaElement e : elements) {
\r
177 handle(parent, indicator, e);
\r
179 } else if (indicator.getType() == SchemaElement.ElementType.CHOICE) {
\r
180 String name = getChoiceName(elements);
\r
181 boolean single = true;
\r
182 for (SchemaElement e : elements) {
\r
183 if (e.getRestriction().many()) {
\r
188 String relationName = ontRoot+getName(parent)+".has"+name;
\r
189 writer.print(relationName);
\r
191 List<String> types = new ArrayList<String>();
\r
192 for (SchemaElement e : elements) {
\r
193 Element localElement = e.getElement();
\r
194 QName refType = null;
\r
195 String type = null;
\r
197 if (localElement.getName() != null) {
\r
198 refType = localElement.getType();
\r
199 type = getL0TypeFromPrimitiveType(refType);
\r
200 } else if (localElement.getRef() != null) {
\r
201 refType = localElement.getRef();
\r
202 type = getL0TypeFromPrimitiveType(refType);
\r
204 if (type == null) {
\r
205 SchemaObject obj = getWithName(parent, refType.getLocalPart());
\r
206 types.add(ontRoot+getName(obj,"has"));
\r
209 if (types.size() > 0) {
\r
210 for (String type : types) {
\r
211 writer.print(" <R " + type);
\r
214 writer.print(" <R XML.hasElement");
\r
219 for (SchemaElement e : elements) {
\r
220 Element localElement = e.getElement();
\r
221 QName refType = null;
\r
222 String type = null;
\r
223 if (localElement.getName() != null) {
\r
224 refType = localElement.getType();
\r
225 type = getType(refType);
\r
226 } else if (localElement.getRef() != null) {
\r
227 refType = localElement.getRef();
\r
228 type = getType(refType);
\r
230 if (type != null) {
\r
231 writer.println(" --> " + type);
\r
235 writer.println(ontRoot+name+ "List <T XML.ElementList");
\r
236 if (types.size() == 0) {
\r
237 writer.println(relationName+ "List <R XML.hasElementList : L0.FunctionalRelation");
\r
239 writer.print(relationName+ "List");
\r
240 for (String type : types) {
\r
241 writer.print(" <R " + type+"List");
\r
243 writer.println(" : L0.FunctionalRelation");
\r
245 writer.println(" --> " + ontRoot+name+"List");
\r
254 //protected void handleIndicator(SchemaObject parent, SchemaElement indicator, SchemaElement element, boolean reference, String refName, QName refType) {
\r
255 protected void handleIndicator(SchemaObject parent, SchemaElement indicator, SchemaElement element, String refName, RefType refType) {
\r
256 if (refType != refType.Element) {
\r
257 QName referenceType = null;
\r
258 if (refType == RefType.Type) {
\r
259 referenceType = element.getElement().getType();
\r
260 //refName = element.getElement().getName()
\r
261 SchemaObject eObj = elements.get(element.getElement());
\r
262 if (refName == null)
\r
263 refName = eObj.getName();
\r
265 referenceType = element.getElement().getRef();
\r
266 if (refName == null)
\r
267 refName = referenceType.getLocalPart();
\r
269 String type = getL0TypeFromPrimitiveType(referenceType);
\r
270 SchemaObject obj = null;
\r
271 if (type == null) {
\r
272 obj = getWithName(parent, referenceType.getLocalPart());
\r
274 writer.println(ontRoot+getName(parent)+".has"+refName + " <R " + ontRoot+ getName(obj,"has"));
\r
275 writer.println(" --> " + ontRoot+getName(obj));
\r
277 writer.println(ontRoot+getName(parent)+".has"+refName + " <R XML.hasElement");
\r
278 writer.println(" --> " + getType(referenceType));
\r
281 if (useElementList(parent, indicator,element, refType == RefType.Reference, refName, referenceType)) {
\r
283 if (type == null) {
\r
284 writer.println(ontRoot+getName(parent)+"."+refName + "List <T XML.ElementList");
\r
285 writer.println(ontRoot+getName(parent)+".has"+refName + "List <R " + ontRoot+getName(obj,"has")+"List : L0.FunctionalRelation");
\r
287 writer.println(ontRoot+getName(parent)+"."+refName + "List <T XML.ElementList");
\r
288 writer.println(ontRoot+getName(parent)+".has"+refName + "List <R XML.hasElementList : L0.FunctionalRelation");
\r
292 Element attrs = element.getElement();
\r
293 SchemaObject obj = getWithObj(parent, attrs);
\r
294 if (refName == null)
\r
295 refName = obj.getName();
\r
297 writer.println(ontRoot+getName(parent)+".has"+refName + " <R " + ontRoot+ getName(obj,"has"));
\r
298 writer.println(" --> " + ontRoot+getName(obj));
\r
299 if (useElementList(parent, indicator,element, false, refName, new QName(obj.getName()))) {
\r
300 writer.println(ontRoot+getName(parent)+"."+refName + "List <T XML.ElementList");
\r
301 writer.println(ontRoot+getName(parent)+".has"+refName + "List <R " + ontRoot+getName(obj,"has")+"List : L0.FunctionalRelation");
\r
308 protected void handleIndicator(SchemaObject parent, SchemaElement indicator, SchemaElement any) {
\r
313 protected void handle(SchemaObject parent, Attribute attribute) {
\r
314 String name = attribute.getName();
\r
315 QName primitiveType = attribute.getType();
\r
316 LocalSimpleType simpleType = attribute.getSimpleType();
\r
317 QName ref = attribute.getRef();
\r
319 String relationName;
\r
320 String relationType;
\r
321 if (name != null) {
\r
322 relationName = ontRoot+"has"+name;
\r
323 if (parent != null)
\r
324 relationName = ontRoot+getName(parent)+".has"+name;
\r
325 relationType = "XML.hasAttribute";
\r
327 else if (ref != null && parent != null) {
\r
328 relationName = ontRoot+getName(parent)+".has"+ref.getLocalPart();
\r
329 relationType = ontRoot+"has"+ref.getLocalPart();
\r
331 throw new RuntimeException();
\r
333 boolean id = false;
\r
334 String ontType = null;
\r
335 if (primitiveType != null) {
\r
336 ontType = getL0TypeFromPrimitiveType(primitiveType);
\r
337 if (ontType != null) {
\r
338 id = getTypeEntry(primitiveType).id;
\r
340 relationType = "XML.hasID";
\r
344 } else if (simpleType != null){
\r
345 Restriction restriction = simpleType.getRestriction();
\r
346 if (restriction == null || simpleType.getUnion() != null || simpleType.getName() != null || simpleType.getId() != null)
\r
347 throw new RuntimeException();
\r
348 QName base = restriction.getBase();
\r
351 ontType = getL0TypeFromPrimitiveType(base);
\r
353 // for (Object facetWrap : restriction.getFacets()) {
\r
354 // JAXBElement<?> element = (JAXBElement<?>)facetWrap;
\r
355 // QName elementName = element.getName();
\r
356 // Facet facet = (Facet)element.getValue();
\r
362 writer.println(relationName+ " <R " + relationType + ": L0.FunctionalRelation");
\r
364 // no need to add range restriction
\r
365 } else if (ontType != null) {
\r
366 writer.println(" --> " + ontType);
\r
367 } else if (primitiveType != null) {
\r
368 writer.println(" <R "+ontRoot+"has"+primitiveType.getLocalPart());
\r
373 protected void handleAttributes(SchemaObject simpleTypeObj) {
\r
374 // SchemaObject parent = simpleTypeObj.getParent();
\r
375 // SimpleType simpleType = simpleTypeObj.getSimpleType();
\r
376 // Restriction restriction = simpleType.getRestriction();
\r
377 // QName base = restriction.getBase();
\r
378 // String ontType = getL0TypeFromPrimitiveType(base);
\r
382 protected void handle(SchemaObject parent, AttributeGroup attributeGroup) {
\r
383 if (parent == null) {
\r
384 NamedAttributeGroup group = (NamedAttributeGroup)attributeGroup;
\r
385 writer.println(ontRoot+getAttributeGroupPrefix()+group.getName()+ " <T XML.AttributeGroup");
\r
386 SchemaObject obj = new SchemaObject(parent,attributeGroup);
\r
387 for (Annotated annotated : group.getAttributeOrAttributeGroup()) {
\r
388 if (annotated instanceof Attribute) {
\r
389 //handle(getAttributeGroupPrefix()+group.getName(),(Attribute)annotated);
\r
390 handle(obj,(Attribute)annotated);
\r
391 } else if (annotated instanceof AttributeGroup) {
\r
392 throw new RuntimeException("Cannot handle nested attribute groups");
\r
396 writer.println(ontRoot+getName(parent) +" L0.Inherits " + ontRoot + getAttributeGroupPrefix() + attributeGroup.getRef().getLocalPart());
\r
402 protected void handleAttributeComposition(SchemaObject parent, AttributeComposition composition, BijectionMap<org.simantics.xml.sax.configuration.Attribute, Annotated> attributes) {
\r
403 Attribute compositionAttribute = new Attribute();
\r
404 compositionAttribute.setName(composition.getName());
\r
405 QName type = new QName(CONVERSION_NS, composition.getType());
\r
406 compositionAttribute.setType(type);
\r
407 handle(parent, compositionAttribute);
\r
411 protected void handleSimpleType(SchemaObject parent, SchemaObject simpleTypeObj) {
\r
412 SimpleType simpleType = simpleTypeObj.getSimpleType();
\r
413 String name = simpleType.getName();
\r
415 org.w3._2001.xmlschema.List list = simpleType.getList();
\r
416 if (list != null) {
\r
417 // TODO : process restriction in lists
\r
418 String relationName = ontRoot+"has"+name;
\r
419 if (parent != null)
\r
420 relationName = ontRoot+getName(parent)+".has"+name;
\r
421 writer.println(relationName+ " <R XML.hasAttribute : L0.FunctionalRelation");
\r
423 String ontType = getL0Type(new QName(SCHEMA_NS, "string"));
\r
424 writer.println(" --> " + ontType);
\r
426 Restriction restriction = simpleType.getRestriction();
\r
427 if (restriction == null || simpleType.getUnion() != null || simpleType.getId() != null)
\r
428 throw new RuntimeException(simpleType.getName() + " restriction error");
\r
429 QName base = restriction.getBase();
\r
431 String relationName = ontRoot+"has"+name;
\r
432 if (parent != null)
\r
433 relationName = ontRoot+getName(parent)+".has"+name;
\r
435 writer.println(relationName+ " <R XML.hasAttribute : L0.FunctionalRelation");
\r
437 String ontType = getL0Type(base);
\r
438 writer.println(" --> " + ontType);
\r
443 protected void handleComplexType(SchemaObject topLevelComplexType) {
\r
444 String name = getName(topLevelComplexType);
\r
445 if (name.contains("Pcurve"))
\r
446 System.out.println();
\r
447 // if (parent != null)
\r
448 // name = parent +"_"+name;
\r
450 String relationName = ontRoot+getName(topLevelComplexType,"has");//ontRoot+"has"+name;
\r
452 writer.println(relationName+ " <R XML.hasComplexType");
\r
453 writer.println(relationName+ "List <R XML.hasElementList");
\r
454 //writer.println(" --> " + ontRoot+getComplexTypePrefix()+name);
\r
455 writer.println(" --> " + ontRoot+name);
\r
457 String baseType = "XML.ComplexType";
\r
459 QName base = getComplexTypeBase(topLevelComplexType.getComplexType());
\r
460 if (base != null) {
\r
461 baseType = getType(base);
\r
463 base = getSimpleTypeBase(topLevelComplexType.getSimpleType());
\r
464 if (base != null) {
\r
465 baseType = getType(base);
\r
467 //writer.println(ontRoot+getComplexTypePrefix()+name+ " <T "+baseType);
\r
468 writer.println(ontRoot+name+ " <T "+baseType);
\r
469 super.handleComplexType(topLevelComplexType);
\r
474 protected void handleElement(SchemaObject elementObj) {
\r
475 Element element = elementObj.getElement();
\r
476 String name = getName(elementObj);//element.getName();
\r
478 if ("Text".equals(name))
\r
479 System.out.println();
\r
481 String type = "XML.Element";
\r
482 Set<String> types = new LinkedHashSet<String>();
\r
483 if (element.getType() != null) {
\r
484 types.add(getType(element.getType()));
\r
486 QName base = getElementBase(element);
\r
487 if (base != null) {
\r
488 if (base.getNamespaceURI().equals(SCHEMA_NS)) {
\r
489 String l0Type = getL0Type(base);
\r
490 if (l0Type == null)
\r
491 throw new RuntimeException("Cannot get L0 type for " + base.getLocalPart());
\r
493 } else if (isElementRef(base.getLocalPart()))
\r
494 types.add(ontRoot+base.getLocalPart());
\r
496 types.add(ontRoot+getComplexTypePrefix()+base.getLocalPart());
\r
498 QName substitution = element.getSubstitutionGroup();
\r
499 if (substitution != null) {
\r
500 if (isElementRef(substitution.getLocalPart()))
\r
501 types.add(ontRoot+substitution.getLocalPart());
\r
503 types.add( ontRoot+getComplexTypePrefix()+substitution.getLocalPart());
\r
505 for (String t : types) {
\r
506 type += " <T " + t;
\r
509 String relationName = ontRoot+getName(elementObj,"has");//ontRoot+"has"+name;
\r
510 // if (elementObj.getParent() != null) {
\r
511 // //relationName = ontRoot+getComplexTypePrefix()+"has"+name.substring(getComplexTypePrefix().length());
\r
512 // relationName = ontRoot+getName(elementObj.getParent()) + "has"+element.getName();
\r
514 writer.println(relationName+ " <R XML.hasElement");
\r
515 writer.println(relationName+ "List <R XML.hasElementList");
\r
517 writer.println(ontRoot+name+ " <T "+type);
\r
519 LocalComplexType complexType = element.getComplexType();
\r
520 LocalSimpleType simpleType = element.getSimpleType();
\r
522 if (complexType != null) {
\r
523 SchemaObject complexTypeObj = complexTypes.get(complexType);
\r
524 handleElementComplexTypeAttributes(complexTypeObj);
\r
525 handleComplexTypeExtension(complexTypeObj);
\r
526 } else if (simpleType != null) {
\r
527 SchemaObject simpleTypeObj = simpleTypes.get(simpleType);
\r
528 handleElementSimpleTypeAttributes(simpleTypeObj);
\r
531 List<IDReference> references = getIDReferences(element);
\r
533 for (IDReference ref : references) {
\r
534 writer.println(ontRoot+name+"."+ref.getReference().getName()+ " <R XML.hasReference");
\r
540 public static String getName(SchemaObject obj) {
\r
541 if (obj.getParent() == null) {
\r
542 switch (obj.getType()) {
\r
544 return getComplexTypePrefix()+obj.getName();
\r
546 return obj.getName();
\r
547 case ATTRIBUTE_GROUP:
\r
548 return getAttributeGroupPrefix()+obj.getName();
\r
550 return obj.getName();
\r
553 SchemaObject o = obj;
\r
554 SchemaObject prev = null;
\r
557 if (o.getName() != null)
\r
558 name = o.getName()+"."+name;
\r
562 name = name.substring(0, name.length()-1);
\r
563 switch (prev.getType()) {
\r
565 return getComplexTypePrefix()+name;
\r
568 case ATTRIBUTE_GROUP:
\r
569 return getAttributeGroupPrefix()+name;
\r
574 throw new RuntimeException();
\r
578 public static String getName(SchemaObject obj, String rel) {
\r
579 if (obj.getParent() == null) {
\r
580 switch (obj.getType()) {
\r
582 return getComplexTypePrefix()+rel+obj.getName();
\r
584 return rel+obj.getName();
\r
585 case ATTRIBUTE_GROUP:
\r
586 return getAttributeGroupPrefix()+rel+obj.getName();
\r
588 return rel+obj.getName();
\r
591 SchemaObject o = obj;
\r
592 SchemaObject prev = null;
\r
595 if (o.getName() != null)
\r
596 name = o.getName()+"."+name;
\r
600 name = name.substring(0, name.length()-1);
\r
601 switch (prev.getType()) {
\r
603 return getComplexTypePrefix()+rel+name;
\r
606 case ATTRIBUTE_GROUP:
\r
607 return getAttributeGroupPrefix()+rel+name;
\r
612 throw new RuntimeException();
\r