/* Copyright 2008 the original author or authors. * * 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. * * This class is originally from the Grails project and was obtained from * * http://jira.codehaus.org/browse/GROOVY-2960 * * Changes: * * 2011-02-13 REC * - Made target protected so subclasses can access it. */ package org.dkpro.lab.groovy.task; import groovy.lang.Closure; /** * Skeleton implementation of a wrapper class for closures that allows you to intercept invocations * of the closure. The wrapper can be used anywhere that the target closure can be used. */ public abstract class AbstractClosureProxy extends Closure { private static final long serialVersionUID = -3406724476488622300L; protected Closure target; /** * Creates a new instance that wraps the target closure and sends profiling events to the given * profiler log. * * @param closure * The target closure to wrap. */ public AbstractClosureProxy(Closure closure) { super(closure.getOwner(), closure.getThisObject()); this.target = closure; } /** * This method is called before the target closure is invoked. This is a passive interceptor, so * you cannot prevent the call to the target closure. You can modify the arguments, though, but * it's not recommended unless you really know what you're doing. * * @param args * The arguments passed to the closure. */ protected abstract void doBeforeCall(Object[] args); /** * This method is called after the target closure is invoked. It will be triggered whether or * not an exception is thrown by the target closure. * * @param args * The arguments passed to the closure. */ protected abstract void doAfterCall(Object[] args); /** * Called when a new instance of the proxy needs to be created for the given closure. Usually * the implementation simply creates a new instance of the current class, copying over the * existing proxy properties: * * <pre> * return new MyClosureProxy(c, this.field1, ...) * </pre> * * @param c * The closure to wrap/proxy. */ protected abstract Closure createWrapper(Closure c); /** * This is the important one: logs entry and exit of the closure call. */ @Override public Object call(Object[] objects) { doBeforeCall(objects); try { return this.target.call(objects); } finally { doAfterCall(objects); } } /** * Compares based on identities, but unlike the standard implementation this one will return * <code>true</code> if the given object is the target closure for this wrapper as well. */ @Override public boolean equals(Object obj) { return this == obj || this.target == obj; } @Override public int hashCode() { return this.target.hashCode(); } @Override public Closure curry(Object[] objects) { return createWrapper(this.target.curry(objects)); } @Override public boolean isCase(Object o) { return this.target.isCase(o); } @Override public Closure asWritable() { return this.target.asWritable(); } @Override public Object getProperty(String property) { return this.target.getProperty(property); } @Override public void setProperty(String s, Object o) { this.target.setProperty(s, o); } @Override public int getMaximumNumberOfParameters() { return this.target.getMaximumNumberOfParameters(); } @SuppressWarnings("rawtypes") @Override public Class[] getParameterTypes() { return this.target.getParameterTypes(); } @Override public Object getDelegate() { return this.target.getDelegate(); } @Override public void setDelegate(Object o) { this.target.setDelegate(o); } @Override public int getDirective() { return this.target.getDirective(); } @Override public void setDirective(int i) { this.target.setDirective(i); } @Override public int getResolveStrategy() { return this.target.getResolveStrategy(); } @Override public void setResolveStrategy(int i) { this.target.setResolveStrategy(i); } }