org.drools.compiler.lang.ReflectiveVisitor Maven / Gradle / Ivy
The newest version!
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses 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 org.drools.compiler.lang;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Java Tip 98: Reflect on the Visitor design pattern. Implement visitors in
* Java, using reflection.
* http://www.javaworld.com/javaworld/javatips/jw-javatip98.html
*
* Michael Neale says: I really hate this code. Not really a helpful use
* of reflection, always annoys me.
*/
public abstract class ReflectiveVisitor
implements
Visitor {
protected static final transient Logger logger = LoggerFactory.getLogger(ReflectiveVisitor.class);
static final String newline = System.getProperty( "line.separator" );
private Map, Method> methodCache = new HashMap<>();
public void visit(final Object object) {
Method method = null;
try {
if ( object != null ) {
method = getMethod( object.getClass() );
method.invoke( this,
object);
} else {
method = getClass().getMethod( "visitNull",
(Class[]) null );
method.invoke( this,
(Object[]) null );
}
} catch ( Exception e ) {
throw new RuntimeException( e.toString() + " : " + object, e);
}
}
private Method getMethod(final Class> clazz) {
if (methodCacheContains(clazz)) {
return getMethodFromCache(clazz);
}
Class> newClazz = clazz;
Method method = null;
// Try the superclasses
while ( method == null && newClazz != Object.class ) {
String methodName = newClazz.getName();
methodName = "visit" + methodName.substring( methodName.lastIndexOf( '.' ) + 1 );
try {
method = getClass().getMethod(methodName,
newClazz);
} catch (final NoSuchMethodException e) {
newClazz = newClazz.getSuperclass();
}
}
// Try the interfaces.
if ( newClazz == Object.class ) {
final Class>[] interfaces = clazz.getInterfaces();
for ( int i = 0; i < interfaces.length && method == null; i++ ) {
String methodName = interfaces[i].getName();
methodName = "visit" + methodName.substring( methodName.lastIndexOf( '.' ) + 1 );
try {
method = getClass().getMethod(methodName,
interfaces[i]);
} catch (final NoSuchMethodException e) {
// swallow
}
}
}
if ( method == null ) {
try {
method = getClass().getMethod( "visitObject",
Object.class);
} catch ( final Exception e ) {
// Shouldn't happen as long as all Visitors extend this class
// and this class continues to implement visitObject(Object).
throw new RuntimeException( e.toString() + " : " + clazz, e.getCause() );
}
}
addMethodToCache(clazz, method);
return method;
}
public void visitObject(final Object object) {
logger.error("no visitor implementation for : " + object.getClass() + " : " + object);
}
private void addMethodToCache(Class> clazz, Method m) {
methodCache.put(clazz, m);
}
private Method getMethodFromCache(Class> clazz) {
return methodCache.get(clazz);
}
private boolean methodCacheContains(Class> clazz) {
return methodCache.containsKey(clazz);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy