/* * Copyright (c) 2008, 2010, Zepheira All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the openrdf.org nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ package net.enilink.komma.generator.builder; import static java.util.Collections.singletonList; import java.io.FileNotFoundException; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.xml.namespace.QName; import net.enilink.composition.annotations.Iri; import net.enilink.komma.core.IEntity; import net.enilink.komma.core.URI; import net.enilink.komma.core.URIs; import net.enilink.komma.generator.JavaNameResolver; import net.enilink.komma.generator.concepts.CodeClass; import net.enilink.komma.generator.concepts.CodeOntology; import net.enilink.komma.generator.source.JavaClassBuilder; import net.enilink.komma.generator.source.JavaCommentBuilder; import net.enilink.komma.generator.source.JavaMethodBuilder; import net.enilink.komma.generator.source.JavaPropertyBuilder; import net.enilink.komma.generator.source.JavaSourceBuilder; import net.enilink.vocab.owl.DataRange; import net.enilink.vocab.owl.DeprecatedClass; import net.enilink.vocab.owl.DeprecatedProperty; import net.enilink.vocab.owl.Restriction; import net.enilink.vocab.owl.Thing; import net.enilink.vocab.rdf.Property; import net.enilink.vocab.rdfs.Class; import net.enilink.vocab.rdfs.Resource; public class JavaCodeBuilder { private static final String OWL = "http://www.w3.org/2002/07/owl#"; private static final String RDFS = "http://www.w3.org/2000/01/rdf-schema#"; private static final QName NOTHING = new QName(OWL, "Nothing"); private static final QName RESOURCE = new QName(RDFS, "Resource"); private static final QName LITERAL = new QName(RDFS, "Literal"); private JavaClassBuilder out; private JavaNameResolver resolver; public JavaCodeBuilder(JavaClassBuilder builder, JavaNameResolver resolver) throws FileNotFoundException { this.out = builder; this.resolver = resolver; } public void close() { out.close(); } public void packageInfo(CodeOntology ontology, String namespace) { comment(out, ontology); out.annotateStrings(Iri.class, singletonList(namespace)); out.pkg(resolver.getPackageName(URIs.createURI(namespace))); } public void interfaceHeader(CodeClass concept) { String pkg = resolver.getPackageName(concept.getURI()); String simple = resolver.getSimpleName(concept.getURI()); if (pkg != null) { out.pkg(pkg); } comment(out, concept); if (concept instanceof DeprecatedClass) { out.annotate(Deprecated.class); } List<URI> list = new ArrayList<URI>(); URI type = resolver.getType(concept.getURI()); if (type != null) { list.add(type); } // for (Class eq : concept.getOwlEquivalentClasses()) { // type = resolver.getType(eq.getURI()); // if (type != null) { // list.add(type); // } // } out.annotateURIs(Iri.class, list); // List<URI> oneOf = new ArrayList<URI>(); // if (concept.getOwlOneOf() != null) { // for (Object o : concept.getOwlOneOf()) { // if (o instanceof IEntity) { // oneOf.add(((IEntity) o).getURI()); // } // } // } // out.annotateQNames(oneOf.class, oneOf); // annotate(intersectionOf.class, concept.getOwlIntersectionOf()); // annotate(complementOf.class, concept.getOwlComplementOf()); // annotate(disjointWith.class, concept.getOwlDisjointWith()); out.interfaceName(simple); for (Class sups : concept.getRdfsSubClassOf()) { if (sups.getURI() == null || sups.equals(concept)) continue; String className = resolver.getClassName(sups.getURI()); if (!className.contains(".")) { // skip unknown classes without a package continue; } out.extend(className); } } public void classHeader(CodeClass datatype) { String pkg = resolver.getPackageName(datatype.getURI()); String simple = resolver.getSimpleName(datatype.getURI()); if (pkg != null) { out.pkg(pkg); } comment(out, datatype); URI type = resolver.getType(datatype.getURI()); out.annotateURI(Iri.class, type); out.className(simple); for (Class sups : datatype.getRdfsSubClassOf()) { if (sups.getURI() == null || sups.equals(datatype)) continue; out.extend(resolver.getClassName(sups.getURI())); } } public JavaCodeBuilder constants(CodeClass concept) { List<Object> oneOf = concept.getOwlOneOf(); if (oneOf != null) { List<String> names = new ArrayList<String>(oneOf.size()); for (Object one : oneOf) { if (one instanceof IEntity) { URI uri = ((IEntity) one).getURI(); String localPart = uri.localPart(); String name = localPart.replaceAll("^[^a-zA-Z]", "_") .replaceAll("\\W", "_").toUpperCase(); names.add(name); out.staticURIField(name, uri); } } if (!names.isEmpty()) { out.staticURIArrayField("URIS", names); } } return this; } public JavaCodeBuilder stringConstructor(CodeClass datatype) { String cn = resolver.getClassName(datatype.getURI()); String simple = resolver.getSimpleName(datatype.getURI()); JavaMethodBuilder method = out.staticMethod("valueOf"); method.returnType(cn); method.param(String.class.getName(), "value"); method.code("return new ").code(simple).code("(value);").end(); JavaMethodBuilder code = out.constructor(); code.param(String.class.getName(), "value"); code.code("super(value);").end(); return this; } public JavaCodeBuilder property(CodeClass dec, Property property) { JavaPropertyBuilder prop = out.property(getPropertyName(dec, property)); comment(prop, property); if (property instanceof DeprecatedProperty) { prop.annotate(Deprecated.class); } List<URI> list = new ArrayList<URI>(); URI type = resolver.getType(property.getURI()); if (type != null) { list.add(type); } // if (property instanceof OwlProperty) { // OwlProperty p = (OwlProperty) property; // for (Property eq : p.getOwlEquivalentProperties()) { // type = resolver.getType(eq.getURI()); // if (type != null) { // list.add(type); // } // } // } prop.annotateURIs(Iri.class, list); // list.clear(); // if (property instanceof SymmetricProperty) { // type = resolver.getType(property.getURI()); // if (type != null) { // list.add(type); // } // } // if (property instanceof CodeProperty) { // CodeProperty p = (CodeProperty) property; // for (Property eq : p.findAllInverseOfProperties()) { // type = resolver.getType(eq.getURI()); // if (type != null) { // list.add(type); // } // } // } // prop.annotateQNames(inverseOf.class, list); String className = getRangeClassName(dec, property); if (dec.isFunctional(property)) { prop.type(className); } else { prop.setOf(className); } prop.getter(); comment(prop, property); prop.end(); return this; } private void comment(JavaSourceBuilder out, Resource concept) { JavaCommentBuilder comment = out.comment(concept.getRdfsComment()); for (Object see : concept.getRdfsSeeAlso()) { if (see instanceof Class) { URI name = ((Class) see).getURI(); comment.seeAlso(resolver.getClassName(name)); } else if (see instanceof Property) { Property property = (Property) see; for (Class domain : property.getRdfsDomains()) { CodeClass cc = (CodeClass) domain; String cn = resolver.getClassName(domain.getURI()); String name = getPropertyName(cc, property); String range = getRangeClassName(cc, property); if ("boolean".equals(range)) { comment.seeBooleanProperty(cn, name); } else { comment.seeProperty(cn, name); } } } else { comment.seeAlso(see.toString()); } } if (concept instanceof Thing) { for (Object version : ((Thing) concept).getOwlVersionInfo()) { comment.version(version.toString()); } } comment.generated(); comment.end(); } private String getPropertyName(CodeClass code, Property param) { String propertyName; if (code.isFunctional(param)) { propertyName = resolver.getPropertyName(param.getURI()); } else { propertyName = resolver.getPluralPropertyName(param.getURI()); } // this ensures that getters and setters are renamed if the property has // a different range as for its super classes Collection<Class> overriddenRanges = code.getOverriddenRanges(param); Class range = code.getRange(param); if (range != null) { overriddenRanges.remove(range); } if (range != null && range.getURI() != null && !overriddenRanges.isEmpty()) { propertyName += "As" + resolver.getSimpleName(range.getURI()); } return propertyName; } private String getRangeClassName(CodeClass code, Property property) { CodeClass range = code.getRange(property); if (range == null) { return Object.class.getName(); } String type = null; if (range instanceof DataRange) { // TODO support XML Schema facets for (Object data : range.getOwlOneOf()) { type = data.getClass().getName(); } } else if (NOTHING.equals(range.getURI())) { return "void"; } else if (LITERAL.equals(range.getURI())) { return Object.class.getName(); } else if (RESOURCE.equals(range.getURI())) { return Object.class.getName(); } else if (range.getURI() != null) { type = resolver.getClassName(range.getURI()); } else { return Object.class.getName(); } BigInteger one = BigInteger.valueOf(1); for (Class c : code.getRdfsSubClassOf()) { if (c instanceof Restriction) { Restriction r = (Restriction) c; if (property.equals(r.getOwlOnProperty())) { if (one.equals(r.getOwlMaxCardinality()) && one.equals(r.getOwlMinCardinality()) || one.equals(r.getOwlCardinality())) { type = unwrap(type); } } } } return type; } private String unwrap(String type) { if (type.equals("java.lang.Character")) return "char"; if (type.equals("java.lang.Byte")) return "byte"; if (type.equals("java.lang.Short")) return "short"; if (type.equals("java.lang.Integer")) return "int"; if (type.equals("java.lang.Long")) return "long"; if (type.equals("java.lang.Float")) return "float"; if (type.equals("java.lang.Double")) return "double"; if (type.equals("java.lang.Boolean")) return "boolean"; return type; } }