/* * Beanfabrics Framework Copyright (C) by Michael Karneim, beanfabrics.org Use is subject to license terms. See * license.txt. */ package org.beanfabrics.model; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.UndeclaredThrowableException; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import org.beanfabrics.meta.MetadataRegistry; import org.beanfabrics.support.AnnotatedClassProcessor; import org.beanfabrics.support.AnnotatedFieldProcessor; import org.beanfabrics.support.AnnotatedMethodProcessor; import org.beanfabrics.support.AnnotationProcessor; import org.beanfabrics.support.Processor; import org.beanfabrics.support.PropertySupport; import org.beanfabrics.support.SupportUtil; import org.beanfabrics.util.ReflectionUtil; /** * @author Michael Karneim */ public class PMManager { private static final PMManager INSTANCE = new PMManager(); private final MetadataRegistry metadata = new MetadataRegistry(); private final Map<Class<?>, List<Member>> membersPerClass = new IdentityHashMap<Class<?>, List<Member>>(); public static void setup(PresentationModel model) { getInstance().processPresentationModel(model); } public static PMManager getInstance() { return INSTANCE; } private PMManager() { // } public MetadataRegistry getMetadata() { return this.metadata; } protected void processPresentationModel(PresentationModel model) { PropertySupport.get(model).setup(); // OperationSupport.get(model).setup(); // ServiceSupport.get(model).setup(); // ValidationSupport.get(model).setup(); // OnChangeSupport.get(model).setup(); Class cls = model.getClass(); List<Class> classes = ReflectionUtil.getAllClasses(cls); processClasses(model, classes); List<Member> members = membersPerClass.get(cls); if (members == null) { members = ReflectionUtil.getAllMembers(cls); members = SupportUtil.sortMembers(members); membersPerClass.put(cls, members); } processMembers(model, members); } private void processClasses(PresentationModel model, List<Class> classes) { for (Class cls : classes) { processClass(model, cls); } } private void processMembers(PresentationModel model, List<Member> members) { for (Member member : members) { if (member instanceof Field) { Field f = (Field)member; processField(model, f); } else if (member instanceof Method) { Method m = (Method)member; processMethod(model, m); } else { throw new Error("Unexpected Member type: " + member.getClass().getName()); } } } private void processClass(PresentationModel model, Class cls) { Annotation[] annos = cls.getAnnotations(); for (Annotation anno : annos) { processClassAnnotation(model, cls, anno); } } private void processField(PresentationModel model, Field field) { Annotation[] annos = field.getAnnotations(); for (Annotation anno : annos) { processFieldAnnotation(model, field, anno); } } private void processMethod(PresentationModel model, Method method) { Annotation[] annos = method.getAnnotations(); for (Annotation anno : annos) { processMethodAnnotation(model, method, anno); } } private void processClassAnnotation(PresentationModel model, Class cls, Annotation anno) { AnnotationProcessor proc = getProcessor(anno); if (proc == null) { return; } else if (proc instanceof AnnotatedClassProcessor) { call((AnnotatedClassProcessor)proc, model, cls, anno); } else { throw new IllegalStateException("Can't process annotation '" + anno.getClass().getName() + "' on class '" + cls.getName() + "' with processor '" + proc.getClass().getName() + "'"); } } private void processFieldAnnotation(PresentationModel model, Field field, Annotation anno) { AnnotationProcessor proc = getProcessor(anno); if (proc == null) { return; } else if (proc instanceof AnnotatedFieldProcessor) { call((AnnotatedFieldProcessor)proc, model, field, anno); } else { throw new IllegalStateException("Can't process annotation '" + anno.getClass().getName() + "' on field '" + field.getName() + "' of class '" + field.getDeclaringClass().getName() + "' with processor '" + proc.getClass().getName() + "'"); } } private void processMethodAnnotation(PresentationModel model, Method method, Annotation anno) { AnnotationProcessor proc = getProcessor(anno); if (proc == null) { return; } else if (proc instanceof AnnotatedMethodProcessor) { call((AnnotatedMethodProcessor)proc, model, method, anno); } else { throw new IllegalStateException("Can't process annotation '" + anno.getClass().getName() + "' on method '" + method.getName() + "' of class '" + method.getDeclaringClass().getName() + "' with processor '" + proc.getClass().getName() + "'"); } } private void call(AnnotatedClassProcessor proc, PresentationModel model, Class cls, Annotation anno) { proc.process(model, cls, anno); } private void call(AnnotatedFieldProcessor proc, PresentationModel model, Field field, Annotation anno) { proc.process(model, field, anno); } private void call(AnnotatedMethodProcessor proc, PresentationModel model, Method method, Annotation anno) { proc.process(model, method, anno); } private AnnotationProcessor getProcessor(Annotation anno) { try { Processor processor = anno.annotationType().getAnnotation(Processor.class); if (processor == null) { return null; } AnnotationProcessor result = (AnnotationProcessor)processor.value().newInstance(); return result; } catch (InstantiationException e) { throw new UndeclaredThrowableException(e); } catch (IllegalAccessException e) { throw new UndeclaredThrowableException(e); } } }