/* * Copyright 2007-2013 * Licensed under GNU Lesser General Public License * * This file is part of EpochX * * EpochX is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * EpochX is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with EpochX. If not, see <http://www.gnu.org/licenses/>. * * The latest version is available from: http://www.epochx.org */ package org.epochx; import org.epochx.event.Event; import org.epochx.event.EventManager; import org.epochx.event.Listener; import org.epochx.event.OperatorEvent.EndOperator; import org.epochx.event.OperatorEvent.StartOperator; /** * A skeletal implementation of the {@link Operator} interface than fires * events at the start (before) and end (after) the operator is performed. * Typically, subclasses will override one of the following methods: * * <ul> * * <li>{@link #perform(Individual...)}: when no custom end event is needed; * * <li>{@link #perform(OperatorEvent.EndOperator, Individual...)}: when a custom end event is * used, this method should be overridden to set the additional information. * * </ul> * * @see Event * @see EventManager * @see Listener */ public abstract class AbstractOperator implements Operator { @Override public final Individual[] apply(Individual ... individuals) { Individual[] parents = clone(individuals); // fires the start event StartOperator start = getStartEvent(individuals); EventManager.getInstance().fire(start); EndOperator end = getEndEvent(individuals); parents = perform(end, parents); // fires the end event only if the operator was successful if (parents != null) { end.setChildren(clone(parents)); EventManager.getInstance().fire(end); } return parents; } /** * Performs the operator on the specified individuals. If the operator is * not successful, the specified individuals will not be changed and * <code>null</code> is returned. The default implementation calls the * {@link #perform(Individual...)} method. * <p> * When overriding this method, the specified <code>EndOperator</code> event * can be used to provide more information about the operator. In order to * do so, the {@link #getEndEvent(Individual...)} method must return a * custom event instance, enabling this method to set its properties. * </p> * * @param event the end event object to be fired after this operator is * performed. * @param individuals the individuals undergoing the operator. * * @return the indivuals produced by this operator. * * @see #getEndEvent(Individual...) */ public Individual[] perform(EndOperator event, Individual ... individuals) { return perform(individuals); } /** * Performs the operator on the specified individuals. If the operator is * not successful, the specified individuals will not be changed and * <code>null</code> is returned. The default implementation just returns * the same individuals. * * @param individuals the individuals undergoing the operator. * * @return the indivduals produced by this operator; <code>null</code> when * the operator could not be applied. */ public Individual[] perform(Individual ... individuals) { return individuals; } /** * Returns the operator's start event. The default implementation returns * a <code>StartOperator</code> instance. * * @param parents the individuals undergoing the operator. * * @return the operator's start event. */ protected StartOperator getStartEvent(Individual ... parents) { return new StartOperator(this, parents); } /** * Returns the operator's end event. The default implementation returns * a <code>EndOperator</code> instance. The end event is passed to the * {@link #perform(Individual...)} method to allow the operator to add * additional information. * * @param parents the individuals undergoing the operator. * * @return the operator's end event. */ protected EndOperator getEndEvent(Individual ... parents) { return new EndOperator(this, parents); } /** * Returns a (deep) clone copy of the specified array of individuals. * * @param individuals the array of individuals to be cloned. * * @return a (deep) clone copy of the specified array of individuals. */ private Individual[] clone(Individual[] individuals) { Individual[] clone = new Individual[individuals.length]; for (int i = 0; i < clone.length; i++) { if (individuals[i] != null) { clone[i] = individuals[i].clone(); } } return clone; } }