/******************************************************************************* * Copyright (c) 2012, 2013 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.objmap.graph.schema; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.exception.DatabaseException; import org.simantics.objmap.bidirectional.IBidirectionalMappingRule; import org.simantics.objmap.graph.annotations.CompoundRelatedGetValue; import org.simantics.objmap.graph.annotations.DynamicGraphType; import org.simantics.objmap.graph.annotations.GraphType; import org.simantics.objmap.graph.annotations.HasCollectionAdder; import org.simantics.objmap.graph.annotations.HasCollectionRemover; import org.simantics.objmap.graph.annotations.HasSetter; import org.simantics.objmap.graph.annotations.OptionalRelatedElements; import org.simantics.objmap.graph.annotations.OrderedElementsGet; import org.simantics.objmap.graph.annotations.OrderedSetType; import org.simantics.objmap.graph.annotations.RelatedElements; import org.simantics.objmap.graph.annotations.RelatedElementsGet; import org.simantics.objmap.graph.annotations.RelatedGetObj; import org.simantics.objmap.graph.annotations.RelatedGetValue; import org.simantics.objmap.graph.annotations.RelatedOrderedSetElements; import org.simantics.objmap.graph.annotations.RelatedValue; import org.simantics.objmap.graph.annotations.UpdateMethod; import org.simantics.objmap.graph.annotations.factories.CompoundRelatedGetSetValueRuleFactory; import org.simantics.objmap.graph.annotations.factories.OptionalRelatedElementsRuleFactory; import org.simantics.objmap.graph.annotations.factories.OrderedElementsRuleFactory; import org.simantics.objmap.graph.annotations.factories.RelatedElementsRuleFactory; import org.simantics.objmap.graph.annotations.factories.RelatedElementsRuleFactory2; import org.simantics.objmap.graph.annotations.factories.RelatedGetSetObjRuleFactory; import org.simantics.objmap.graph.annotations.factories.RelatedGetSetValueRuleFactory; import org.simantics.objmap.graph.annotations.factories.RelatedOrderedSetElementsRuleFactory; import org.simantics.objmap.graph.annotations.factories.RelatedValueRuleFactory; import org.simantics.objmap.graph.annotations.factories.UpdateMethodFactory; import org.simantics.objmap.graph.annotations.meta.IsClassRule; import org.simantics.objmap.graph.annotations.meta.IsCollectionRule; import org.simantics.objmap.graph.annotations.meta.IsFieldRule; import org.simantics.objmap.graph.annotations.meta.IsGetSetRule; import org.simantics.objmap.graph.annotations.meta.IsMethodRule; import org.simantics.objmap.graph.rules.factory.IClassRuleFactory; import org.simantics.objmap.graph.rules.factory.ICollectionRuleFactory; import org.simantics.objmap.graph.rules.factory.IFieldRuleFactory; import org.simantics.objmap.graph.rules.factory.IGetSetRuleFactory; import org.simantics.objmap.graph.rules.factory.IMethodRuleFactory; public class MappingSchemas { /** * Creates a new SimpleLinkType based on the annotations in the given class. * @throws IllegalAccessException * @throws InstantiationException * @see GraphType * @see RelatedValue */ public static SimpleLinkType fromAnnotations(ReadGraph g, Class clazz) throws DatabaseException, InstantiationException, IllegalAccessException { GraphType graphType = clazz.getAnnotation(GraphType.class); if (graphType != null) { ArrayList> rules = new ArrayList>(); collectRulesFromAnnotations(g, clazz, rules); return new SimpleLinkType(g.getResource(graphType.value()), clazz, rules); } DynamicGraphType dynamicType = clazz.getAnnotation(DynamicGraphType.class); if (dynamicType != null) { ArrayList> rules = new ArrayList>(); collectRulesFromAnnotations(g, clazz, rules); return new DynamicSimpleLinkType(g.getResource(dynamicType.value()), clazz, rules); } OrderedSetType orderedSetType = clazz.getAnnotation(OrderedSetType.class); if (orderedSetType != null) { ArrayList> rules = new ArrayList>(); collectRulesFromAnnotations(g, clazz, rules); return new OrderedSetSimpleLinkType(g.getResource(orderedSetType.value()), clazz, rules); } throw new IllegalArgumentException("Class " + clazz.toString() + " does not contain annotations."); } public static void collectRulesFromAnnotations(ReadGraph g, Class clazz, Collection> rules) throws DatabaseException, InstantiationException, IllegalAccessException { Class superclass = clazz.getSuperclass(); if(superclass != null) collectRulesFromAnnotations(g, superclass, rules); for(Annotation annotation : clazz.getAnnotations()) { IsClassRule tag = annotation.annotationType().getAnnotation(IsClassRule.class); if(tag!= null) { rules.add(createClassRule(g, annotation, clazz).create(g, annotation, clazz)); } } for(Field f : clazz.getDeclaredFields()) { f.setAccessible(true); for(Annotation annotation : f.getAnnotations()) { IsFieldRule tag = annotation.annotationType().getAnnotation(IsFieldRule.class); if(tag != null) { rules.add(createFieldRule(g, annotation, f).create(g, annotation, f)); } } } for(Method m : clazz.getDeclaredMethods()) { m.setAccessible(true); for(Annotation annotation : m.getAnnotations()) { IsMethodRule tag = annotation.annotationType().getAnnotation(IsMethodRule.class); if(tag != null) { rules.add(createMethodRule(g, annotation, m).create(g, annotation, m)); } } } for (Method m : clazz.getDeclaredMethods()) { m.setAccessible(true); for (Annotation annotation : m.getAnnotations()) { Class annotationType = annotation.annotationType(); IsGetSetRule tag = annotationType.getAnnotation(IsGetSetRule.class); if (tag != null) { HasSetter setterAnnType = annotationType.getAnnotation(HasSetter.class); Class setterAnn = setterAnnType.value(); Method getter = m; IGetSetRuleFactory ruleFactory = createGetSetRuleFactory(g, annotation, getter); Method setter = null; for (Method m2 : clazz.getDeclaredMethods()) { Annotation set = m2.getAnnotation(setterAnn); if (set != null && ruleFactory.isSetter(annotation, set)) setter = m2; } rules.add(ruleFactory.create(g, annotation, getter, setter)); } } } for (Method m : clazz.getDeclaredMethods()) { m.setAccessible(true); for (Annotation annotation : m.getAnnotations()) { Class annotationType = annotation.annotationType(); IsCollectionRule tag = annotationType.getAnnotation(IsCollectionRule.class); if (tag != null) { HasCollectionAdder adderAnnType = annotationType.getAnnotation(HasCollectionAdder.class); HasCollectionRemover removerAnnType = annotationType.getAnnotation(HasCollectionRemover.class); Class adderAnn = adderAnnType.value(); Class removerAnn = removerAnnType.value(); Method getter = m; ICollectionRuleFactory ruleFactory = createCollectionRuleFactory(g, annotation, getter); Method adder = null; Method remover = null; for (Method m2 : clazz.getDeclaredMethods()) { Annotation add = m2.getAnnotation(adderAnn); Annotation rem = m2.getAnnotation(removerAnn); if (add != null && ruleFactory.isAdder(annotation, add)) adder = m2; if (rem != null && ruleFactory.isRemover(annotation, rem)) remover = m2; } rules.add(ruleFactory.create(g, annotation, getter,adder,remover)); } } } } public static IClassRuleFactory createClassRule(ReadGraph g, Annotation annotation, Class clazz) { return null; } public static IFieldRuleFactory createFieldRule(ReadGraph g, Annotation annotation, Field field) { if (annotation.annotationType().equals(RelatedElements.class)) return new RelatedElementsRuleFactory(); if (annotation.annotationType().equals(RelatedValue.class)) return new RelatedValueRuleFactory(); if (annotation.annotationType().equals(OptionalRelatedElements.class)) return new OptionalRelatedElementsRuleFactory(); if (annotation.annotationType().equals(RelatedOrderedSetElements.class)) return new RelatedOrderedSetElementsRuleFactory(); return null; } public static IMethodRuleFactory createMethodRule(ReadGraph g, Annotation annotation, Method m) { if (annotation.annotationType().equals(UpdateMethod.class)) return new UpdateMethodFactory(); return null; } public static IGetSetRuleFactory createGetSetRuleFactory(ReadGraph g, Annotation annotation, Method getter) { if (annotation.annotationType().equals(RelatedGetValue.class)) return new RelatedGetSetValueRuleFactory(); if (annotation.annotationType().equals(RelatedGetObj.class)) return new RelatedGetSetObjRuleFactory(); if (annotation.annotationType().equals(CompoundRelatedGetValue.class)) return new CompoundRelatedGetSetValueRuleFactory(); return null; } public static ICollectionRuleFactory createCollectionRuleFactory(ReadGraph g, Annotation annotation, Method getter) { if (annotation.annotationType().equals(RelatedElementsGet.class)) return new RelatedElementsRuleFactory2(); if (annotation.annotationType().equals(OrderedElementsGet.class)) return new OrderedElementsRuleFactory(); return null; } /** * Creates a new SimpleLinkType based on the annotations in the given class. * @throws IllegalAccessException * @throws InstantiationException * @see GraphType * @see RelatedValue */ public static AdaptedLinkType fromAdaptable(ReadGraph g, String type, Class clazz) throws DatabaseException, InstantiationException, IllegalAccessException { return new AdaptedLinkType(g.getResource(type), clazz); } }