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.vmd.api.model;
042:
043: import org.openide.util.Utilities;
044: import org.openide.util.TopologicalSortException;
045:
046: import java.util.*;
047:
048: /**
049: * @author David Kaspar
050: */
051: final class PresenterEventManager implements PresenterEvent {
052:
053: private ArrayList<DependencyItem> dependencies;
054:
055: private HashSet<PresenterListener> changed;
056:
057: private List<PresenterListener> topology;
058: private Map<PresenterListener, HashSet<PresenterListener>> dependencyMap;
059:
060: PresenterEventManager() {
061: dependencies = new ArrayList<DependencyItem>();
062: }
063:
064: void firePresenterChanged(PresenterListener listener) {
065: changed.add(listener);
066: }
067:
068: void addPresenterListener(DesignComponent component,
069: Class<? extends Presenter> presenterClass,
070: PresenterListener listener) {
071: dependencies.add(new DependencyItem(component, presenterClass,
072: listener));
073: topology = null;
074: }
075:
076: void removePresenterListener(DesignComponent component,
077: Class<? extends Presenter> presenterClass,
078: PresenterListener listener) {
079: dependencies.remove(new DependencyItem(component,
080: presenterClass, listener));
081: topology = null;
082: }
083:
084: void removeAllPresenterListeners(PresenterListener listener) {
085: for (Iterator<DependencyItem> i = dependencies.iterator(); i
086: .hasNext();) {
087: DependencyItem di = i.next();
088: if (di.listener == listener) {
089: i.remove();
090: topology = null;
091: }
092: }
093: }
094:
095: void prepare(boolean forceUpdateTopology) {
096: changed = new HashSet<PresenterListener>(100);
097: if (forceUpdateTopology)
098: topology = null;
099: }
100:
101: void execute() {
102: if (topology == null)
103: createTopology();
104: List<PresenterListener> _topology = this .topology;
105: Map<PresenterListener, HashSet<PresenterListener>> _dependencyMap = this .dependencyMap;
106:
107: HashSet<PresenterListener> marked = new HashSet<PresenterListener>(
108: 100);
109: for (PresenterListener presenterListener : changed) {
110: if (_topology.contains(presenterListener))
111: marked.add(presenterListener);
112: else
113: presenterListener.presenterChanged(this );
114: }
115:
116: for (PresenterListener presenterListener : _topology) {
117: if (marked.contains(presenterListener))
118: presenterListener.presenterChanged(this );
119: if (changed.contains(presenterListener)) {
120: HashSet<PresenterListener> set = _dependencyMap
121: .get(presenterListener);
122: if (set == null)
123: continue;
124: for (PresenterListener listener : set)
125: marked.add(listener);
126: }
127: }
128: }
129:
130: private void createTopology() {
131: HashSet<PresenterListener> unsortedSet = new HashSet<PresenterListener>();
132: HashMap<PresenterListener, HashSet<PresenterListener>> _dependencyMap = new HashMap<PresenterListener, HashSet<PresenterListener>>();
133:
134: for (DependencyItem item : dependencies)
135: item.setupTopology(unsortedSet, _dependencyMap);
136:
137: try {
138: this .topology = Utilities.topologicalSort(unsortedSet,
139: _dependencyMap);
140: this .dependencyMap = _dependencyMap;
141: } catch (TopologicalSortException e) {
142: Debug.warning(e);
143: System.err
144: .println("TopologicalSortException: Topological Sets:"
145: + Arrays.toString(e.topologicalSets())); // NOI18N
146: System.err
147: .println("TopologicalSortException: Unsortable Set:"
148: + Arrays.toString(e.unsortableSets())); // NOI18N
149: this .topology = Collections.emptyList();
150: this .dependencyMap = Collections.emptyMap();
151: }
152: }
153:
154: public boolean isPresenterChanged(DesignComponent component,
155: Class<? extends Presenter> presenterClass) {
156: assert component != null && presenterClass != null;
157: for (Presenter presenter : component
158: .getPresenters(presenterClass))
159: if (presenter instanceof DynamicPresenter)
160: if (changed.contains(((DynamicPresenter) presenter)
161: .getPresenterListener()))
162: return true;
163: return false;
164: }
165:
166: private class DependencyItem {
167:
168: private DesignComponent component;
169: private Class<? extends Presenter> presenterClass;
170: private PresenterListener listener;
171:
172: public DependencyItem(DesignComponent component,
173: Class<? extends Presenter> presenterClass,
174: PresenterListener listener) {
175: assert component != null && presenterClass != null
176: && listener != null;
177: this .component = component;
178: this .presenterClass = presenterClass;
179: this .listener = listener;
180: }
181:
182: @Override
183: public boolean equals(Object o) {
184: if (this == o)
185: return true;
186: if (o == null || getClass() != o.getClass())
187: return false;
188: final DependencyItem di = (DependencyItem) o;
189:
190: if (component != di.component)
191: return false;
192: if (!presenterClass.equals(di.presenterClass))
193: return false;
194: return listener == di.listener;
195: }
196:
197: @Override
198: public int hashCode() {
199: int result;
200: result = (component != null ? component.hashCode() : 0);
201: result = 29
202: * result
203: + (presenterClass != null ? presenterClass
204: .hashCode() : 0);
205: result = 29 * result
206: + (listener != null ? listener.hashCode() : 0);
207: return result;
208: }
209:
210: private void setupTopology(
211: HashSet<PresenterListener> unsortedSet,
212: HashMap<PresenterListener, HashSet<PresenterListener>> dependencyMap) {
213: Presenter presenter = component
214: .getPresenter(presenterClass);
215: if (!(presenter instanceof DynamicPresenter))
216: return;
217: PresenterListener presenterListener = ((DynamicPresenter) presenter)
218: .getPresenterListener();
219: if (presenterListener == listener)
220: return;
221:
222: unsortedSet.add(presenterListener);
223: unsortedSet.add(listener);
224:
225: HashSet<PresenterListener> set = dependencyMap
226: .get(presenterListener);
227: if (set == null) {
228: set = new HashSet<PresenterListener>();
229: dependencyMap.put(presenterListener, set);
230: }
231: set.add(listener);
232: }
233:
234: }
235:
236: }
|