/* * Copyright (c) 2010 Mysema Ltd. * All rights reserved. * */ package com.mysema.rdfbean.object; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import javax.annotation.Nullable; import com.mysema.commons.lang.Assert; import com.mysema.rdfbean.CORE; import com.mysema.rdfbean.annotations.ClassMapping; import com.mysema.rdfbean.annotations.MappedClasses; import com.mysema.rdfbean.model.RDF; import com.mysema.rdfbean.model.RDFS; import com.mysema.rdfbean.model.UID; import com.mysema.rdfbean.model.XSD; import com.mysema.rdfbean.owl.OWL; import com.mysema.rdfbean.xsd.ConverterRegistry; import com.mysema.rdfbean.xsd.ConverterRegistryImpl; import com.mysema.util.ClassPathUtils; /** * Default implementation of the Configuration interface * * @author sasa * */ public class DefaultConfiguration implements Configuration { private static final Set<String> buildinNamespaces = new HashSet<String>(); static { buildinNamespaces.add(RDF.NS); buildinNamespaces.add(RDFS.NS); buildinNamespaces.add(XSD.NS); buildinNamespaces.add(OWL.NS); buildinNamespaces.add(CORE.NS); } private final Set<MappedClass> mappedClasses = new LinkedHashSet<MappedClass>(); private final Set<Class<?>> polymorphicClasses = new HashSet<Class<?>>(); private final ConverterRegistry converterRegistry = new ConverterRegistryImpl(); private final MappedClassFactory mappedClassFactory; private final Set<String> restrictedResources = new HashSet<String>(buildinNamespaces); private final Map<UID, List<MappedClass>> type2classes = new HashMap<UID, List<MappedClass>>(); public DefaultConfiguration(@Nullable String defaultNamespace) { this.mappedClassFactory = new MappedClassFactory(defaultNamespace); } public DefaultConfiguration() { this((String) null); } public DefaultConfiguration(Class<?>... classes) { this((String) null); addClasses(classes); } public DefaultConfiguration(Package... packages) { this((String) null); addPackages(packages); } public DefaultConfiguration(@Nullable String defaultNamespace, Class<?>... classes) { this(defaultNamespace); addClasses(classes); } public DefaultConfiguration(@Nullable String defaultNamespace, Package... packages) { this(defaultNamespace); addPackages(packages); } public DefaultConfiguration(@Nullable String defaultNamespace, String... packages) { this(defaultNamespace); scanPackages(packages); } public final void addClasses(Class<?>... classes) { for (Class<?> clazz : classes) { if (clazz.getAnnotation(ClassMapping.class) != null) { MappedClass mappedClass = mappedClassFactory.getMappedClass(clazz); if (mappedClass.getUID() != null) { ClassMapping classMapping = clazz.getAnnotation(ClassMapping.class); if (clazz.isEnum() && !classMapping.parent().equals(Object.class)) { MappedClass parentClass = mappedClassFactory.getMappedClass(classMapping .parent()); for (Object constant : clazz.getEnumConstants()) { UID instance = new UID(mappedClass.getClassNs(), ((Enum) constant).name()); addClass(instance, parentClass); } } addClass(mappedClass.getUID(), mappedClass); } for (MappedClass superClass : mappedClass.getMappedSuperClasses()) { polymorphicClasses.add(superClass.getJavaClass()); } mappedClasses.add(mappedClass); } else { throw new IllegalArgumentException("No @ClassMapping annotation for " + clazz.getName()); } } } private void addClass(UID uid, MappedClass mappedClass) { List<MappedClass> classList = type2classes.get(uid); if (classList == null) { classList = new ArrayList<MappedClass>(); type2classes.put(uid, classList); } classList.add(mappedClass); } public final void addPackages(Package... packages) { for (Package pack : packages) { MappedClasses classes = pack.getAnnotation(MappedClasses.class); if (classes != null) { addClasses(classes.value()); } else { throw new IllegalArgumentException("No @MappedClasses annotation for " + pack.getName()); } } } @Override public boolean allowCreate(Class<?> clazz) { return true; } public boolean allowRead(MappedPath path) { // TODO filter unmapped types? return true; } @Override @Nullable public UID createURI(Object instance) { Class<?> clazz = instance.getClass(); UID context = getMappedClass(clazz).getContext(); if (context != null) { return new UID(context.getId() + "#", clazz.getSimpleName() + "-" + UUID.randomUUID().toString()); } return null; } @Override public ConverterRegistry getConverterRegistry() { return converterRegistry; } @Override public MappedClass getMappedClass(Class<?> javaClass) { return mappedClassFactory.getMappedClass(javaClass); } @Override public Set<MappedClass> getMappedClasses() { return mappedClasses; } public List<MappedClass> getMappedClasses(UID uid) { if (type2classes.containsKey(uid)) { return type2classes.get(Assert.notNull(uid, "uid")); } else { return Collections.emptyList(); } } public boolean isMapped(Class<?> clazz) { return clazz.getAnnotation(ClassMapping.class) != null; } public boolean isPolymorphic(Class<?> clazz) { return polymorphicClasses.contains(clazz); } @Override public boolean isRestricted(UID uid) { return restrictedResources.contains(uid.getId()) || restrictedResources.contains(uid.ns()); } public void scanPackages(Package... packages) { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); for (Package pkg : packages) { try { for (Class<?> cl : ClassPathUtils.scanPackage(classLoader, pkg)) { if (cl.getAnnotation(ClassMapping.class) != null) { addClasses(cl); } } } catch (IOException e) { throw new ConfigurationException(e); } } } public void scanPackages(String... packages) { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); for (String pkg : packages) { try { for (Class<?> cl : ClassPathUtils.scanPackage(classLoader, pkg)) { if (cl.getAnnotation(ClassMapping.class) != null) { addClasses(cl); } } } catch (IOException e) { throw new ConfigurationException(e); } } } }