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: * Portions Copyrighted 2007 Sun Microsystems, Inc.
027: */
028: package org.netbeans.modules.cnd.gotodeclaration.element.providers;
029:
030: import java.util.ArrayList;
031: import java.util.Collection;
032: import java.util.Collections;
033: import java.util.HashMap;
034: import java.util.HashSet;
035: import java.util.Map;
036: import java.util.Set;
037: import org.netbeans.api.project.Project;
038: import org.netbeans.modules.cnd.api.model.CsmModelAccessor;
039: import org.netbeans.modules.cnd.api.model.CsmProject;
040: import org.netbeans.modules.cnd.gotodeclaration.element.spi.ElementDescriptor;
041: import org.netbeans.modules.cnd.gotodeclaration.element.spi.ElementProvider;
042: import org.netbeans.modules.cnd.gotodeclaration.util.NameMatcher;
043: import org.netbeans.modules.cnd.gotodeclaration.util.NameMatcherFactory;
044: import org.netbeans.spi.jumpto.type.SearchType;
045:
046: /**
047: * A common base class for several providers
048: * @author Vladimir Kvashin
049: */
050: public abstract class BaseProvider implements ElementProvider {
051:
052: protected interface ResultSet {
053: public void add(ElementDescriptor descriptor);
054:
055: public Collection<? extends ElementDescriptor> getResult();
056: }
057:
058: protected abstract static class ProviderDelegate {
059:
060: protected class ResultSetImpl implements ResultSet {
061:
062: private Map<ElementDescriptor, Boolean> data = new HashMap<ElementDescriptor, Boolean>();
063:
064: public void add(ElementDescriptor descriptor) {
065: // There might be several instances that correspond to the same declaration (IZ #116478);
066: // in this case instance that belongs to non-artificial project is stronger
067: if (!data.containsKey(descriptor)
068: || !isArtificial(currentProject)) {
069: data.put(descriptor, Boolean.TRUE);
070: }
071: }
072:
073: public Collection<? extends ElementDescriptor> getResult() {
074: return new ArrayList<ElementDescriptor>(data.keySet());
075: }
076:
077: private boolean isArtificial(CsmProject project) {
078: return project != null && project.isArtificial();
079: }
080:
081: }
082:
083: private boolean isCancelled = false;
084:
085: protected static final boolean PROCESS_LIBRARIES = true; // Boolean.getBoolean("cnd.type.provider.libraries");
086: protected static final boolean TRACE = Boolean
087: .getBoolean("cnd.goto.fv.trace");
088:
089: /** To not process same libararies twice */
090: private Set<CsmProject> processedProjects = new HashSet<CsmProject>();
091:
092: /** Project that is currently being processed. */
093: private CsmProject currentProject;
094:
095: public void cancel() {
096: isCancelled = true;
097: }
098:
099: protected final boolean isCancelled() {
100: return isCancelled;
101: }
102:
103: protected abstract void processProject(CsmProject project,
104: ResultSet result, NameMatcher comparator);
105:
106: public Collection<? extends ElementDescriptor> getElements(
107: Project project, String text, SearchType type,
108: boolean first) {
109:
110: if (TRACE)
111: System.err.printf("%s.getElements(%s, %s, %s)\n",
112: getBriefClassName(), project, text, type);
113:
114: NameMatcher comparator = NameMatcherFactory
115: .createNameMatcher(text, type);
116: if (comparator == null) {
117: return Collections.emptyList();
118: }
119:
120: if (first) {
121: processedProjects.clear();
122: }
123: ResultSet result = new ResultSetImpl();
124: CsmProject csmProject = CsmModelAccessor.getModel()
125: .getProject(project);
126: if (csmProject != null) {
127: // we should check the processed project here:
128: // otherwise when some of the required projects are open,we'll have duplicates
129: if (!processedProjects.contains(csmProject)) {
130: processedProjects.add(csmProject);
131: currentProject = csmProject;
132: processProject(csmProject, result, comparator);
133: currentProject = null;
134: if (PROCESS_LIBRARIES) {
135: for (CsmProject lib : csmProject.getLibraries()) {
136: if (isCancelled()) {
137: break;
138: }
139: if (lib.isArtificial()) {
140: if (!processedProjects.contains(lib)) {
141: processedProjects.add(lib);
142: currentProject = lib;
143: processProject(lib, result,
144: comparator);
145: currentProject = null;
146: }
147: }
148: }
149: }
150: }
151: }
152: return result.getResult();
153: }
154:
155: public void cleanup() {
156: processedProjects.clear();
157: currentProject = null;
158: }
159:
160: private String getBriefClassName() {
161: String name = getClass().getName();
162: int pos = name.lastIndexOf('.');
163: return (pos >= 0) ? name.substring(pos + 1) : name;
164: }
165:
166: }
167:
168: private ProviderDelegate delegate;
169:
170: protected abstract ProviderDelegate createDelegate();
171:
172: public void cancel() {
173: ProviderDelegate oldDelegate = null;
174: synchronized (this ) {
175: if (delegate != null) {
176: oldDelegate = delegate;
177: delegate = null;
178: }
179: }
180: if (oldDelegate != null) {
181: oldDelegate.cancel();
182: }
183: }
184:
185: public boolean isSuitable() {
186: return !CsmModelAccessor.getModel().projects().isEmpty();
187: }
188:
189: public Collection<? extends ElementDescriptor> getElements(
190: Project project, String text, SearchType type, boolean first) {
191: cancel();
192: delegate = createDelegate();
193: return delegate.getElements(project, text, type, first);
194: }
195:
196: public void cleanup() {
197: ProviderDelegate oldDelegate = null;
198: synchronized (this) {
199: if (delegate != null) {
200: oldDelegate = delegate;
201: delegate = null;
202: }
203: }
204: if (oldDelegate != null) {
205: oldDelegate.cancel();
206: oldDelegate.cleanup();
207: }
208:
209: }
210: }
|