All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.popper.fw.impl.PageObjectImplementation Maven / Gradle / Ivy

Go to download

Definition of the interfaces all Popper Framework implementations depend on

The newest version!
/*
 * Copyright [2013] [Michael Bulla, [email protected]]
 *
 * Licensed 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.popper.fw.impl;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javassist.util.proxy.MethodHandler;

import org.jgrapht.alg.CycleDetector;
import org.jgrapht.graph.DefaultDirectedGraph;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.traverse.TopologicalOrderIterator;
import org.popper.fw.annotations.ImplementedBy;
import org.popper.fw.annotations.RunAfter;
import org.popper.fw.annotations.RunBefore;
import org.popper.fw.interfaces.IAnnotationProcessor;
import org.popper.fw.interfaces.LocatorContextInformation;
import org.popper.fw.interfaces.ReEvalutateException;

public class PageObjectImplementation implements InvocationHandler, MethodHandler {
	protected final Class basicClass;

	protected final String name;

	protected final PageObjectImplementation parent;

	private Map, Object> extensions;
	
	private final AbstractPopperContext context;
	
	public PageObjectImplementation(AbstractPopperContext context, Class basicClass, String name,
			PageObjectImplementation parent) {
		this.context = context;
		this.extensions = new HashMap, Object>();
		this.basicClass = basicClass;
		this.parent = parent;
		this.name = name;
	}

//	@Override
	public Object invoke(Object self, Method thisMethod, Method proceed,
			Object[] args) throws Throwable {
		return invoke(self, thisMethod, args);
	}
	
	@SuppressWarnings({ "cast" })
//	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		if (method.getDeclaringClass() == ImplHolder.class) {
			return this;
		}
		
		String methodName = method.getName();
		if ("equals".equals(methodName)) {
			return equals(args[0]);
		} else if ("hashCode".equals(methodName)) {
			return hashCode();
		} else if ("toString".equals(methodName)) {
			return "[" + basicClass.getName() + "]";
		}
		
		boolean evaluate = true;
		Object result = null;
		while (evaluate) {
			evaluate = false;
			try {
				result = evaluateMethod(method, args);
			} catch (ReEvalutateException ree) {
				evaluate = true;
			}
		}
		
		return result;
	}

	protected Map, Object> createReolver() {
		Map, Object> resolver = new HashMap, Object>();
		resolver.put(PageObjectImplementation.class, this);
//		fillResolverWithParents(resolver, this);
		return resolver;
	}
	
//	private static void fillResolverWithParents(Map, Object> resolver, PageObjectImplementation po) {
//		resolver.put(po.basicClass, po.proxy);
//		if (po.parent != null) {
//			fillResolverWithParents(resolver, po.parent);
//		}
//
//	}

	@SuppressWarnings({ "rawtypes", "cast", "unchecked" })
	private Object evaluateMethod(Method method, Object[] args)
			throws ReEvalutateException {
		Object result = null;
		LocatorContextInformation info = new LocatorContextInformation(this, method, args, basicClass, context);
		boolean foundAction = false;
		for (Annotation annotation : getOrderedAnnotations(method)) {
			ImplementedBy annotationImpl = annotation.annotationType().getAnnotation(ImplementedBy.class);
			if (annotationImpl != null) {
				IAnnotationProcessor annotationProcessor = context.instantiateObject(annotationImpl.value());
				result = annotationProcessor.processAnnotation(annotation, info, result);
				foundAction = true;
			}
		}
		
		if (!foundAction) {
			throw new RuntimeException("couldnt find any implementation-rule for " + method);
		}
		return result;
	}
	
	private List getOrderedAnnotations(Method method) {
        DefaultDirectedGraph graph = 
        		new DefaultDirectedGraph(DefaultEdge.class);
        for (Annotation annotation : method.getAnnotations()) {
            graph.addVertex(annotation);
        }

        for (Annotation annotation : method.getAnnotations()) {
            Class thisClass = annotation.annotationType();
            
            RunAfter runAfterAnnotation = thisClass.getAnnotation(RunAfter.class);
            if (runAfterAnnotation != null) {
            	for (Class otherClass : runAfterAnnotation.value()) {
            		graph.addEdge(method.getAnnotation(otherClass), annotation);
            	}
            }

            RunBefore runBeforeAnnotation = thisClass.getAnnotation(RunBefore.class);
            if (runBeforeAnnotation != null) {
            	for (Class otherClass : runBeforeAnnotation.value()) {
            		graph.addEdge(annotation, method.getAnnotation(otherClass));
            	}
            }
        }

        return getOrderedReferences(graph);
    }

    private List getOrderedReferences(DefaultDirectedGraph g) {
        CycleDetector cycleDetector = new CycleDetector(g);
        if (cycleDetector.detectCycles()) {
            throw new CycleException(cycleDetector);
        }

        List ret = new ArrayList();
        TopologicalOrderIterator orderIterator = new TopologicalOrderIterator(g);
        while (orderIterator.hasNext()) {
            ret.add(orderIterator.next());
        }

        return ret;
    }
	
	public void addExtension(Object extension) {
		extensions.put(extension.getClass(), extension);
	}
	
	public T getExtension(Class clazz) {
		return clazz.cast(extensions.get(clazz));
	}
	
	public String getName() {
		return name;
	}

	public PageObjectImplementation getParent() {
		return parent;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy