001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.php.model.impl;
042:
043: import java.util.LinkedList;
044: import java.util.List;
045:
046: import org.netbeans.api.languages.ASTItem;
047: import org.netbeans.api.languages.ASTNode;
048: import org.netbeans.api.languages.ASTToken;
049: import org.netbeans.modules.php.model.CallExpression;
050: import org.netbeans.modules.php.model.ClassConst;
051: import org.netbeans.modules.php.model.ClassFunctionDefinition;
052: import org.netbeans.modules.php.model.ClassMemberReference;
053: import org.netbeans.modules.php.model.ObjectDefinition;
054: import org.netbeans.modules.php.model.SourceElement;
055: import org.netbeans.modules.php.model.VariableAppearance;
056: import org.netbeans.modules.php.model.refs.ReferenceResolver;
057:
058: /**
059: * This reference could be reference to class member.
060: * This class member can be constant or static member ( attribute or method).
061: * So method get() can return two types : ClassConst or ClassFunctionDefinition.
062: * @author ads
063: *
064: */
065: class ClassMemberReferenceImpl<T extends SourceElement> extends
066: ReferenceImpl<T> implements ClassMemberReference<T> {
067:
068: ClassMemberReferenceImpl(SourceElementImpl source,
069: ASTNode identifierNode, Class<T> clazz) {
070: super (source, identifierNode.getAsText().trim(), clazz);
071: myNode = identifierNode;
072: }
073:
074: public String getMemberName() {
075: if (myMemberName == null) {
076: initIds();
077: }
078: return myMemberName;
079: }
080:
081: /* (non-Javadoc)
082: * @see org.netbeans.modules.php.model.ClassReference#getObject()
083: */
084: public ObjectDefinition getObject() {
085: T result = get();
086: if (result == null) {
087: return resolveObject();
088: } else {
089: return findOwner(result);
090: }
091: }
092:
093: /* (non-Javadoc)
094: * @see org.netbeans.modules.php.model.ClassReference#getObjectName()
095: */
096: public String getObjectName() {
097: if (myClassName == null) {
098: initIds();
099: }
100: return myClassName;
101: }
102:
103: /* (non-Javadoc)
104: * @see org.netbeans.modules.php.model.Reference#get()
105: */
106: public T get() {
107: String id = getIdentifier();
108: T result = null;
109: if (id.contains("$")) {
110: result = get(VariableAppearance.class);
111: } else {
112: SourceElement parent = getSource().getParent();
113: if (parent instanceof CallExpression) {
114: /*
115: * Do not try search method in interface because interface
116: * cannot have static methods.
117: */
118: result = get(ClassFunctionDefinition.class);
119: } else {
120: result = get(ClassConst.class);
121: }
122: }
123: return result;
124: }
125:
126: private ObjectDefinition resolveObject() {
127: if (myObject != null) {
128: return myObject;
129: }
130: List<ReferenceResolver> resolvers = getResolvers(ObjectDefinition.class);
131: List<ObjectDefinition> result = null;
132: for (ReferenceResolver referenceResolver : resolvers) {
133: List<ObjectDefinition> list = referenceResolver.resolve(
134: getSource(), getObjectName(),
135: ObjectDefinition.class, true);
136: result = add(result, list);
137: }
138: if (result != null && result.size() > 0) {
139: return result.get(result.size() - 1);
140: }
141: return null;
142: }
143:
144: private T get(Class<? extends SourceElement> clazz) {
145: List<ReferenceResolver> classResolvers = getResolvers(clazz);
146: for (ReferenceResolver referenceResolver : classResolvers) {
147: List<? extends SourceElement> statements = referenceResolver
148: .resolve(getSource(), getIdentifier(), clazz, true);
149: for (SourceElement statement : statements) {
150: if (getType().isAssignableFrom(
151: statement.getElementType())) {
152: T result = getType().cast(statements.get(0));
153: return result;
154: }
155: }
156: }
157: return null;
158: }
159:
160: private ObjectDefinition findOwner(T result) {
161: SourceElement current = result;
162: while (current != null) {
163: if (current instanceof ObjectDefinition) {
164: return (ObjectDefinition) current;
165: }
166: current = current.getParent();
167: }
168: return null;
169: }
170:
171: private List<ObjectDefinition> add(List<ObjectDefinition> list,
172: List<ObjectDefinition> elements) {
173: if (list == null) {
174: list = new LinkedList<ObjectDefinition>();
175: }
176: list.addAll(elements);
177: return list;
178: }
179:
180: private void initIds() {
181: List<ASTItem> children = myNode.getChildren();
182: byte count = 0;
183: boolean nodeIsFound = false;
184: for (ASTItem item : children) {
185: if (item instanceof ASTToken) {
186: ASTToken token = (ASTToken) item;
187: if (!token.getTypeName().equals(Utils.IDENTIFIER)) {
188: continue;
189: }
190: if (count > 0) {
191: myMemberName = token.getIdentifier().trim();
192: } else {
193: myClassName = token.getIdentifier().trim();
194: }
195: assert count < 2;
196: count++;
197: }
198: if (item instanceof ASTNode) {
199: assert !nodeIsFound;
200: myMemberName = ((ASTNode) item).getAsText().trim();
201: nodeIsFound = true;
202: }
203: }
204: }
205:
206: private String myClassName;
207:
208: private String myMemberName;
209:
210: private ObjectDefinition myObject;
211:
212: private final ASTNode myNode;
213:
214: }
|