/*
 * Copyright (c) 2006-2008 Maskat Project.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Maskat Project - initial API and implementation
 */
package org.maskat.core;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * An instance of this class represents definition node.
 * <code>IBasicDef</code>s form a tree.
 * The children should have orders, so have indices.
 * The children are not required to be of the same type.
 */
public interface MaskatElement extends Cloneable {

	/**
	 * BasicDefs should have its parent reference. 
	 * For example: Child could see its parent so that it could delete itself
	 * from its parent. 
	 * Note: the returned object of getParentDef may not hold this "child"
	 * object as a child!!! For example, the child is removed from the parent,
	 * but the parentDef property is not set to null.
	 * 
	 * @see org.maskat.ui.views.properties.DeleteChildCommand
	 * 
	 */
	public MaskatElement getParent();

	public void setParent(MaskatElement parent);
	
	/**
	 * Get the <b>unremovable</b> iterator of all the children of the specified
	 * type(class). Children should be returned by the Iterator in the proper
	 * order.
	 * 
	 * @param clazz
	 * @return iterator
	 */
	public Iterator getTypedChildren(Class clazz);

	/**
	 * Get the <b>unremovable</b> iterator of all the children objects.
	 * Children should be returned by the Iterator in the proper order.
	 * 
	 * @return iterator
	 */
	public Iterator getChildren();

	/**
	 * Get a unmodifiable list containing the children in the proper order.
	 * Generally the client could choose between getAllChildren and
	 * getUnmodifiableChildren for the appropriate one.
	 * 
	 * @return list of unmodifiable children
	 */
	public List getUnmodifiableChildren();

	/**
	 * Add a child to this object, the newly-added child will have the last
	 * order.
	 *
	 * @param child
	 */
	public void addChild(Object child);

	/**
	 * Get the index of the specified child.
	 * 
	 * @param child
	 * @return　index of the specified child.
	 */
	public int getChildIdx(Object child);

	/**
	 * should only be used by <code>DelBasicDefCommand</code> or
	 * <code>DelGridHeaderCommand</code>, to restore the original index of
	 * child element
	 * 
	 * @param child
	 * @param idx
	 */
	public void addChildToIdx(Object child, int idx);

	/**
	 * Remove the specified child.
	 * 
	 * @param obj
	 */
	public void removeChild(Object obj);

	/**
	 * In the ordered childrens of the specified type, returns the one that have
	 * index idx, or null if not found.
	 * 
	 * @param clazz
	 * @param idx
	 * @return returns null if cannot find a element with type clazz and have
	 *         index idx
	 */
	public Object getChildByTypeIdx(Class clazz, int idx);

	/**
	 * Remove all the children definition nodes.
	 */
	public void removeAllChildren();

	public void accept(MaskatElementVisitor visitor);

	public Object clone() throws CloneNotSupportedException;
	
	public void getAllDescendants(MaskatElement parent, Class descendantClass, ArrayList result);
}
