/*
 * MiningMart Version 1.0
 * 
 * Copyright (C) 2006 Martin Scholz, Timm Euler, 
 *                    Daniel Hakenjos, Katharina Morik
 *
 * Contact: miningmart@ls8.cs.uni-dortmund.de
 *
 * A list of contributing developers (other than the copyright 
 * holders) can be found at
 * http://mmart.cs.uni-dortmund.de/downloads/download.html
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program, see the file MM_HOME/LICENSE; if not, write
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA 02110-1301, USA.
 */
package edu.udo.cs.miningmart.m4.core;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;

import edu.udo.cs.miningmart.db.DB;
import edu.udo.cs.miningmart.exception.M4Exception;
import edu.udo.cs.miningmart.m4.utils.InterM4Communicator;
import edu.udo.cs.miningmart.m4.utils.InterM4OperatorAssertion;
import edu.udo.cs.miningmart.m4.utils.InterM4OperatorCondition;
import edu.udo.cs.miningmart.m4.utils.InterM4OperatorConstraint;
import edu.udo.cs.miningmart.m4.utils.InterM4OperatorOpParam;
import edu.udo.cs.miningmart.m4.utils.M4Info;
import edu.udo.cs.miningmart.m4.utils.M4InfoEntry;
import edu.udo.cs.miningmart.m4.utils.Print;
import edu.udo.cs.miningmart.m4.utils.XmlInfo;

/**
 * This is the class representing the OPERATOR_T table of the M4 schema.
 * Operator constraints are also accessible from Operator objects.
 * The top class of the executable operators of the compiler is
 * <code>ExecutableOperator</code>.
 * 
 * @author Martin Scholz
 * @version $Id: Operator.java,v 1.3 2006/04/11 14:10:14 euler Exp $
 */
public class Operator extends M4Data implements XmlInfo, edu.udo.cs.miningmart.m4.Operator{

	/** The name of the corresponding M4 table. */
	public static final String M4_TABLE_NAME = "operator_t";

	/** db level: name of the operator id attribute */
	public static final String ATTRIB_OPERATOR_ID = "op_id";

	/** db level: name of the operator name attribute */
	public static final String ATTRIB_OPERATOR_NAME             = "OP_NAME";

	/** db level: name of the attribute indicating if it is a manual operator */
	public static final String ATTRIB_OPERATOR_IS_MANUAL        = "OP_MANUAL";

	/** db level: name of the attribute indicating if it is a loopable operator */
	public static final String ATTRIB_OPERATOR_IS_LOOPABLE      = "OP_LOOP";

	/** db level: name of the attribute indicating if it is a multi-stepable operator */
	public static final String ATTRIB_OPERATOR_IS_MULTISTEPABLE = "OP_MULTI";

	/** db level: name of the attribute for operator realization */
	public static final String ATTRIB_OPERATOR_REALIZED         = "OP_REALIZE";

	// Communication objects:
	static final InterM4Communicator op2oppar  = new InterM4OperatorOpParam();
	static final InterM4Communicator op2assert = new InterM4OperatorAssertion();
	static final InterM4Communicator op2cond   = new InterM4OperatorCondition();
	static final InterM4Communicator op2constr = new InterM4OperatorConstraint();


	/** Cache for getM4Info() */
	public static M4Info m4Info = null;

	/** @see M4Table.getM4TableName() */
	public String getM4TableName() {
		return M4_TABLE_NAME;	
	}

	/** @see M4Table.getIdAttributeName() */
	public String getIdAttributeName() {
		return ATTRIB_OPERATOR_ID;
	}

	/** @see M4Table.getM4Info() */
	public M4Info getM4Info() {
		if (m4Info == null) {
			M4InfoEntry[] m4i = {
				new M4InfoEntry(ATTRIB_OPERATOR_ID,               "getId",       "setId",       long.class,   NOT_NULL),
				new M4InfoEntry(ATTRIB_OPERATOR_NAME,             "getName",     "setName",     String.class, NOT_NULL),
				new M4InfoEntry(ATTRIB_OPERATOR_REALIZED,         "getRealize",  "setRealize",  String.class),
				new M4InfoEntry(ATTRIB_OPERATOR_IS_MANUAL,        "getManual",   "setManual",   String.class),
				new M4InfoEntry(ATTRIB_OPERATOR_IS_LOOPABLE,      "getLoopable", "setLoopable", String.class),
				new M4InfoEntry(ATTRIB_OPERATOR_IS_MULTISTEPABLE, "getStepable", "setStepable", String.class)
			};
			m4Info = new M4Info(m4i);
		}
		return m4Info;
	}

	/** Cache for getXmlInfo() */
	private static M4Info xmlInfo = null;

	/** @see XmlInfo.getXmlInfo() */
	public M4Info getXmlInfo() {
		if (xmlInfo == null) {
			M4InfoEntry[] m4i = { 
				new M4InfoEntry("Name",            "getName",          "setName",          String.class),
				new M4InfoEntry("isManual",        "getManual",        "setManual",        String.class),
				new M4InfoEntry("isLoopable",      "getLoopable",      "setLoopable",      String.class),
				new M4InfoEntry("isMultiStepable", "getStepable",      "setStepable",      String.class),
				new M4InfoEntry("Docu",            "getDocumentation", "setDocumentation", String.class)
			};
			xmlInfo = new M4Info(m4i);
		}
		return xmlInfo;
	}

    // Operator Variables from M4-DB
    protected     boolean loopable;
    protected     boolean stepable;
    protected     boolean manual;
    protected     String realize;
	private final Vector myOpParams    = new Vector();
	private	final Vector myAssertions  = new Vector();
	private	final Vector myConditions  = new Vector();
	private final Vector myConstraints = new Vector();

	// Flags for the lazy getters:
	private boolean allOpParamsLoaded    = false;
	private boolean allAssertionsLoaded  = false;
	private boolean allConditionsLoaded  = false;
	private boolean allConstraintsLoaded = false;
	
	/**
	 * Constructor.
	 * @param db the reference to the Case's DB object.
	 * */
	public Operator(DB db) {
		super(db);	
	}

	// ***** Methods for loading *****

	/**
	 * Get an iterator.
	 * 
	 * @return an <code>Iterator</code> for the parameters stored in table <i>OP_PARAM_T</i>,
	 * represented as objects of type <code>OpParam</code>.
	 */
	public Iterator getOpParamsIterator() throws M4Exception {
        Collection col = this.getOpParams();
		Iterator it = (col == null) ? null : col.iterator();
		return it;
	}

	// ***** Getter and setter *****
	
	/**
	 * @see edu.udo.cs.miningmart.m4.core.M4Data#getObjectsInNamespace(Class)
	 */
	protected Collection getObjectsInNamespace(Class typeOfObjects) throws M4Exception {
		return null;
	}
	
	/**
	 * Setter method.
	 * @param r the new value
	 */
    public void setRealize(String r)
    {   
    	this.setDirty();
    	this.realize = r;
    }

	/**
	 * Getter method.
	 * @return the value
	 */
    public String getRealize()
    {   return realize;   }

	/**
	 * Setter method.
	 * @param l the new value
	 */
    public void setLoopable(boolean l)
    {   
    	this.setDirty();
    	this.loopable = l;
    }

	/**
	 * Setter method.
	 * @param loopable the new value in the database <code>String</code>
	 *        representation
	 */
    public void setLoopable(String loopable) {
    	this.setLoopable(DB.c_yes.equals(loopable));
    }

	/**
	 * "Getter" method.
	 * @return the value
	 */
    public boolean isLoopable()
    {   return loopable;   }

	/**
	 * "Getter" method.
	 * @return the value in database <code>String</code> representation
	 */
    public String getLoopable() {
    	return (this.isLoopable() ? DB.c_yes : DB.c_no);
    }

	/**
	 * Setter method.
	 * @param m the new value
	 */
    public void setManual(boolean m)
    {   
    	this.setDirty();
    	this.manual = m;
    }

	/**
	 * Setter method.
	 * @param manual the new value in the database <code>String</code>
	 *        representation
	 */
    public void setManual(String manual) {
    	this.setManual(DB.c_yes.equals(manual));
    }

	/**
	 * "Getter" method.
	 * @return the value
	 */
    public boolean isManual()
    {   return manual;   }

	/**
	 * "Getter" method.
	 * @return the value in database <code>String</code> representation
	 */
    public String getManual() {
    	return (this.isManual() ? DB.c_yes : DB.c_no);
    }

	/**
	 * Setter method.
	 * @param s the new value
	 */
    public void setStepable(boolean s)
    {   
    	this.setDirty();
    	this.stepable = s;
    }

	/**
	 * Setter method.
	 * @param stepable the new value in the database <code>String</code>
	 *        representation
	 */
    public void setStepable(String stepable) {
    	this.setStepable(DB.c_yes.equals(stepable));
    }

	/**
	 * "Getter" method.
	 * @return the value
	 */
    public boolean isStepable()
    {   return stepable;   }

	/**
	 * "Getter" method.
	 * @return the value in database <code>String</code> representation
	 */
    public String getStepable() {
    	return (this.isStepable() ? DB.c_yes : DB.c_no);
    }


	/**
	 * Active getter for this operator's OpParam's.
	 * 
	 * @return the <code>Collection</code> of <code>OpParam</code>s for this operator
	 */
	public Collection getOpParams() throws M4Exception {
		if (this.allOpParamsLoaded == false && ( ! this.isNew())) {
			this.allOpParamsLoaded = true;
			this.readOpParamsForOp();
		}
		return this.myOpParams;
	}

	/**
	 * Add an <code>OpParam</code> object to this operator's specification.
	 * @param opParam the <code>OpParam</code> to be added
	 */
	public void addOpParam(edu.udo.cs.miningmart.m4.OpParam opParam) throws M4Exception {
		Operator.op2oppar.checkNameExists((OpParam) opParam, this);
		Operator.op2oppar.add(this, (OpParam) opParam);
	}

	/**
	 * Remove an <code>OpParam</code> object from this operator's specification.
	 * 
	 * @param opParam the <code>OpParam</code> to be removed
	 * @return <code>true</code> iff the object was part of this <code>Operator</code>'s
	 * specification and could be removed.
	 */
	public boolean removeOpParam(edu.udo.cs.miningmart.m4.OpParam opParam) throws M4Exception {
		return Operator.op2oppar.remove(this, (OpParam) opParam);
	}

	// ***** Constraints, Conditions, Assertions *****

	public Collection getAssertions() throws M4Exception {
		if (!this.allAssertionsLoaded && ( ! this.isNew())) {
			this.allAssertionsLoaded = true;
			this.readAssertionsFromDB();	
		}
		return this.myAssertions;
	}
	
	public Collection getConditions() throws M4Exception {
		if (!this.allConditionsLoaded && ( ! this.isNew())) {
			this.allConditionsLoaded = true;
			this.readConditionsFromDB();	
		}
		return this.myConditions;	
	}
	
	public Collection getConstraints() throws M4Exception {
		if (!this.allConstraintsLoaded && ( ! this.isNew())) {
			this.allConstraintsLoaded = true;	
			this.readConstraintsFromDB();
		}
		return this.myConstraints;	
	}

	/** 
	 * @param assertion an <code>Assertion</code> to be added
	 */
	public void addAssertion(edu.udo.cs.miningmart.m4.Assertion assertion) throws M4Exception {
		op2assert.add(this, (Assertion) assertion);
	}

	/** 
	 * @param condition a <code>Condition</code> to be added
	 */	
	public void addCondition(edu.udo.cs.miningmart.m4.Condition condition) throws M4Exception {
		op2cond.add(this, (Condition) condition);
	}

	/** 
	 * @param constraint a <code>Constraint</code> to be added
	 */		
	public void addConstraint(edu.udo.cs.miningmart.m4.Constraint constraint) throws M4Exception {
		op2constr.add(this, (Constraint) constraint);	
	}

	/** 
	 * @param assertion an <code>Assertion</code> to be removed
	 */
	public boolean removeAssertion(edu.udo.cs.miningmart.m4.Assertion assertion) throws M4Exception {
		return op2assert.remove(this, (Assertion) assertion);
	}

	/** 
	 * @param condition a <code>Condition</code> to be removed
	 */	
	public boolean removeCondition(edu.udo.cs.miningmart.m4.Condition condition) throws M4Exception {
		return op2cond.remove(this, (Condition) condition);
	}

	/** 
	 * @param constraint a <code>Constraint</code> to be removed
	 */		
	public boolean removeConstraint(edu.udo.cs.miningmart.m4.Constraint constraint) throws M4Exception {
		return op2constr.remove(this, (Constraint) constraint);	
	}		

	/**
	 * @see Operator#createAssertion(String, String, String, String)
	 */
	public edu.udo.cs.miningmart.m4.Assertion createAssertion(
		String type,
		String object1,
		String object2,
		String text)
		throws M4Exception
	{
		Assertion assertion = new Assertion(this.getM4Db());
		assertion.setAssertionType(type);
		assertion.setObj1(object1);
		assertion.setObj2(object2);
		assertion.setDocumentation(text);
		try {
			this.addAssertion(assertion);
		}
		catch (M4Exception e) {
			throw new M4Exception(
				"Could not add new assertion ("
				+ type + ", " + object1 + ", " + object2 + ", " + text
				+ ") to operator with ID " + this.getId()
				+ ":\n" + e.getMessage());
		}
		return assertion;
	}

	/**
	 * @see Operator#createConstraint(String, String, String, String)
	 */
	public edu.udo.cs.miningmart.m4.Constraint createConstraint(
		String type,
		String object1,
		String object2,
		String text)
		throws M4Exception
	{
		Constraint constraint = new Constraint(this.getM4Db());
		constraint.setType(type);
		constraint.setObj1(object1);
		constraint.setObj2(object2);
		constraint.setDocumentation(text);
		try {
			this.addConstraint(constraint);
		}
		catch (M4Exception e) {
			throw new M4Exception(
				"Could not add new constraint ("
				+ type + ", " + object1 + ", " + object2 + ", " + text
				+ ") to operator with ID " + this.getId()
				+ ":\n" + e.getMessage());
		}
		return constraint;
	}
	
	/**
	 * @see Operator#createCondition(String, String, String, String)
	 */
	public edu.udo.cs.miningmart.m4.Condition createCondition(
		String type,
		String object1,
		String object2,
		String text)
		throws M4Exception
	{
		Condition condition = new Condition(this.getM4Db());
		condition.setType(type);
		condition.setObj1(object1);
		condition.setObj2(object2);
		condition.setDocumentation(text);
		try {
			this.addCondition(condition);
		}
		catch (M4Exception e) {
			throw new M4Exception(
				"Could not add new condition ("
				+ type + ", " + object1 + ", " + object2 + ", " + text
				+ ") to operator with ID " + this.getId()
				+ ":\n" + e.getMessage());
		}
		return condition;
	}

	/**
	 * @see Operator#createOperatorParameter(String, int, int, String, String, String)
	 */
	public edu.udo.cs.miningmart.m4.OpParam createOperatorParameter(
		String name,
		int minNrOfArgs,
		int maxNrOfArgs,
		String ioType,
		String parameterType,
		String text)
		throws M4Exception
	{
		OpParam opParam = new OpParam(this.getM4Db());
		opParam.setName(name);
		opParam.setMinArg(minNrOfArgs);
		opParam.setMaxArg(maxNrOfArgs);
		opParam.setInput(ioType);
		opParam.setType(parameterType);
		opParam.setDocumentation(text);
		try {
			this.addOpParam(opParam);
		}
		catch (M4Exception e) {
			throw new M4Exception(
				"Could not add new OperatorParameter ("
				+ name + ", " + minNrOfArgs + ", " + maxNrOfArgs
				+ ", " + ioType + ", " + parameterType + ", " + text
				+ ") to operator with ID " + this.getId()
				+ ":\n" + e.getMessage());
		}
		return opParam;
	}	

	/**
	 * @see Operator#getOperatorParameter(String)
	 */
	public OpParam getOperatorParameter(String name) throws M4Exception {
		Iterator it = null;
		if ((it = this.getOpParamsIterator()) != null && name != null) {
			while (it.hasNext()) {
				OpParam opParam = (OpParam) it.next();
				if (opParam != null && name.equals(opParam.getName())) {
					return opParam;
				}
			}
		}
		return null;
	}
	
	/**
	 * @see Operator#removeOperatorParameter(String)
	 */
	public void removeOperatorParameter(String name) throws M4Exception {
		OpParam opParam = this.getOperatorParameter(name);
		if (opParam != null) {
			this.removeOpParam(opParam);
		}
	}

	/**
	 * @see Operator#removeAllOperatorParameters()
	 */
	public void removeAllOperatorParameters() throws M4Exception {
		Collection col = this.getAllOperatorParameters();
		if (col == null)
			return;
		Iterator it = col.iterator();
		while (it.hasNext()) {
			OpParam opPar = (OpParam) it.next();
			this.removeOpParam(opPar);
		}
	}
	
	/**
	 * @see Operator#removeOperatorParameterByType(String)
	 */
	public void removeOperatorParameterByType(String type)
		throws M4Exception
	{
		Collection col = this.getOperatorParametersByType(type);
		if (col == null)
			return;
		Iterator it = col.iterator();
		while (it.hasNext()) {
			OpParam opPar = (OpParam) it.next();
			this.removeOpParam(opPar);
		}
	}

	/**
	 * @see Operator#getAllOperatorParameters()
	 */
	public Collection getAllOperatorParameters() throws M4Exception {
		return this.getOpParams();
	}

	/**
	 * @see Operator#getOperatorParametersByType(String)
	 */
	public Collection getOperatorParametersByType(String type) throws M4Exception {
		Iterator it = null;
		if ((it = this.getOpParamsIterator()) != null && type != null) {
			Vector results = new Vector();
			while (it.hasNext()) {
				OpParam opParam = (OpParam) it.next();
				if (opParam != null && type.equals(opParam.getTypeS())) {
					results.add(opParam);
				}
			}
			return results;
		}
		return null;
	}
	
	/**
	 * @see Operator#getAllInputOperatorParameters()
	 */
	public Collection getAllInputOperatorParameters() throws M4Exception {
		Iterator it = null;
		if ((it = this.getOpParamsIterator()) != null) {
			Vector results = new Vector();
			while (it.hasNext()) {
				OpParam opParam = (OpParam) it.next();
				if (opParam != null && opParam.isInput()) {
					results.add(opParam);
				}
			}
			return results;
		}
		return null;
	}
	
	/**
	 * @see Operator#getAllOutputOperatorParameters()
	 */
	public Collection getAllOutputOperatorParameters() throws M4Exception {
		Iterator it = null;
		if ((it = this.getOpParamsIterator()) != null) {
			Vector results = new Vector();
			while (it.hasNext()) {
				OpParam opParam = (OpParam) it.next();
				if (opParam != null && !opParam.isInput()) {
					results.add(opParam);
				}
			}
			return results;
		}		
		return null;
	}
	
	public edu.udo.cs.miningmart.m4.OpParam getOpParam(String name) throws M4Exception {
		Iterator it = null;
		if ((it = this.getOpParamsIterator()) != null) {
			while (it.hasNext()) {
				OpParam opParam = (OpParam) it.next();
				if (opParam != null && opParam.getName().equals(name)) {
					return opParam;
				}
			}
		}		
		return null;
	}

	/**
	 * @see edu.udo.cs.miningmart.m4.Operator#getCoordinatedParameterArrays()
	 */
	public Collection getCoordinatedParameterArrays() throws M4Exception {
		// There may be several groups of parameter arrays, with coordination
		// needed within each group, but not between the groups. Thus a collection
		// of collections of OpParams is returned.
		
		HashMap theCollections = new HashMap(); // maps parameter names to coordination groups;
		
		// loop through the coordination constraints:	
		Iterator it = this.getConstraintsOfType(Constraint.TYPE_COORDINATED_ARRAYS).iterator();
		while (it.hasNext()) {
			Constraint myConstr = (Constraint) it.next();
			// make a group of OpParams for each coordination group
			String name1 = myConstr.getObj1();
			String name2 = myConstr.getObj2();
			if (name1 == null || name2 == null) {
				throw new M4Exception("Operator.getCoordinatedParameterArrays(): Found a Constraint of type " +
						Constraint.TYPE_COORDINATED_ARRAYS + " that is underspecified!");
			}
			// check if the group already exists:
			HashSet theGroup = (HashSet) theCollections.get(name1);
			if (theGroup == null) {
				theGroup = (HashSet) theCollections.get(name2);
			}
			else {
				// check if two different groups are merged by this constraint:
				HashSet secondGroup = (HashSet) theCollections.get(name2);
				if (secondGroup != null) {
					theGroup.addAll(secondGroup);
				}
				
			}
			if (theGroup == null) { 
				// no group for this coordination exists, so create a new one:
				theGroup = new HashSet();
			}
			// ensure that the group is found under all key names:
			theCollections.put(name1, theGroup);
			theCollections.put(name2, theGroup);
			// ensure that the OpParam objects corresponding to the two names
			// are in the group:
			OpParam par1 = this.getOperatorParameter(name1);
			OpParam par2 = this.getOperatorParameter(name2);
			if (par1 == null) {
				throw new M4Exception("Operator.getCoordinatedParameterArrays: could not find OpParam object with name '" + name1 + "'!");
			}
			if (par2 == null) {
				throw new M4Exception("Operator.getCoordinatedParameterArrays: could not find OpParam object with name '" + name2 + "'!");
			}
			theGroup.add(par1);
			theGroup.add(par2);
		}
		
		// return a collection of collections, not a collection of map entries:
		Vector ret = new Vector();
		Iterator entryIt = theCollections.entrySet().iterator();
		while (entryIt.hasNext()) {
			Map.Entry myEntry = (Map.Entry) entryIt.next();
			HashSet myGroup = (HashSet) myEntry.getValue();
			if ( ! ret.contains(myGroup)) {
				ret.add(myGroup);
			}
		}
		return ret;
	}
	
	
	// ***** Private helper methods *****


	/*
	 * return only the constraints of the given type
	 */
	private Collection getConstraintsOfType(String type) throws M4Exception {
		Iterator it = this.getConstraints().iterator();
		Vector result = new Vector();
		while (it.hasNext()) {
			Constraint myConstr = (Constraint) it.next();
			if (myConstr.getType().equalsIgnoreCase(type)) {
				 result.add(myConstr);
		    }
		}
		return result;
	}
	
    /**
     * Reads all parameter objects for the given operator and sets them into it.
     * @param op the operator object for which the parameters are to be loaded
     */
    private void readOpParamsForOp() throws M4Exception
    {
    	Iterator it = this.getObjectsReferencingMe(OpParam.class).iterator();
    	while (it.hasNext()) {
    		this.addOpParam((edu.udo.cs.miningmart.m4.OpParam) it.next());
    	}
    }

    /** Reads and stores the assertions for this operator. */
    private void readAssertionsFromDB() throws M4Exception
    {
    	Iterator it = this.getObjectsReferencingMe(Assertion.class).iterator();
    	while (it.hasNext()) {
    		this.addAssertion((edu.udo.cs.miningmart.m4.Assertion) it.next());
    	}
    }

    /** Reads and stores the conditions for this operator. */
    private void readConditionsFromDB() throws M4Exception
    {
    	Iterator it = this.getObjectsReferencingMe(Condition.class).iterator();
    	while (it.hasNext()) {
    		this.addCondition((edu.udo.cs.miningmart.m4.Condition) it.next());
    	}
    }

    /** Reads and stores the constraints for this operator. */
    private void readConstraintsFromDB() throws M4Exception
    {
    	Iterator it = this.getObjectsReferencingMe(Constraint.class).iterator();
    	while (it.hasNext()) {
    		this.addConstraint((edu.udo.cs.miningmart.m4.Constraint) it.next());
    	}
    }

    
    public void print() {
		this.doPrint(Print.M4_OBJECT, "Operator " + this.getName() + " (ID: " + this.getId() + "): {");
		this.doPrint(Print.M4_OBJECT, ((this.isManual()) ? "" : "not") + " manual,");
		this.doPrint(Print.M4_OBJECT, ((this.isLoopable()) ? "" : "not") + " loopable,");
		this.doPrint(Print.M4_OBJECT, ((this.isStepable()) ? "" : "not") + " multistep-able\n}");
		
		try {
			Iterator it = this.getOpParamsIterator();
			while (it.hasNext()) {
				OpParam op = (OpParam) it.next();
				op.print();
			}
		}
		catch (M4Exception e) {
			this.doPrint(Print.MAX, "Warning: Exception when printing operator " + this.getId() + ":");
			this.doPrint(e);	
		}
    }
    
   	/** @see M4Data#removeAllM4References() */
	protected void removeAllM4References() throws M4Exception {
		Vector empty = new Vector();
		op2assert.setCollectionTo(this, empty);
		op2cond.setCollectionTo(this, empty);
		op2constr.setCollectionTo(this, empty);
		op2oppar.setCollectionTo(this, empty);
		this.removeDocObject();
	}

	/** @see M4Data#getDependentObjects */
	public Collection getDependentObjects() throws M4Exception {
		Collection ret = super.getDependentObjects();
		ret.addAll(this.getOpParams());
		ret.addAll(this.getAssertions());
		ret.addAll(this.getConditions());
		ret.addAll(this.getConstraints());
		return ret;
	}

}
/*
 * Historie
 * --------
 * 
 * $Log: Operator.java,v $
 * Revision 1.3  2006/04/11 14:10:14  euler
 * Updated license text.
 *
 * Revision 1.2  2006/04/06 16:31:13  euler
 * Prepended license remark.
 *
 * Revision 1.1  2006/01/03 09:54:17  hakenjos
 * Initial version!
 *
 */
