/*******************************************************************************
 * Copyright (c) 2003, 2008 IBM Corporation and others.
 * 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:
 *     IBM Corporation - initial API and implementation
 *     Technical University Berlin - extended API and implementation
 *******************************************************************************/

package org.eclipse.jdt.core.dom;

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

/**
 * Type parameter node (added in JLS3 API).
 * <pre>
 * TypeParameter:
 *    TypeVariable [ <b>extends</b> Type { <b>&</b> Type } ]
 * </pre>
 * 
 * @since 3.1
 * @noinstantiate This class is not intended to be instantiated by clients.
 */
public class TypeParameter extends ASTNode {
	
	/**
	 * The "name" structural property of this node type.
	 */
	public static final ChildPropertyDescriptor NAME_PROPERTY = 
		new ChildPropertyDescriptor(TypeParameter.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$

	/**
	 * The "typeBounds" structural property of this node type.
	 */
	public static final ChildListPropertyDescriptor TYPE_BOUNDS_PROPERTY = 
		new ChildListPropertyDescriptor(TypeParameter.class, "typeBounds", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$

//{ObjectTeams: distinguish value parameters and <B base R>:
	public static final SimplePropertyDescriptor VALUE_PARAMETER_PROPERTY = 
		new SimplePropertyDescriptor(TypeParameter.class, "valueParameter", boolean.class, MANDATORY); //$NON-NLS-1$
	public static final SimplePropertyDescriptor BASE_BOUND_PROPERTY = 
		new SimplePropertyDescriptor(TypeParameter.class, "baseBound", boolean.class, MANDATORY); //$NON-NLS-1$
// SH}

	/**
	 * A list of property descriptors (element type: 
	 * {@link StructuralPropertyDescriptor}),
	 * or null if uninitialized.
	 */
	private static final List PROPERTY_DESCRIPTORS;
	
	static {
		List propertyList = new ArrayList(3);
		createPropertyList(TypeParameter.class, propertyList);
		addProperty(NAME_PROPERTY, propertyList);
		addProperty(TYPE_BOUNDS_PROPERTY, propertyList);
//{ObjectTeams: value parameter:
		addProperty(VALUE_PARAMETER_PROPERTY, propertyList);
// SH}
		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
	}

//{ObjectTeams: value parameter, <B base R>:
	private boolean isValueParameter= false;
	private boolean hasBaseBound= false;
//SH}
	
	/**
	 * Returns a list of structural property descriptors for this node type.
	 * Clients must not modify the result.
	 * 
	 * @param apiLevel the API level; one of the
	 * <code>AST.JLS*</code> constants

	 * @return a list of property descriptors (element type: 
	 * {@link StructuralPropertyDescriptor})
	 */
	public static List propertyDescriptors(int apiLevel) {
		return PROPERTY_DESCRIPTORS;
	}
			
	/** 
	 * The type variable node; lazily initialized; defaults to an unspecfied, 
	 * but legal, name.
	 */
	private SimpleName typeVariableName = null;
	
	/**
	 * The type bounds (element type: <code>Type</code>). 
	 * Defaults to an empty list.
	 */
	private ASTNode.NodeList typeBounds =
		new ASTNode.NodeList(TYPE_BOUNDS_PROPERTY);
	
	/**
	 * Creates a new unparented node for a parameterized type owned by the
	 * given AST. By default, an unspecified, but legal, type variable name, 
	 * and no type bounds.
	 * <p>
	 * N.B. This constructor is package-private.
	 * </p>
	 * 
	 * @param ast the AST that is to own this node
	 */
	TypeParameter(AST ast) {
		super(ast);
	    unsupportedIn2();
	}

	/* (omit javadoc for this method)
	 * Method declared on ASTNode.
	 */
	final List internalStructuralPropertiesForType(int apiLevel) {
		return propertyDescriptors(apiLevel);
	}
	
	/* (omit javadoc for this method)
	 * Method declared on ASTNode.
	 */
	final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
		if (property == NAME_PROPERTY) {
			if (get) {
				return getName();
			} else {
				setName((SimpleName) child);
				return null;
			}
		}
		// allow default implementation to flag the error
		return super.internalGetSetChildProperty(property, get, child);
	}
	
//{ObjectTeams: value parameter?  
	boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
		if (property == VALUE_PARAMETER_PROPERTY) {
			if (get) {
				return isValueParameter();
			} else {
				setIsValueParameter(value);
				return false;
			}
		}
		// allow default implementation to flag the error
		return super.internalGetSetBooleanProperty(property, get, value);
	}
// SH}
	/* (omit javadoc for this method)
	 * Method declared on ASTNode.
	 */
	final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
		if (property == TYPE_BOUNDS_PROPERTY) {
			return typeBounds();
		}
		// allow default implementation to flag the error
		return super.internalGetChildListProperty(property);
	}
	
	/* (omit javadoc for this method)
	 * Method declared on ASTNode.
	 */
	final int getNodeType0() {
		return TYPE_PARAMETER;
	}

	/* (omit javadoc for this method)
	 * Method declared on ASTNode.
	 */
	ASTNode clone0(AST target) {
		TypeParameter result = new TypeParameter(target);
		result.setSourceRange(getStartPosition(), getLength());
		result.setName((SimpleName) ((ASTNode) getName()).clone(target));
//{ObjectTeams: value parameter?
		result.setIsValueParameter(this.isValueParameter());
// SH}
		result.typeBounds().addAll(
			ASTNode.copySubtrees(target, typeBounds()));
		return result;
	}

	/* (omit javadoc for this method)
	 * Method declared on ASTNode.
	 */
	final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
		// dispatch to correct overloaded match method
		return matcher.match(this, other);
	}

	/* (omit javadoc for this method)
	 * Method declared on ASTNode.
	 */
	void accept0(ASTVisitor visitor) {
		boolean visitChildren = visitor.visit(this);
		if (visitChildren) {
			// visit children in normal left to right reading order
			acceptChild(visitor, getName());
			acceptChildren(visitor, this.typeBounds);
		}
		visitor.endVisit(this);
	}
	
	/**
	 * Returns the name of the type variable declared in this type parameter.
	 * 
	 * @return the name of the type variable
	 */ 
	public SimpleName getName() {
		if (this.typeVariableName == null) {
			// lazy init must be thread-safe for readers
			synchronized (this) {
				if (this.typeVariableName == null) {
					preLazyInit();
					this.typeVariableName = new SimpleName(this.ast);
					postLazyInit(this.typeVariableName, NAME_PROPERTY);
				}
			}
		}
		return this.typeVariableName;
	}
	
	/**
	 * Resolves and returns the binding for this type parameter.
	 * <p>
	 * Note that bindings are generally unavailable unless requested when the
	 * AST is being built.
	 * </p>
	 * 
	 * @return the binding, or <code>null</code> if the binding cannot be 
	 *    resolved
	 */	
	public final ITypeBinding resolveBinding() {
		return this.ast.getBindingResolver().resolveTypeParameter(this);
	}
	
	/**
	 * Sets the name of the type variable of this type parameter to the given
	 * name.
	 * 
	 * @param typeName the new name of this type parameter 
	 * @exception IllegalArgumentException if:
	 * <ul>
	 * <li>the node belongs to a different AST</li>
	 * <li>the node already has a parent</li>
	 * </ul>
	 */ 
	public void setName(SimpleName typeName) {
		if (typeName == null) {
			throw new IllegalArgumentException();
		}
		ASTNode oldChild = this.typeVariableName;
		preReplaceChild(oldChild, typeName, NAME_PROPERTY);
		this.typeVariableName = typeName;
		postReplaceChild(oldChild, typeName, NAME_PROPERTY);
	}

	/**
	 * Returns the live ordered list of type bounds of this type parameter.
	 * For the type parameter to be plausible, there can be at most one
	 * class in the list, and it must be first, and the remaining ones must be
	 * interfaces; the list should not contain primitive types (but array types
	 * and parameterized types are allowed).
	 * 
	 * @return the live list of type bounds
	 *    (element type: <code>Type</code>)
	 */ 
	public List typeBounds() {
		return this.typeBounds;
	}
	
//{ObjectTeams: value parameters & <B base R>:
	/**
	 * Returns whether this type parameter is a value parameter.
	 */ 
	public boolean isValueParameter() {
		return this.isValueParameter;
	}
	
	/**
	 * Sets whether this type parameter is a value parameter.
	 */ 
	public void setIsValueParameter(boolean isValueParameter) {
		preValueChange(VALUE_PARAMETER_PROPERTY);
		this.isValueParameter= isValueParameter;
		postValueChange(VALUE_PARAMETER_PROPERTY);
	}

	/**
	 * Returns whether this type parameter has a "base" bound.
	 */ 
	public boolean hasBaseBound() {
		return this.hasBaseBound;
	}
	
	/**
	 * Sets whether this type parameter has a "base" bound.
	 */ 
	public void setHasBaseBound(boolean hasBaseBound) {
		preValueChange(BASE_BOUND_PROPERTY);
		this.hasBaseBound = hasBaseBound;
		postValueChange(BASE_BOUND_PROPERTY);
	}
// SH}
	
	/* (omit javadoc for this method)
	 * Method declared on ASTNode.
	 */
	int memSize() {
		// treat Code as free
		return BASE_NODE_SIZE + 2 * 4;
	}
	
	/* (omit javadoc for this method)
	 * Method declared on ASTNode.
	 */
	int treeSize() {
		return 
			memSize()
			+ (this.typeVariableName == null ? 0 : getName().treeSize())
			+ this.typeBounds.listSize();
	}
}

