001/*
002 * JPPF.
003 * Copyright (C) 2005-2018 JPPF Team.
004 * http://www.jppf.org
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.jppf.client.taskwrapper;
020
021import java.util.concurrent.Callable;
022
023import org.jppf.JPPFException;
024import org.jppf.node.protocol.*;
025
026/**
027 * JPPF task wrapper for an object whose class is annotated with {@link org.jppf.node.protocol.JPPFRunnable JPPFRunnable}.
028 * @author Laurent Cohen
029 */
030public class JPPFAnnotatedTask extends AbstractTask<Object> implements CancellationHandler {
031  /**
032   * Explicit serialVersionUID.
033   */
034  private static final long serialVersionUID = 1L;
035  /**
036   * Wrapper around a task that is not an instance of {@link org.jppf.node.protocol.Task Task<T>}.
037   */
038  protected TaskObjectWrapper taskObjectWrapper = null;
039  /**
040   * A delegate for the <code>onCancel()</code> method.
041   */
042  protected JPPFTaskCallback<Object> cancelCallback = null;
043  /**
044   * A delegate for the <code>onTimeout()</code> method.
045   */
046  protected JPPFTaskCallback<Object> timeoutCallback = null;
047
048  /**
049   * Initialize this task with an object whose class is either annotated with {@link org.jppf.node.protocol.JPPFRunnable JPPFRunnable},
050   * an instance of {@link java.lang.Runnable Runnable} or an instance of {@link java.util.concurrent.Callable Callable}.
051   * @param taskObject an object that encapsulates the task to execute.
052   * @param args the optional arguments for a class that has one of its methods annotated with {@link org.jppf.node.protocol.JPPFRunnable JPPFRunnable}.
053   * @throws JPPFException if an error is raised while initializing this task.
054   */
055  public JPPFAnnotatedTask(final Object taskObject, final Object... args) throws JPPFException {
056    if (taskObject instanceof Runnable) taskObjectWrapper = new RunnableTaskWrapper((Runnable) taskObject);
057    else if (taskObject instanceof Callable) taskObjectWrapper = new CallableTaskWrapper((Callable<?>) taskObject);
058    else taskObjectWrapper = new AnnotatedTaskWrapper(taskObject, args);
059  }
060
061  /**
062   * Initialize this task from a POJO, given a method and its arguments to execute it.
063   * @param taskObject either an instance of the POJO class if the method is non-static, or a class object if the method is static.
064   * @param method the name of the method to execute.
065   * @param args the arguments for the method to execute.
066   * @throws JPPFException if an error is raised while initializing this task.
067   */
068  public JPPFAnnotatedTask(final Object taskObject, final String method, final Object... args) throws JPPFException {
069    taskObjectWrapper = new PojoTaskWrapper(method, taskObject, args);
070  }
071
072  /**
073   * Run the <code>JPPFRunnable</code>-annotated method of the task object.
074   */
075  @Override
076  public void run() {
077    try {
078      final Object result = taskObjectWrapper.execute();
079      if ((getResult() == null) && ((taskObjectWrapper instanceof RunnableTaskWrapper) || (result != null))) setResult(result);
080    } catch (final Exception e) {
081      setThrowable(e);
082    }
083  }
084
085  /**
086   * Get the <code>JPPFRunnable</code>-annotated object or POJO wrapped by this task.
087   * @return an object or class that is JPPF-annotated.
088   */
089  @Override
090  public Object getTaskObject() {
091    return taskObjectWrapper.getTaskObject();
092  }
093
094  /**
095   * Set the delegate for the <code>onCancel()</code> method.
096   * @param cancelCallback a {@link JPPFTaskCallback} instance.
097   * @return this task, for method chaining.
098   */
099  public JPPFAnnotatedTask setCancelCallback(final JPPFTaskCallback<Object> cancelCallback) {
100    this.cancelCallback = cancelCallback;
101    return this;
102  }
103
104  /**
105   * Set the delegate for the <code>onTimeout()</code> method.
106   * @param timeoutCallback a {@link JPPFTaskCallback} instance.
107   * @return this task, for method chaining.
108   */
109  public JPPFAnnotatedTask setTimeoutCallback(final JPPFTaskCallback<Object> timeoutCallback) {
110    this.timeoutCallback = timeoutCallback;
111    return this;
112  }
113
114  @Override
115  public void onCancel() {
116    if (cancelCallback != null) {
117      cancelCallback.setTask(this);
118      cancelCallback.run();
119    }
120  }
121
122  @Override
123  public void onTimeout() {
124    if (timeoutCallback != null) {
125      timeoutCallback.setTask(this);
126      timeoutCallback.run();
127    }
128  }
129
130  /**
131   * Override of {@link org.jppf.node.protocol.Task#setDataProvider(DataProvider) Task.setDataProvider(DataProvider)} to enable setting the data provider
132   * onto tasks that are not subclasses of {@link org.jppf.node.protocol.Task Task} and which implement {@link DataProviderHolder}.
133   * @param dataProvider the data provider to set onto the task.
134   * @return this task, for method chaining.
135   */
136  @Override
137  public JPPFAnnotatedTask setDataProvider(final DataProvider dataProvider) {
138    final Object o = taskObjectWrapper.getTaskObject();
139    if (o instanceof DataProviderHolder) ((DataProviderHolder) o).setDataProvider(dataProvider);
140    else super.setDataProvider(dataProvider);
141    return this;
142  }
143
144  @Override
145  public boolean isInterruptible() {
146    final Object o = getTaskObject();
147    if (o instanceof Interruptibility) return ((Interruptibility) o).isInterruptible();
148    return super.isInterruptible();
149  }
150
151  @Override
152  public void doCancelAction() throws Exception {
153    final Object o = getTaskObject();
154    if (o instanceof CancellationHandler) ((CancellationHandler) o).doCancelAction();
155  }
156}