/* * Copyright (c) 2009 Mysema Ltd. * All rights reserved. * */ package com.mysema.rdfbean.beangen; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import javax.annotation.Nullable; import com.mysema.codegen.JavaWriter; import com.mysema.codegen.StringUtils; import com.mysema.codegen.model.SimpleType; import com.mysema.codegen.model.Type; import com.mysema.codegen.model.TypeCategory; import com.mysema.codegen.model.Types; import com.mysema.query.codegen.BeanSerializer; import com.mysema.query.codegen.EntityType; import com.mysema.query.codegen.Property; import com.mysema.query.codegen.SimpleSerializerConfig; import com.mysema.query.codegen.Supertype; import com.mysema.rdfbean.model.RDF; import com.mysema.rdfbean.model.RDFS; import com.mysema.rdfbean.model.UID; import com.mysema.rdfbean.object.ClassMappingImpl; import com.mysema.rdfbean.object.PredicateImpl; import com.mysema.rdfbean.object.Session; import com.mysema.rdfbean.owl.OWL; import com.mysema.rdfbean.owl.OWLClass; import com.mysema.rdfbean.owl.Restriction; import com.mysema.rdfbean.rdfs.RDFProperty; import com.mysema.rdfbean.rdfs.RDFSClass; /** * JavaBeanExporter provides JavaBean domain generation functionality * * @author tiwe * @version $Id$ */ public class JavaBeanExporter { private static final Pattern normalizePattern = Pattern.compile("[\\-]"); private final Set<String> exportNamespaces = new HashSet<String>(); private final Map<String, String> nsToPackage = new HashMap<String, String>(); private final Map<String, String> nsToClassPrefix = new HashMap<String, String>(); private final Map<String, String> nsToPropertyPrefix = new HashMap<String, String>(); private final Set<UID> localizedProperties = new HashSet<UID>(); private final Set<UID> propertyAsSet = new HashSet<UID>(); private final Set<UID> propertyAsList = new HashSet<UID>(); private final Map<UID, Type> uidToType = new HashMap<UID, Type>(); private boolean oneOfAsEnum = true; private boolean stripHasOff = true; private final List<UID> skippedSupertypes = Arrays.asList(OWL.Thing, RDFS.Resource); private final TypeMapping typeMapping; public JavaBeanExporter(boolean usePrimitives) { this.typeMapping = new TypeMapping(usePrimitives); } public JavaBeanExporter addClassPrefix(String ns, String prefix) { nsToClassPrefix.put(ns, prefix); return this; } public JavaBeanExporter addExportNamespaces(String... namespaces) { for (String ns : namespaces) { exportNamespaces.add(ns); } return this; } public JavaBeanExporter addLocalizedProperty(UID... properties) { for (UID property : properties) { localizedProperties.add(property); } return this; } public JavaBeanExporter addPackage(String ns, String packageName) { nsToPackage.put(ns, packageName); return this; } public JavaBeanExporter addPropertyAsList(UID... properties) { for (UID property : properties) { propertyAsSet.add(property); } return this; } public JavaBeanExporter addPropertyAsSet(UID... properties) { for (UID property : properties) { propertyAsList.add(property); } return this; } public JavaBeanExporter addPropertyPrefix(String ns, String prefix) { nsToPropertyPrefix.put(ns, prefix); return this; } EntityType createBeanType(RDFSClass<?> rdfType) { // type UID id = rdfType.getId().asURI(); String pkgName = getPackage(id); String simpleName = getClassName(id); Type type = new SimpleType(TypeCategory.ENTITY, pkgName + "." + simpleName, pkgName, id.getLocalName(), false, false); uidToType.put(id, type); EntityType entityType = new EntityType(type); entityType.addAnnotation(new ClassMappingImpl(id.getNamespace(), "", Object.class)); Map<RDFProperty, Property> properties = new HashMap<RDFProperty, Property>(); // iterate over properties for (RDFProperty rdfProperty : rdfType.getProperties()) { if (rdfProperty.getId().isURI()) { if (!properties.containsKey(rdfProperty)) { RDFSClass<?> range = null; if (!rdfProperty.getRange().isEmpty()) { range = rdfProperty.getRange().iterator().next(); } properties.put(rdfProperty, createProperty(entityType, id, rdfProperty, range)); } } } // iterate over supertypes for (RDFSClass<?> superType : rdfType.getSuperClasses()) { if (superType != null && !superType.equals(rdfType) && !skippedSupertypes.contains(superType.getId())) { // handle restriction if (superType instanceof Restriction) { handleRestriction(entityType, id, (Restriction) superType, properties); // handle other supertypes } else if (superType.getId().isURI()) { UID superTypeId = (UID) superType.getId(); entityType.addSupertype(new Supertype(getJavaType(superTypeId))); } } } // add properties to bean model for (Property property : properties.values()) { entityType.addProperty(property); } return entityType; } private EntityType createEnumType(RDFSClass<?> rdfType) { // EnumType enumType = new EnumType(classId, getPackage(classId), // getClassName(classId)); // for (Object object : rdfType.getOneOf()){ // if (object instanceof MappedResourceBase && // ((MappedResourceBase)object).getId().isURI()){ // UID id = (UID) ((MappedResourceBase)object).getId(); // enumType.addEnum(id.getLocalName()); // } // } // return enumType; // type UID id = rdfType.getId().asURI(); String pkgName = getPackage(id); String simpleName = getClassName(id); Type type = new SimpleType(TypeCategory.ENTITY, pkgName + "." + simpleName, pkgName, id.getLocalName(), false, false); uidToType.put(id, type); EntityType entityType = new EntityType(type); entityType.addAnnotation(new ClassMappingImpl(id.getNamespace(), "", Object.class)); return entityType; } private Property createProperty(EntityType entityType, UID entityId, RDFProperty rdfProperty, @Nullable RDFSClass<?> range) { UID propertyId = rdfProperty.getId().asURI(); Type propertyType = getPropertyType(rdfProperty, range); String propertyName = getPropertyName(propertyId); Property property = new Property(entityType, propertyName, propertyType); if (propertyId.getNamespace().equals(entityId.getNamespace())) { if (propertyName.equals(propertyId.getLocalName())) { property.addAnnotation(new PredicateImpl("", "", "", false)); } else { property.addAnnotation(new PredicateImpl("", "", propertyId.getLocalName(), false)); } } else { property.addAnnotation(new PredicateImpl("", propertyId, false)); } return property; } public void export(Session session, File targetFolder) throws IOException { List<EntityType> entityTypes = new ArrayList<EntityType>(); // collect entity types for (OWLClass owlClass : session.findInstances(OWLClass.class)) { if (owlClass.getId().isURI()) { EntityType entityType; if (oneOfAsEnum && !owlClass.getOneOf().isEmpty()) { entityType = createEnumType(owlClass); } else { entityType = createBeanType(owlClass); } entityTypes.add(entityType); } } // serialize BeanSerializer beanSerializer = new BeanSerializer(); beanSerializer.setPrintSupertype(true); for (EntityType entityType : entityTypes) { File folder = new File(targetFolder, entityType.getPackageName().replace('.', '/')); folder.mkdirs(); File javaFile = new File(folder, entityType.getSimpleName() + ".java"); javaFile.createNewFile(); Writer writer = new OutputStreamWriter(new FileOutputStream(javaFile), "UTF-8"); try { beanSerializer.serialize(entityType, SimpleSerializerConfig.DEFAULT, new JavaWriter(writer)); } finally { writer.close(); } } } private Type getJavaType(UID id) { Type type = uidToType.get(id); if (type == null) { String typePackage = getPackage(id); String typeName = getClassName(id); type = new SimpleType(TypeCategory.ENTITY, typePackage + "." + typeName, typePackage, typeName, false, false); uidToType.put(id, type); } return type; } private String getClassName(UID classId) { String localName = normalize(classId.getLocalName()); if (nsToClassPrefix.containsKey(classId.getNamespace())) { localName = nsToClassPrefix.get(classId.getNamespace()) + localName; } return localName; } private String getPackage(UID id) { if (nsToPackage.containsKey(id.getNamespace())) { return nsToPackage.get(id.getNamespace()); } else { throw new IllegalArgumentException("No package declared for " + id.getNamespace()); } } private String getPropertyName(UID propertyId) { String propertyName = normalize(propertyId.getLocalName()); if (nsToPropertyPrefix.containsKey(propertyId.getNamespace())) { propertyName = nsToPropertyPrefix.get(propertyId.getNamespace()) + StringUtils.capitalize(propertyName); } else if (stripHasOff && propertyName.startsWith("has") && propertyName.length() > 3) { propertyName = StringUtils.uncapitalize(propertyName.substring(3)); } return propertyName; } private Type getPropertyType(RDFProperty rdfProperty, @Nullable RDFSClass<?> range) { Type propertyType = typeMapping.getDefaultType(); if (localizedProperties.contains(rdfProperty.getId())) { propertyType = typeMapping.get(RDF.text); } else if (range != null) { if (typeMapping.containsKey(range.getId())) { propertyType = typeMapping.get(range.getId()); } else if (range.getId().isURI()) { UID id = (UID) range.getId(); String pkgName = getPackage(id); String simpleName = getClassName(id); propertyType = new SimpleType(TypeCategory.SIMPLE, pkgName + "." + simpleName, pkgName, simpleName, false, false); } } if (propertyAsList.contains(rdfProperty.getId())) { propertyType = new SimpleType(Types.LIST, propertyType); } else if (propertyAsSet.contains(rdfProperty.getId())) { propertyType = new SimpleType(Types.LIST, propertyType); } return propertyType; } private void handleRestriction(EntityType entityType, UID entityId, Restriction restriction, Map<RDFProperty, Property> properties) { if (restriction.getHasValue() != null) { return; } Collection<RDFProperty> rdfProperties = Collections.emptySet(); if (restriction.getOnProperty() != null) { rdfProperties = Collections.singleton(restriction.getOnProperty()); } else if (restriction.getOnProperties() != null && !restriction.getOnProperties().isEmpty()) { rdfProperties = restriction.getOnProperties(); } for (RDFProperty rdfProperty : rdfProperties) { // allValueForm Property property; if (restriction.getAllValuesFrom() != null && restriction.getAllValuesFrom().getId().isURI()) { RDFSClass<?> range = restriction.getAllValuesFrom(); if (properties.containsKey(rdfProperty)) { property = properties.get(rdfProperty); // property.setType(getPropertyType(rdfProperty, range)); } else { property = createProperty(entityType, entityId, rdfProperty, range); properties.put(rdfProperty, property); } } else { if (properties.containsKey(rdfProperty)) { property = properties.get(rdfProperty); } else { RDFSClass<?> range = null; if (!rdfProperty.getRange().isEmpty()) { range = rdfProperty.getRange().iterator().next(); } property = createProperty(entityType, entityId, rdfProperty, range); properties.put(rdfProperty, property); } } // FIXME // for (Integer cardinality : Arrays.asList( // restriction.getCardinality(), // restriction.getMinCardinality(), // restriction.getMaxCardinality())){ // if (cardinality != null){ // property.setMultipleValues(true); // } // } } } private String normalize(String str) { return normalizePattern.matcher(str).replaceAll("_"); } public JavaBeanExporter setDefaultType(Type type) { typeMapping.setDefaultType(type); return this; } public JavaBeanExporter setOneOfAsEnum(boolean b) { this.oneOfAsEnum = b; return this; } public JavaBeanExporter setStripHasOff(boolean b) { this.stripHasOff = b; return this; } }