package org.jboss.windup.graph; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Set; import java.util.logging.Logger; import org.jboss.windup.graph.model.WindupVertexFrame; import org.jboss.windup.util.Logging; import org.jboss.windup.util.exception.WindupException; import com.tinkerpop.blueprints.Element; import com.tinkerpop.blueprints.Vertex; import com.tinkerpop.frames.FramedGraph; import com.tinkerpop.frames.modules.MethodHandler; /** * Handles @SetInProperties Set<String,String>. * * @author <a href="mailto:ozizka@redhat.com">Ondrej Zizka</a> */ public class SetInPropertiesHandler implements MethodHandler<SetInProperties> { private static final Logger log = Logging.get(SetInPropertiesHandler.class); private static final String SET_VERTEX_PROP_VALUE = "1"; @Override public Class<SetInProperties> getAnnotationType() { return SetInProperties.class; } /** * The handling method. */ @Override public Object processElement(Object frame, Method method, Object[] args, SetInProperties ann, FramedGraph<?> framedGraph, Element elm) { String methodName = method.getName(); if (methodName.startsWith("get")) return handleGetter((Vertex) elm, method, args, ann, framedGraph); else if (methodName.startsWith("set")) handleSetter((Vertex) elm, method, args, ann, framedGraph); else if (methodName.startsWith("addAll")) handleAddAll((Vertex) elm, method, args, ann, framedGraph); else if (methodName.startsWith("add")) handleAdder((Vertex) elm, method, args, ann, framedGraph); else throw new WindupException("Only get*, set*, add*, and addAll* method names are supported for @" + SetInProperties.class.getSimpleName() + ", found at: " + method.getName()); return frame; } /** * Getter */ private Set<String> handleGetter(Vertex vertex, Method method, Object[] args, SetInProperties ann, FramedGraph<?> framedGraph) { if (args != null && args.length != 0) throw new WindupException("Method must take zero arguments"); Set<String> set = new HashSet<>(); String prefix = preparePrefix(ann); Set<String> keys = vertex.getPropertyKeys(); for (String key : keys) { String tail = key; if (!prefix.isEmpty()) { if(!key.startsWith(prefix)) continue; else tail = key.substring(prefix.length()); } set.add(tail); } return set; } /** * Setter */ private void handleSetter(Vertex vertex, Method method, Object[] args, SetInProperties ann, FramedGraph<?> framedGraph) { // Argument. if (args == null || args.length != 1) throw new WindupException("Method must take one argument: " + method.getName()); if (!(args[0] instanceof Set)) throw new WindupException("Argument of " + method.getName() + " must be a Set<String>, but is: " + args[0].getClass()); @SuppressWarnings("unchecked") Set<String> newSet = (Set<String>) args[0]; String prefix = preparePrefix(ann); // For all keys in the old set... Set<String> vertKeys = vertex.getPropertyKeys(); for (String vertKey : vertKeys) { if (!vertKey.startsWith(prefix)) continue; if (WindupVertexFrame.TYPE_PROP.equals(vertKey)) // Leave the "type" property. continue; if (vertKey.startsWith("w:")) // Leave windup internal properties. TODO: Get the prefix from somewhere. continue; String subKey = vertKey.substring(prefix.length()); // ...either change to the new value, if (newSet.contains(subKey)) { vertex.setProperty(vertKey, SET_VERTEX_PROP_VALUE); newSet.remove(subKey); } // or remove the old. else vertex.removeProperty(vertKey); } // Add the new entries. for (String item : newSet) { if (!(item instanceof String)) throw new WindupException("Argument of " + method.getName() + " must be a Set<String>, but it contains: " + item.getClass()); vertex.setProperty(prefix + item, "1"); } } private void handleAdder(Vertex vertex, Method method, Object[] args, SetInProperties ann, FramedGraph<?> framedGraph) { if (args == null || args.length == 0) throw new WindupException("Method must take at least one String argument: " + method.getName()); String prefix = preparePrefix(ann); for (Object arg : args) { if (!(arg instanceof String)) throw new WindupException("The arguments of the add*() method " + method.getName() + " must be String, but was: " + arg.getClass()); vertex.setProperty(prefix + arg, SET_VERTEX_PROP_VALUE); } } /** * Adder */ private void handleAddAll(Vertex vertex, Method method, Object[] args, SetInProperties ann, FramedGraph<?> framedGraph) { if (args == null || args.length != 1) throw new WindupException("Method must take one String argument: " + method.getName()); String prefix = preparePrefix(ann); // Argument. @SuppressWarnings("unchecked") Set<String> set = (Set<String>) args[0]; // Store all set entries in vertex'es properties. for (String item : set) { vertex.setProperty(prefix + item, SET_VERTEX_PROP_VALUE); } } /** * Returns "<ann.propertyPrefix()><SEPAR>", for example, "set:"; or an empty string if the prefix is empty. */ private String preparePrefix(SetInProperties ann) { return "".equals(ann.propertyPrefix()) ? "" : (ann.propertyPrefix() + SetInProperties.SEPAR); } }