X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Fcanvas%2Fimpl%2FHintReflection.java;fp=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Fcanvas%2Fimpl%2FHintReflection.java;h=3edd342b70b13049c4c5ae9531a9207f890ce612;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/HintReflection.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/HintReflection.java new file mode 100644 index 000000000..3edd342b7 --- /dev/null +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/HintReflection.java @@ -0,0 +1,185 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 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.g2d.canvas.impl; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import org.simantics.utils.datastructures.hints.IHintListener; +import org.simantics.utils.datastructures.hints.IHintObservable; +import org.simantics.utils.datastructures.hints.IHintContext.Key; + +/** + * @author Toni Kalajainen + */ +public class HintReflection { + + private final static HintListenerDefinition[] EMPTY = new HintListenerDefinition[0]; + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public static @interface HintListener { + Class Class(); + String Field(); + } + + /** + * Scans an object for reflections of hint listeners + *

+ * Example: + * + * @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM") + * public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) { + * ... + * } + * @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM") + * public void hintRemoved(IHintObservable sender, Key key, Object oldValue) { + * ... + * } + * + * @param obj object to scan + * @return an array of painters and their priorities + */ + public static HintListenerDefinition[] getDependencies(final Object obj) + { + Map result = new HashMap(); + Class clazz = obj.getClass(); + _add(obj, clazz, result); + //if (result==null) return EMPTY; + return result.values().toArray(EMPTY); + } + + private static void _add(final Object obj, Class clazz, Map result) + { + try { + for (final Method m : clazz.getDeclaredMethods()) { + HintListener anno = (HintListener) m + .getAnnotation(HintListener.class); + if (anno == null) + continue; + + Class keyContainerClass = anno.Class(); + assert (keyContainerClass != null); + String fieldName = anno.Field(); + assert (fieldName != null); + Field field; + field = keyContainerClass.getField(fieldName); + assert (field != null); + field.setAccessible(true); + Object value = field.get(field != null); + assert (value != null); + assert (value instanceof Key); + Key key = (Key) value; + + Class returnType = m.getReturnType(); + assert (returnType == void.class); + Class[] params = m.getParameterTypes(); + assert (params.length == 4 || params.length == 3); + assert (params[0].equals(IHintObservable.class)); + assert (params[1].equals(Key.class)); + assert (params[2].equals(Object.class)); + + if (params.length == 4) + assert (params[3].equals(Object.class)); + + HintListenerDefinition def = result.get(key); + if (def==null) { + def = new HintListenerDefinition(key, obj); + result.put(key, def); + } + + m.setAccessible(true); + if (params.length == 4) + def.changedHandlerMethod = m; + else + def.removedHandlerMethod = m; + } + } catch (SecurityException e) { + throw new Error(e); + } catch (NoSuchFieldException e) { + throw new Error(e); + } catch (IllegalAccessException e) { + throw new Error(e); + } + /* + for (final Field f : clazz.getDeclaredFields()) { + Class c = f.getType(); + Dependency dep = (Dependency) f.getAnnotation(Dependency.class); + Reference ref = (Reference) f.getAnnotation(Reference.class); + if (dep==null && ref==null) continue; + assert(ICanvasParticipant.class.isAssignableFrom( c )); + assert(!(dep!=null && ref!=null)); + ReferenceDefinition rd = new ReferenceDefinition(); + rd.dependency = dep!=null; + rd.field = f; + rd.requirement = c; + f.setAccessible(true); + result.add(rd); + } + */ + + Class superClass = clazz.getSuperclass(); + if (superClass!=null) + _add(obj, superClass, result); + } + + + public final static class HintListenerDefinition implements IHintListener { + public final Key key; + public final Object object; + public Method changedHandlerMethod; + public Method removedHandlerMethod; + + public HintListenerDefinition(Key key, Object object) { + this.key = key; + this.object = object; + } + + @Override + public void hintChanged(IHintObservable sender, Key key, + Object oldValue, Object newValue) { + if (changedHandlerMethod==null) return; + try { + changedHandlerMethod.invoke(object, sender, key, oldValue, newValue); + } catch (IllegalArgumentException e) { + throw new Error(e); + } catch (IllegalAccessException e) { + throw new Error(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + @Override + public void hintRemoved(IHintObservable sender, Key key, Object oldValue) { + if (removedHandlerMethod==null) return; + try { + removedHandlerMethod.invoke(object, sender, key, oldValue); + } catch (IllegalArgumentException e) { + throw new Error(e); + } catch (IllegalAccessException e) { + throw new Error(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e.getCause()); + } + } + + + } + +}