001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.ui.browsing;
011:
012: import java.util.ArrayList;
013: import java.util.HashMap;
014: import java.util.List;
015: import java.util.Map;
016:
017: import org.eclipse.core.runtime.Assert;
018:
019: import org.eclipse.jface.util.IPropertyChangeListener;
020: import org.eclipse.jface.util.PropertyChangeEvent;
021: import org.eclipse.jface.viewers.StructuredViewer;
022: import org.eclipse.jface.viewers.TreeViewer;
023: import org.eclipse.jface.viewers.Viewer;
024:
025: import org.eclipse.jdt.core.ElementChangedEvent;
026: import org.eclipse.jdt.core.IElementChangedListener;
027: import org.eclipse.jdt.core.IJavaElement;
028: import org.eclipse.jdt.core.IJavaElementDelta;
029: import org.eclipse.jdt.core.IJavaProject;
030: import org.eclipse.jdt.core.IPackageFragment;
031: import org.eclipse.jdt.core.JavaCore;
032: import org.eclipse.jdt.core.JavaModelException;
033:
034: import org.eclipse.jdt.internal.ui.JavaPlugin;
035:
036: abstract class LogicalPackagesProvider implements
037: IPropertyChangeListener, IElementChangedListener {
038:
039: protected static final Object[] NO_CHILDREN = new Object[0];
040:
041: protected Map fMapToLogicalPackage;
042: protected Map fMapToPackageFragments;
043: protected boolean fCompoundState;
044: protected StructuredViewer fViewer;
045: protected boolean fInputIsProject;
046:
047: public LogicalPackagesProvider(StructuredViewer viewer) {
048: fViewer = viewer;
049: fCompoundState = isInCompoundState();
050: fInputIsProject = true;
051: fMapToLogicalPackage = new HashMap();
052: fMapToPackageFragments = new HashMap();
053: JavaPlugin.getDefault().getPreferenceStore()
054: .addPropertyChangeListener(this );
055: }
056:
057: /**
058: * Adds the given fragments to the internal map.
059: * Existing fragments will be replaced by the new ones.
060: *
061: * @param packageFragments the package fragments to add
062: */
063: protected void addFragmentsToMap(IPackageFragment[] packageFragments) {
064: for (int i = 0; i < packageFragments.length; i++) {
065: IPackageFragment fragment = packageFragments[i];
066: String key = getKey(fragment);
067: fMapToPackageFragments.put(key, fragment);
068: }
069: }
070:
071: protected String getKey(IPackageFragment fragment) {
072: return fragment.getElementName()
073: + fragment.getJavaProject().getElementName();
074: }
075:
076: /**
077: * Returns the logical package for the given package fragment
078: * or <code>null</code> if it is not grouped by logical package.
079: *
080: * @param fragment the package fragment
081: * @return the logical package
082: */
083: public LogicalPackage findLogicalPackage(IPackageFragment fragment) {
084: Assert.isNotNull(fragment);
085: if (isInCompoundState())
086: return (LogicalPackage) fMapToLogicalPackage
087: .get(getKey(fragment));
088: else
089: return null;
090: }
091:
092: /**
093: * Combines packages with same names into a logical package which will
094: * be added to the resulting array. If a package is not yet in this content
095: * provider then the package fragment is added to the resulting array.
096: *
097: * @param packageFragments the package fragments to combine
098: * @return an array with combined (logical) packages and package fragments
099: */
100: protected Object[] combineSamePackagesIntoLogialPackages(
101: IPackageFragment[] packageFragments) {
102:
103: if (!fCompoundState)
104: return packageFragments;
105:
106: List newChildren = new ArrayList();
107:
108: for (int i = 0; i < packageFragments.length; i++) {
109: IPackageFragment fragment = packageFragments[i];
110:
111: if (fragment == null)
112: continue;
113:
114: LogicalPackage lp = findLogicalPackage(fragment);
115:
116: if (lp != null) {
117: if (lp.belongs(fragment)) {
118: lp.add(fragment);
119: }
120: if (!newChildren.contains(lp))
121: newChildren.add(lp);
122:
123: } else {
124: String key = getKey(fragment);
125: IPackageFragment frag = (IPackageFragment) fMapToPackageFragments
126: .get(key);
127: if (frag != null && !fragment.equals(frag)) {
128: lp = new LogicalPackage(frag);
129: lp.add(fragment);
130: newChildren.remove(frag);
131: newChildren.add(lp);
132: fMapToLogicalPackage.put(key, lp);
133: fMapToPackageFragments.remove(frag);
134: } else {
135: fMapToPackageFragments.put(key, fragment);
136: newChildren.add(fragment);
137: }
138: }
139: }
140: return newChildren.toArray();
141: }
142:
143: /**
144: * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
145: */
146: public void propertyChange(PropertyChangeEvent event) {
147: if (fCompoundState == isInCompoundState())
148: return;
149: else
150: fCompoundState = isInCompoundState();
151:
152: if (!isInCompoundState()) {
153: fMapToLogicalPackage.clear();
154: fMapToPackageFragments.clear();
155: }
156:
157: if (fViewer instanceof TreeViewer) {
158: TreeViewer viewer = (TreeViewer) fViewer;
159: Object[] expandedObjects = viewer.getExpandedElements();
160: viewer.refresh();
161: viewer.setExpandedElements(expandedObjects);
162: } else
163: fViewer.refresh();
164: }
165:
166: protected boolean isInCompoundState() {
167: // XXX: for now we don't offer a preference might become a view menu entry
168: // return AppearancePreferencePage.logicalPackagesInPackagesView();
169: return true;
170: }
171:
172: public void dispose() {
173: JavaPlugin.getDefault().getPreferenceStore()
174: .removePropertyChangeListener(this );
175: fMapToLogicalPackage = null;
176: fMapToPackageFragments = null;
177: }
178:
179: /*
180: * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
181: */
182: public void inputChanged(Viewer viewer, Object oldInput,
183: Object newInput) {
184: if (newInput != null) {
185: JavaCore.addElementChangedListener(this );
186: } else {
187: JavaCore.removeElementChangedListener(this );
188: }
189: fInputIsProject = (newInput instanceof IJavaProject);
190:
191: if (viewer instanceof StructuredViewer)
192: fViewer = (StructuredViewer) viewer;
193: }
194:
195: abstract protected void processDelta(IJavaElementDelta delta)
196: throws JavaModelException;
197:
198: /*
199: * @since 3.0
200: */
201: protected boolean isClassPathChange(IJavaElementDelta delta) {
202:
203: // need to test the flags only for package fragment roots
204: if (delta.getElement().getElementType() != IJavaElement.PACKAGE_FRAGMENT_ROOT)
205: return false;
206:
207: int flags = delta.getFlags();
208: return (delta.getKind() == IJavaElementDelta.CHANGED
209: && ((flags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) != 0)
210: || ((flags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0) || ((flags & IJavaElementDelta.F_REORDER) != 0));
211: }
212:
213: /*
214: * @see org.eclipse.jdt.core.IElementChangedListener#elementChanged(org.eclipse.jdt.core.ElementChangedEvent)
215: */
216: public void elementChanged(ElementChangedEvent event) {
217: try {
218: processDelta(event.getDelta());
219: } catch (JavaModelException e) {
220: JavaPlugin.log(e);
221: }
222: }
223:
224: }
|