/******************************************************************************* * Copyright (c) 2009 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 * Zend Technologies *******************************************************************************/ package org2.eclipse.php.internal.core.ast.nodes; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import org2.eclipse.php.internal.core.PHPVersion; import org2.eclipse.php.internal.core.ast.match.ASTMatcher; import org2.eclipse.php.internal.core.ast.visitor.Visitor; /** * Represents namespace name: * * <pre>e.g. * * <pre> * MyNamespace; * MyProject\Sub\Level; * namespace\MyProject\Sub\Level; */ public class NamespaceName extends Identifier { protected ASTNode.NodeList<Identifier> segments = new ASTNode.NodeList<Identifier>( ELEMENTS_PROPERTY); /** * Whether the namespace name has '\' prefix, which means it relates to the * global scope */ private boolean global; /** * Whether the namespace name has 'namespace' prefix, which means it relates * to the current namespace scope */ private boolean current; /** * The "namespace" structural property of this node type. */ public static final ChildListPropertyDescriptor ELEMENTS_PROPERTY = new ChildListPropertyDescriptor( NamespaceName.class, "segments", Identifier.class, NO_CYCLE_RISK); //$NON-NLS-1$ public static final SimplePropertyDescriptor GLOBAL_PROPERTY = new SimplePropertyDescriptor( UseStatementPart.class, "global", Boolean.class, MANDATORY); //$NON-NLS-1$ public static final SimplePropertyDescriptor CURRENT_PROPERTY = new SimplePropertyDescriptor( UseStatementPart.class, "current", Boolean.class, MANDATORY); //$NON-NLS-1$ /** * A list of property descriptors (element type: * {@link StructuralPropertyDescriptor}), or null if uninitialized. */ private static final List<StructuralPropertyDescriptor> PROPERTY_DESCRIPTORS; static { List<StructuralPropertyDescriptor> properyList = new ArrayList<StructuralPropertyDescriptor>( 2); properyList.add(NAME_PROPERTY); properyList.add(ELEMENTS_PROPERTY); properyList.add(GLOBAL_PROPERTY); properyList.add(CURRENT_PROPERTY); PROPERTY_DESCRIPTORS = Collections.unmodifiableList(properyList); } public NamespaceName(AST ast) { super(ast); } public NamespaceName(int start, int end, AST ast, Identifier[] segments, boolean global, boolean current) { super(start, end, ast, buildName(segments, global, current)); if (segments == null) { throw new IllegalArgumentException(); } for (Identifier name : segments) { this.segments.add(name); } this.global = global; this.current = current; } @SuppressWarnings({"unchecked", "rawtypes", "unused"}) public NamespaceName(int start, int end, AST ast, List segments, boolean global, boolean current) { super(start, end, ast, buildName((Identifier[]) segments .toArray(new Identifier[segments.size()]), global, current)); if (segments == null) { throw new IllegalArgumentException(); } Iterator<Identifier> it = segments.iterator(); while (it.hasNext()) { this.segments.add(it.next()); } this.global = global; this.current = current; } protected static String buildName(Identifier[] segments, boolean global, boolean current) { StringBuilder buf = new StringBuilder(); if (global) { buf.append('\\'); } else if (current) { buf.append("namespace\\"); //$NON-NLS-1$ } for (int i = 0; i < segments.length; ++i) { if (i > 0) { buf.append('\\'); } buf.append(segments[i].getName()); } return buf.toString(); } public void childrenAccept(Visitor visitor) { for (ASTNode node : this.segments) { node.accept(visitor); } } public void traverseTopDown(Visitor visitor) { accept(visitor); for (ASTNode node : this.segments) { node.traverseTopDown(visitor); } } public void traverseBottomUp(Visitor visitor) { for (ASTNode node : this.segments) { node.traverseBottomUp(visitor); } accept(visitor); } public void toString(StringBuffer buffer, String tab) { buffer.append(tab).append("<NamespaceName"); //$NON-NLS-1$ appendInterval(buffer); buffer.append(" global='").append(global).append('\''); //$NON-NLS-1$ buffer.append(" current='").append(current).append('\''); //$NON-NLS-1$ buffer.append(">\n"); //$NON-NLS-1$ for (ASTNode node : this.segments) { node.toString(buffer, TAB + tab); buffer.append("\n"); //$NON-NLS-1$ } buffer.append(tab).append("</NamespaceName>"); //$NON-NLS-1$ } public void accept0(Visitor visitor) { final boolean visit = visitor.visit(this); if (visit) { childrenAccept(visitor); } visitor.endVisit(this); } public int getType() { return ASTNode.NAMESPACE_NAME; } /** * Returns whether this namespace name has global context (starts with '\') * * @return */ public boolean isGlobal() { return global; } public void setGlobal(boolean global) { preValueChange(GLOBAL_PROPERTY); this.global = global; postValueChange(GLOBAL_PROPERTY); } /** * Returns whether this namespace name has current namespace context (starts * with 'namespace') * * @return */ public boolean isCurrent() { return current; } public void setCurrent(boolean current) { preValueChange(CURRENT_PROPERTY); this.current = current; postValueChange(CURRENT_PROPERTY); } /** * Retrieves names parts of the namespace * * @return segments. If names list is empty, that means that this namespace * is global. */ public List<Identifier> segments() { return this.segments; } /* * (omit javadoc for this method) Method declared on ASTNode. */ public boolean subtreeMatch(ASTMatcher matcher, Object other) { // dispatch to correct overloaded match method return matcher.match(this, other); } /* * (omit javadoc for this method) Method declared on ASTNode. */ @SuppressWarnings("rawtypes") protected ASTNode clone0(AST target) { final List segments = ASTNode.copySubtrees(target, segments()); final boolean global = isGlobal(); final boolean current = isCurrent(); final NamespaceName result = new NamespaceName(this.getStart(), this .getEnd(), target, segments, global, current); return result; } @Override protected List<StructuralPropertyDescriptor> internalStructuralPropertiesForType( PHPVersion apiLevel) { return PROPERTY_DESCRIPTORS; } boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) { if (property == GLOBAL_PROPERTY) { if (get) { return isGlobal(); } else { setGlobal(value); return false; } } if (property == CURRENT_PROPERTY) { if (get) { return isCurrent(); } else { setCurrent(value); return false; } } return super.internalGetSetBooleanProperty(property, get, value); } /* * (omit javadoc for this method) Method declared on ASTNode. */ @SuppressWarnings({ "unchecked", "rawtypes" }) final List internalGetChildListProperty(ChildListPropertyDescriptor property) { if (property == ELEMENTS_PROPERTY) { return segments(); } // allow default implementation to flag the error return super.internalGetChildListProperty(property); } }