/*******************************************************************************
 * Copyright (c) 2000, 2014 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
 *******************************************************************************/

package org.aspectj.org.eclipse.jdt.core.dom;

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

/**
 * Type node for an array type.
 * <p>
 * In JLS8 and later, array types are represented by a base element type (which cannot
 * be an array type) and a list of dimensions, each of which may have a list of annotations.
 * </p>
 * <pre>
 * ArrayType: 
 *    Type Dimension <b>{</b> Dimension <b>}</b>
 * </pre>
 * 
 * In JLS4 and before, array types were expressed in a recursive manner, one dimension at a time:
 * <pre>
 * ArrayType:
 *    Type <b>[</b> <b>]</b></pre>
 *
 * This structure became untenable with the advent of type-use annotations,
 * because in the language model, the base type binds with array dimensions from right to left,
 * whereas a recursive structure binds from left to right (inside out).
 * <p>
 * Example:<br>
 * <code><u>int @A[] @B[] @C[]</u></code>
 * is an <u><code>@A</code></u>-array of<br>
 * <code><u>int </u>&nbsp;&nbsp;&nbsp;&nbsp;<u> @B[] @C[]</u></code>,
 * but such a component type is not representable by nested <code>ArrayType</code>s with contiguous source ranges.
 * 
 * @since 2.0
 * @noinstantiate This class is not intended to be instantiated by clients.
 */
@SuppressWarnings({"rawtypes", "unchecked"})
public class ArrayType extends Type {

	/**
	 * The "componentType" structural property of this node type (child type: {@link Type}).
	 * @deprecated In the JLS8 API, this property is replaced by {@link #ELEMENT_TYPE_PROPERTY} and {@link #DIMENSIONS_PROPERTY}.
	 * @since 3.0
	 */
	public static final ChildPropertyDescriptor COMPONENT_TYPE_PROPERTY =
		new ChildPropertyDescriptor(ArrayType.class, "componentType", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$

	/**
	 * The "elementType" structural property of this node type (child type: {@link Type}) (added in JLS8 API).
	 * Cannot be an array type.
	 * @since 3.10
	 */
	public static final ChildPropertyDescriptor ELEMENT_TYPE_PROPERTY =
			new ChildPropertyDescriptor(ArrayType.class, "elementType", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$	
	
	/**
	 * The "dimensions" structural property of this node type (element type: {@link Dimension}) (added in JLS8 API).
	 * @since 3.10
	 */
	public static final ChildListPropertyDescriptor DIMENSIONS_PROPERTY =
			new ChildListPropertyDescriptor(ArrayType.class, "dimensions", Dimension.class, CYCLE_RISK); //$NON-NLS-1$	
	/**
	 * A list of property descriptors (element type:
	 * {@link StructuralPropertyDescriptor}),
	 * or null if uninitialized.
	 */
	private static final List PROPERTY_DESCRIPTORS;
	/**
	 * A list of property descriptors (element type:
	 * {@link StructuralPropertyDescriptor}),
	 * or null if uninitialized.
	 * @since 3.10
	 */
	private static final List PROPERTY_DESCRIPTORS_8_0;

	static {
		List propertyList = new ArrayList(2);
		createPropertyList(ArrayType.class, propertyList);
		addProperty(COMPONENT_TYPE_PROPERTY, propertyList);
		PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);

		propertyList = new ArrayList(3);
		createPropertyList(ArrayType.class, propertyList);
		addProperty(ELEMENT_TYPE_PROPERTY, propertyList);
		addProperty(DIMENSIONS_PROPERTY, propertyList);
		PROPERTY_DESCRIPTORS_8_0 = reapPropertyList(propertyList);
	}

	/**
	 * 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})
	 * @since 3.0
	 */
	public static List propertyDescriptors(int apiLevel) {
		switch (apiLevel) {
			case AST.JLS2_INTERNAL :
			case AST.JLS3_INTERNAL :
			case AST.JLS4_INTERNAL:
				return PROPERTY_DESCRIPTORS;
			default :
				return PROPERTY_DESCRIPTORS_8_0;
		}
	}

	/**
	 * The element type (before JLS8: component type); lazily initialized; defaults to a simple type with
	 * an unspecified, but legal, name.
	 */
	private Type type = null;

	/**
	 * List of dimensions this node has with optional annotations
	 * (element type: {@link Dimension}).
	 * Null before JLS8. Added in JLS8; defaults to a list with one element
	 * (see constructor).
	 * 
	 * @since 3.10
	 */
	private ASTNode.NodeList dimensions = null;

	/**
	 * Creates a new unparented node for an array type owned by the given AST.
	 * By default, a 1-dimensional array of an unspecified simple type.
	 * <p>
	 * N.B. This constructor is package-private.
	 * </p>
	 *
	 * @param ast the AST that is to own this node
	 */
	ArrayType(AST ast) {
		super(ast);
		if (ast.apiLevel >= AST.JLS8_INTERNAL) {
			this.dimensions = new ASTNode.NodeList(DIMENSIONS_PROPERTY);
			// single dimension array is the default
			this.dimensions().add(this.ast.newDimension());
		}
	}

	/**
	* Creates a new unparented node for an array type owned by the given AST.
	* <p>
	* N.B. This constructor is package-private.
	* </p>
	*
	* @param ast the AST that is to own this node
	* @param dimensions no of dimensions - can be zero
	*
	* @since 3.10
	*/
	ArrayType(AST ast, int dimensions) {
		super(ast);
		unsupportedIn2_3_4();
		this.dimensions = new ASTNode.NodeList(DIMENSIONS_PROPERTY);
		for (int i = 0; i < dimensions; ++i) {
			this.dimensions().add(this.ast.newDimension());
		}
	}

	@Override
	final List internalStructuralPropertiesForType(int apiLevel) {
		return propertyDescriptors(apiLevel);
	}

	@Override
	final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
		if (property == DIMENSIONS_PROPERTY) {
			return dimensions();
		}
		// allow default implementation to flag the error
		return super.internalGetChildListProperty(property);
	}

	@Override
	final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
		if (property == COMPONENT_TYPE_PROPERTY) {
			if (get) {
				return getComponentType();
			} else {
				setComponentType((Type) child);
				return null;
			}
		} else if (property == ELEMENT_TYPE_PROPERTY) {
			if (get) {
				return getElementType();
			} else {
				setElementType((Type) child);
				return null;
			}
		}
		// allow default implementation to flag the error
		return super.internalGetSetChildProperty(property, get, child);
	}

	@Override
	final int getNodeType0() {
		return ARRAY_TYPE;
	}

	@Override
	ASTNode clone0(AST target) {
		ArrayType result;
		if (this.ast.apiLevel < AST.JLS8_INTERNAL) {
			result = new ArrayType(target);
			result.setComponentType((Type) getComponentType().clone(target));			
		} else {
			result = new ArrayType(target, 0);
			result.setElementType((Type) getElementType().clone(target));
			result.dimensions().addAll(
					ASTNode.copySubtrees(target, dimensions()));
		}
		result.setSourceRange(getStartPosition(), getLength());
		return result;
	}

	@Override
	final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
		// dispatch to correct overloaded match method
		return matcher.match(this, other);
	}

	@Override
	void accept0(ASTVisitor visitor) {
		boolean visitChildren = visitor.visit(this);
		if (visitChildren) {
			// visit children in normal left to right reading order
			if (this.ast.apiLevel < AST.JLS8_INTERNAL) {
				acceptChild(visitor, getComponentType());				
			} else {
				acceptChild(visitor, getElementType());
				acceptChildren(visitor, this.dimensions);
			}
		}
		visitor.endVisit(this);
	}

	/**
	 * Returns the component type of this array type. The component type
	 * may be another array type.
	 *
	 * @return the component type node
	 * @exception UnsupportedOperationException if this operation is used in
	 * an AST later than JLS4
	 * @see #dimensions()
	 * @deprecated In the JLS8 API, the recursive structure is not valid.
	 */
	public Type getComponentType() {
		supportedOnlyIn2_3_4();
		return internalGetType(COMPONENT_TYPE_PROPERTY);
	}

	private Type internalGetType(ChildPropertyDescriptor property) {
		if (this.type == null) {
			// lazy init must be thread-safe for readers
			synchronized (this) {
				if (this.type == null) {
					preLazyInit();
					this.type = new SimpleType(this.ast);
					postLazyInit(this.type, property);
				}
			}
		}
		return this.type;
	}

	/**
	 * Sets the component type of this array type. The component type
	 * may be another array type.
	 *
	 * @param componentType the component type
	 * @exception IllegalArgumentException if:
	 * <ul>
	 * <li>the node belongs to a different AST</li>
	 * <li>the node already has a parent</li>
	 * <li>a cycle in would be created</li>
	 * </ul>
	 * @exception UnsupportedOperationException if this operation is used in
	 * an AST later than JLS4
	 * @deprecated In the JLS8 API, the recursive structure is not valid.
	 */
	public void setComponentType(Type componentType) {
		supportedOnlyIn2_3_4();
		if (componentType == null) {
			throw new IllegalArgumentException();
		}
		internalSetType(componentType, COMPONENT_TYPE_PROPERTY);
	}

	private void internalSetType(Type componentType, ChildPropertyDescriptor property) {
		ASTNode oldChild = this.type;
		preReplaceChild(oldChild, componentType, property);
		this.type = componentType;
		postReplaceChild(oldChild, componentType, property);
	}

	/**
	 * Returns the element type of this array type. The element type is
	 * never an array type.
	 * <p>
	 * In JLS4 and earlier, this is a convenience method that descends a chain of nested array types
	 * until it reaches a non-array type.
	 * </p>
	 *
	 * @return the element type node
	 */
	public Type getElementType() {
		if (this.ast.apiLevel() < AST.JLS8_INTERNAL) {
			Type t = getComponentType();
			while (t.isArrayType()) {
				t = ((ArrayType) t).getComponentType();
			}
			return t;
		}
		return internalGetType(ELEMENT_TYPE_PROPERTY);
	}

	/**
	 * Sets the element type of the array.
	 *
	 * @param type the new type
	 * @exception IllegalArgumentException if:
	 * <ul>
	 * <li>the node belongs to a different AST</li>
	 * <li>the node already has a parent</li>
	 * <li>the node is an array type</li>
	 * </ul>
	 * @exception UnsupportedOperationException if this operation is used below JLS8
	 * @since 3.10
	 */
	public void setElementType(Type type) {
		unsupportedIn2_3_4();
		if (type == null || type instanceof ArrayType) {
			throw new IllegalArgumentException();
		}
		internalSetType(type, ELEMENT_TYPE_PROPERTY);
	}

	/**
	 * Returns the number of dimensions in this array type.
	 * <p>
	 * In JLS8 and later, this is a convenience method that returns <code>dimensions().size()</code>.
	 * </p>
	 * <p>
	 * In JLS4 and earlier, this is a convenience method that descends a chain of nested array types
	 * until it reaches a non-array type.
	 * </p>
	 *
	 * @return the number of dimensions (always positive)
	 */
	public int getDimensions() {
		if (this.ast.apiLevel() >= AST.JLS8_INTERNAL) {
			return dimensions().size();
		}
		Type t = getComponentType();
		int dimension = 1; // always include this array type
		while (t.isArrayType()) {
			dimension++;
			t = ((ArrayType) t).getComponentType();
		}
		return dimension;			
	}

	/**
	 * Returns the live ordered list of dimensions with optional annotations (added in JLS8 API).
	 * <p>
	 * For the array type to be plausible, the list should contain at least one element.
	 * </p>
	 * 
	 * @return the live list of dimensions with optional annotations (element type: {@link Dimension})
	 * @exception UnsupportedOperationException if this operation is used below JLS8
	 * @since 3.10
	 */
	public List dimensions() {
		// more efficient than just calling unsupportedIn2_3_4() to check
		if (this.dimensions == null) {
			unsupportedIn2_3_4();
		}
		return this.dimensions;
	}

	@Override
	int memSize() {
		return BASE_NODE_SIZE + 2 * 4;
	}

	@Override
	int treeSize() {
		return
			memSize()
			+ (this.type == null ? 0 : (this.ast.apiLevel() < AST.JLS8_INTERNAL ? getComponentType().treeSize() : getElementType().treeSize())
			+ (this.dimensions == null ? 0 : this.dimensions.listSize()));
	}
}

