/** * Copyright 2015 Santhosh Kumar Tekuri * * The JLibs authors license this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package jlibs.core.graph.visitors; import jlibs.core.graph.Sequence; import jlibs.core.graph.Visitor; import jlibs.core.graph.sequences.IterableSequence; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; /** * @author Santhosh Kumar T */ public abstract class ReflectionVisitor<E, R> implements Visitor<E, R>{ private Map<Class<?>, Method> methodMap = new HashMap<Class<?>, Method>(); private Sequence<Class<?>> seq; private void sort(){ Class clazz = getClass(); do{ for(Method method: clazz.getDeclaredMethods()){ if(method.getName().equals("process")){ Class<?>[] params = method.getParameterTypes(); if(params.length==1 && !methodMap.containsKey(params[0])){ methodMap.put(params[0], method); method.setAccessible(true); } } } clazz = clazz.getSuperclass(); }while(clazz!=null); seq = new IterableSequence<Class<?>>(ClassSorter.sort(methodMap.keySet())); } public void generateCode(){ if(seq==null) sort(); else seq.reset(); for(Class<?> clazz; (clazz=seq.next())!=null;){ System.out.print(" "); if(seq.index()!=0) System.out.print("else "); System.out.format("if(elem instanceof %s)%n", clazz.getSimpleName()); System.out.format(" return process((%s)elem);%n", clazz.getSimpleName()); } System.out.println(" else"); System.out.println(" return getDefault(elem);"); } @Override @SuppressWarnings({"unchecked"}) public R visit(E elem){ if(elem!=null){ if(seq==null) sort(); else seq.reset(); for(Class<?> clazz; (clazz=seq.next())!=null;){ if(clazz.isAssignableFrom(elem.getClass())){ try{ return (R)methodMap.get(clazz).invoke(this, elem); }catch(Exception ex){ throw new RuntimeException(ex); } } } } return getDefault(elem); } protected abstract R getDefault(Object elem); }