001: /*
002: The contents of this file are subject to the Common Public Attribution License
003: Version 1.0 (the "License"); you may not use this file except in compliance with
004: the License. You may obtain a copy of the License at
005: http://www.projity.com/license . The License is based on the Mozilla Public
006: License Version 1.1 but Sections 14 and 15 have been added to cover use of
007: software over a computer network and provide for limited attribution for the
008: Original Developer. In addition, Exhibit A has been modified to be consistent
009: with Exhibit B.
010:
011: Software distributed under the License is distributed on an "AS IS" basis,
012: WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
013: specific language governing rights and limitations under the License. The
014: Original Code is OpenProj. The Original Developer is the Initial Developer and
015: is Projity, Inc. All portions of the code written by Projity are Copyright (c)
016: 2006, 2007. All Rights Reserved. Contributors Projity, Inc.
017:
018: Alternatively, the contents of this file may be used under the terms of the
019: Projity End-User License Agreeement (the Projity License), in which case the
020: provisions of the Projity License are applicable instead of those above. If you
021: wish to allow use of your version of this file only under the terms of the
022: Projity License and not to allow others to use your version of this file under
023: the CPAL, indicate your decision by deleting the provisions above and replace
024: them with the notice and other provisions required by the Projity License. If
025: you do not delete the provisions above, a recipient may use your version of this
026: file under either the CPAL or the Projity License.
027:
028: [NOTE: The text of this license may differ slightly from the text of the notices
029: in Exhibits A and B of the license at http://www.projity.com/license. You should
030: use the latest text at http://www.projity.com/license for your modifications.
031: You may not remove this license text from the source files.]
032:
033: Attribution Information: Attribution Copyright Notice: Copyright © 2006, 2007
034: Projity, Inc. Attribution Phrase (not exceeding 10 words): Powered by OpenProj,
035: an open source solution from Projity. Attribution URL: http://www.projity.com
036: Graphic Image as provided in the Covered Code as file: openproj_logo.png with
037: alternatives listed on http://www.projity.com/logo
038:
039: Display of Attribution Information is required in Larger Works which are defined
040: in the CPAL as a work which combines Covered Code or portions thereof with code
041: not governed by the terms of the CPAL. However, in addition to the other notice
042: obligations, all copies of the Covered Code in Executable and Source Code form
043: distributed must, as a form of attribution of the original author, include on
044: each user interface screen the "OpenProj" logo visible to all users. The
045: OpenProj logo should be located horizontally aligned with the menu bar and left
046: justified on the top left of the screen adjacent to the File menu. The logo
047: must be at least 100 x 25 pixels. When users click on the "OpenProj" logo it
048: must direct them back to http://www.projity.com.
049: */
050: package com.projity.pm.graphic.model.cache;
051:
052: import java.util.ArrayList;
053: import java.util.Collection;
054: import java.util.HashSet;
055: import java.util.Iterator;
056: import java.util.List;
057: import java.util.ListIterator;
058: import java.util.Set;
059:
060: import com.projity.pm.graphic.model.event.CacheEvent;
061:
062: /**
063: *
064: */
065: public class NodeCache extends CellCache {
066:
067: public NodeCache() {
068: super ();
069: }
070:
071: public void updateVisibleElements(Set updates) {
072: //dumpVoids();
073: VisibleNodes v;
074: HashSet u = new HashSet();
075: for (Iterator i = visibleElements.iterator(); i.hasNext();) {
076: v = (VisibleNodes) i.next();
077: u.clear();
078: u.addAll(updates);
079: updateVisibleElements(v, u);
080: }
081: }
082:
083: public void updateVisibleElements(VisibleNodes v, Set updates) {
084: // long t0=System.currentTimeMillis();
085:
086: ArrayList visibleElements = v.getElements();
087: ArrayList oldList = (ArrayList) visibleElements.clone();
088:
089: visibleElements.clear();
090: int minLevel = -1;
091: for (Iterator i = getCacheIterator(); i.hasNext();) {
092: GraphicNode node = (GraphicNode) i.next();
093: if (minLevel != -1 && node.getLevel() > minLevel)
094: continue;
095: minLevel = -1;
096: visibleElements.add(node);
097: if (node.isComposite() && node.isCollapsed())
098: minLevel = node.getLevel();
099: }
100: // long t1=System.currentTimeMillis();
101: // System.out.println("\t\tcache NodeCache#1 ran in "+(t1-t0)+"ms");
102:
103: v.applyTransformer();
104: // t0=System.currentTimeMillis();
105: // System.out.println("\t\tcache NodeCache#2 ran in "+(t0-t1)+"ms");
106:
107: applyUpdates(oldList, visibleElements, updates, v.getEvents(),
108: this );
109: // t1=System.currentTimeMillis();
110: // System.out.println("\t\tcache NodeCache#3 ran in "+(t1-t0)+"ms");
111:
112: }
113:
114: //for schedule caching option
115: // public void updateCachedSchedule(){
116: // GraphicNode node;
117: // for (Iterator i=cache.iterator();i.hasNext();){
118: // node=(GraphicNode)i.next();
119: // node.updateScheduleCache();
120: // }
121: // }
122:
123: public static void applyUpdates(ArrayList oldList,
124: ArrayList newList, Set updates, List events, Object source) {
125: ArrayList o = (ArrayList) oldList.clone();
126: ArrayList n = (ArrayList) newList.clone();
127:
128: // long t0=System.currentTimeMillis();
129: ArrayList removeList = null;
130: ArrayList removeNodeList = null;
131: //if (removeFunctor!=null){
132: removeList = new ArrayList();
133: removeNodeList = new ArrayList();
134: createRemoveDiff(o, n, removeNodeList, removeList, updates);
135: if (removeList.size() > 0) {
136: //removeFunctor.execute(removeNodeList,removeList);
137: events.add(new CacheEvent(source, CacheEvent.NODES_REMOVED,
138: (List) removeNodeList.clone(), (List) removeList
139: .clone()));
140: }
141: //}
142: // long t1=System.currentTimeMillis();
143: // System.out.println("\t\t\tcache applyUpdates#1 ran in "+(t1-t0)+"ms");
144:
145: ArrayList insertList = null;
146: ArrayList insertNodeList = null;
147: //if (insertFunctor!=null){
148: insertList = new ArrayList();
149: insertNodeList = new ArrayList();
150: createRemoveDiff(n, o, insertNodeList, insertList, updates);
151: if (insertList.size() > 0) {
152: events.add(new CacheEvent(source,
153: CacheEvent.NODES_INSERTED, (List) insertNodeList
154: .clone(), (List) insertList.clone()));
155: //insertFunctor.execute(insertNodeList,insertList);
156: }
157: //}
158: // t0=System.currentTimeMillis();
159: // System.out.println("\t\t\tcache applyUpdates#2 ran in "+(t0-t1)+"ms");
160:
161: //if (removeFunctor!=null&&insertFunctor!=null){
162: removeList.clear();
163: removeNodeList.clear();
164: insertList.clear();
165: insertNodeList.clear();
166: createPermutationDiff(o, n, removeNodeList, insertNodeList,
167: removeList, insertList, updates);
168: if (removeList.size() > 0) {
169: events.add(new CacheEvent(source, CacheEvent.NODES_REMOVED,
170: removeNodeList, removeList));
171: //removeFunctor.execute(removeNodeList,removeList);
172: }
173: if (insertList.size() > 0) {
174: events.add(new CacheEvent(source,
175: CacheEvent.NODES_INSERTED, (List) insertNodeList
176: .clone(), (List) insertList.clone()));
177: //insertFunctor.execute(insertNodeList,insertList);
178: }
179: // t1=System.currentTimeMillis();
180: // System.out.println("\t\t\tcache applyUpdates#3 ran in "+(t1-t0)+"ms");
181: //}
182:
183: //if (updateFunctor!=null){
184: insertList.clear();
185: insertNodeList.clear();
186: createUpdateDiff(newList, insertNodeList, insertList, updates);
187: if (insertList.size() > 0) {
188: events.add(new CacheEvent(source, CacheEvent.NODES_CHANGED,
189: insertNodeList, insertList));
190: //updateFunctor.execute(insertNodeList,insertList);
191: }
192: //}
193: // t0=System.currentTimeMillis();
194: // System.out.println("\t\t\tcache applyUpdates#4 ran in "+(t0-t1)+"ms");
195:
196: }
197:
198: protected static void createRemoveDiff(ArrayList oldList,
199: ArrayList newList, ArrayList nodeDiff,
200: ArrayList intervaldiff, Set updates) {
201: Collection newCol = getContainsCollection(newList);
202: int row = 0;
203: int begin = -1;
204: int end = -1;
205: Object current;
206: for (ListIterator i = oldList.listIterator(); i.hasNext(); row++) {
207: if (!newCol.contains(current = i.next())) {
208: nodeDiff.add(current);
209: if (updates != null)
210: updates.remove(current); //to avoid remove/insert followed by update
211: if (begin == -1) {
212: begin = row;
213: end = row;
214: } else {
215: if (row == end + 1)
216: end = row;
217: else {
218: intervaldiff.add(new CacheInterval(begin, end));
219: begin = row;
220: end = row;
221: }
222: }
223: i.remove();
224: }
225: }
226: if (begin != -1)
227: intervaldiff.add(new CacheInterval(begin, end));
228: }
229:
230: protected static void createPermutationDiff(ArrayList oldList,
231: ArrayList newList, ArrayList removeNodeList,
232: ArrayList insertNodeList, ArrayList removeIntervalList,
233: ArrayList insertIntervalList, Set updates) {
234: //oldList and newList have the same size and contains the same elements
235: ListIterator o = oldList.listIterator();
236: ListIterator n = newList.listIterator();
237: int startRow = -1;
238: ;
239: for (int row = 0; o.hasNext(); row++) {
240: Object oelement = o.next();
241: Object nelement = n.next();
242: if (oelement.equals(nelement)) {
243: if (startRow != -1 && startRow < row) {
244: CacheInterval interval = new CacheInterval(
245: startRow, row - 1);
246: removeIntervalList.add(interval);
247: insertIntervalList.add(interval);
248: startRow = -1;
249: }
250: } else {
251: if (startRow == -1)
252: startRow = row;
253: removeNodeList.add(oelement);
254: insertNodeList.add(nelement);
255: }
256: }
257: if (startRow != -1) {
258: CacheInterval interval = new CacheInterval(startRow,
259: oldList.size() - 1);
260: removeIntervalList.add(interval);
261: insertIntervalList.add(interval);
262: }
263: }
264:
265: protected static void createUpdateDiff(ArrayList newList,
266: ArrayList nodeDiff, ArrayList diff, Set updates) {
267: if (updates != null && updates.size() > 0) {
268: Collection updatesCol = getContainsCollection(updates);
269: int begin = -1;
270: int end = -1;
271: int row = 0;
272: Object current;
273: for (Iterator i = newList.iterator(); i.hasNext(); row++) {
274: if (updatesCol.contains(current = i.next())) {
275: nodeDiff.add(current);
276: if (begin == -1) {
277: begin = row;
278: end = row;
279: } else {
280: if (row == end + 1)
281: end = row;
282: else {
283: diff.add(new CacheInterval(begin, end));
284: begin = row;
285: end = row;
286: }
287: }
288: }
289: }
290: if (begin != -1)
291: diff.add(new CacheInterval(begin, end));
292: }
293:
294: }
295:
296: public Object getBase(Object base) {
297: return ((GraphicNode) base).getNode();
298: }
299:
300: //
301: // private void dumpVoids(){
302: // Object current;
303: // List vn;
304: // GraphicNode node;
305: // for (Iterator i=voidNodes.keySet().iterator();i.hasNext();){
306: // current=i.next();
307: // System.out.println(current+":");
308: // vn=(List)voidNodes.get(current);
309: // for (Iterator j=vn.iterator();j.hasNext();){
310: // node=(GraphicNode)j.next();
311: // System.out.println("\t"+node+": "+node.getLevel());
312: // }
313: // }
314: // }
315:
316: protected void fireEvents(Object source, List nodeEvents,
317: List edgeEvents) {
318: if (nodeEvents.size() > 0 || edgeEvents.size() > 0)
319: for (Iterator i = visibleElements.iterator(); i.hasNext();)
320: ((VisibleNodes) i.next())
321: .fireGraphicNodesCompositeEvent(source,
322: nodeEvents, edgeEvents);
323: }
324:
325: // protected void fireScheduleEvent(Object source, ScheduleEvent scheduleEvent) {
326: // for (Iterator i=visibleElements.iterator();i.hasNext();)
327: // ((VisibleNodes)i.next()).fireGraphicNodesCompositeEvent(source,null,null,scheduleEvent,null);
328: // }
329: // protected void fireObjectEvent(Object source, ObjectEvent objectEvent) {
330: // for (Iterator i=visibleElements.iterator();i.hasNext();)
331: // ((VisibleNodes)i.next()).fireGraphicNodesCompositeEvent(source,null,null,null, objectEvent);
332: // }
333: public void fireEvents(Object source, VisibleNodes nodes) {
334: List nodeEvents = nodes.getEvents();
335: List edgeEvents = nodes.getVisibleDependencies().getEvents();
336: if (nodeEvents.size() > 0 || edgeEvents.size() > 0) {
337: nodes.fireGraphicNodesCompositeEvent(source, nodeEvents,
338: edgeEvents);
339: nodes.clearEvents();
340: nodes.getVisibleDependencies().clearEvents();
341:
342: }
343: }
344:
345: public void fireEvents(Object source) {
346: for (Iterator i = visibleElements.iterator(); i.hasNext();) {
347: VisibleNodes v = (VisibleNodes) i.next();
348: List nodeEvents = v.getEvents();
349: List edgeEvents = v.getVisibleDependencies().getEvents();
350: if (nodeEvents.size() > 0 || edgeEvents.size() > 0) {
351: v.fireGraphicNodesCompositeEvent(source, nodeEvents,
352: edgeEvents);
353: v.clearEvents();
354: v.getVisibleDependencies().clearEvents();
355: }
356: }
357: }
358:
359: }
|