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.grouping.core.model;
051:
052: import java.util.ArrayList;
053: import java.util.Enumeration;
054: import java.util.HashMap;
055: import java.util.Iterator;
056: import java.util.List;
057: import java.util.Map;
058:
059: import javax.swing.undo.UndoableEditSupport;
060:
061: import org.apache.commons.collections.Closure;
062:
063: import com.projity.document.Document;
064: import com.projity.document.ObjectEvent;
065: import com.projity.grouping.core.Node;
066: import com.projity.grouping.core.NodeFactory;
067: import com.projity.grouping.core.hierarchy.HierarchyUtils;
068: import com.projity.grouping.core.hierarchy.MutableNodeHierarchy;
069: import com.projity.pm.assignment.Assignment;
070: import com.projity.pm.assignment.AssignmentService;
071: import com.projity.pm.assignment.HasAssignments;
072: import com.projity.pm.task.NormalTask;
073: import com.projity.pm.task.Project;
074: import com.projity.undo.AssignmentCreationEdit;
075: import com.projity.undo.AssignmentDeletionEdit;
076:
077: /**
078: *
079: */
080: public class AssignmentNodeModel extends DefaultNodeModel implements
081: ObjectEvent.Listener {
082: protected Document document;
083: protected boolean containsLeftObjects;
084:
085: public AssignmentNodeModel(Document document,
086: boolean containsLeftObjects) {
087: super ();
088: this .containsLeftObjects = containsLeftObjects;
089: setDocument(document);
090: }
091:
092: public AssignmentNodeModel(NodeModelDataFactory dataFactory) {
093: this (dataFactory, null, false);
094: }
095:
096: public AssignmentNodeModel(NodeModelDataFactory dataFactory,
097: Document document, boolean containsLeftObjects) {
098: super (dataFactory);
099: this .containsLeftObjects = containsLeftObjects;
100: setDocument(document);
101: }
102:
103: AssignmentNodeModel(
104: /*ArrayList list,*/MutableNodeHierarchy hierarchy,
105: NodeModelDataFactory dataFactory, Document document,
106: boolean containsLeftObjects) {
107: super (/*list,*/hierarchy, dataFactory);
108: this .containsLeftObjects = containsLeftObjects;
109: setDocument(document);
110: }
111:
112: public void objectChanged(ObjectEvent objectEvent) {
113: if (objectEvent.getObject() instanceof Assignment) {
114: Assignment assignment = ((Assignment) objectEvent
115: .getObject());
116: if (assignment.isDefault())
117: return;
118: if (assignment.getDocument(containsLeftObjects) == document) { //TODO check if it's correct
119: if (objectEvent.isCreate()) {
120: Object parentObject = containsLeftObjects ? assignment
121: .getLeft()
122: : assignment.getRight();
123: Node parent = search(parentObject);
124: if (parent != null) { // the new assignment has to be added
125: Node child = null;
126: if (objectEvent.getInfo() != null
127: && dataFactory instanceof Project) {
128: //don't want a node shared by Projet and ResourcePool
129: if (objectEvent.getInfo().getNode() != null)
130: child = objectEvent.getInfo().getNode();
131: else
132: child = NodeFactory.getInstance()
133: .createNode(assignment);
134: } else {
135: //search if assignment already exists in hierarchy
136: for (Enumeration e = parent.children(); e
137: .hasMoreElements();) {
138: Node c = (Node) e.nextElement();
139: if (c.getImpl() == assignment) {
140: child = c;
141: break;
142: }
143: }
144: if (child == null)
145: child = NodeFactory.getInstance()
146: .createNode(assignment);
147: }
148: int position = 0;
149: for (Enumeration e = parent.children(); e
150: .hasMoreElements(); position++) {
151: if (!(((Node) e.nextElement()).getImpl() instanceof Assignment))
152: break;
153: }
154: add(parent, child, position, EVENT);
155:
156: if ((objectEvent.getInfo() == null || (objectEvent
157: .getInfo() != null && objectEvent
158: .getInfo().isUndo()))
159: && dataFactory instanceof Project) {
160: UndoableEditSupport undoableEditSupport = getUndoableEditSupport();
161: if (undoableEditSupport != null) {
162: undoableEditSupport
163: .postEdit(new AssignmentCreationEdit(
164: child));
165: }
166: }
167:
168: }
169:
170: } else if (objectEvent.isDelete()) {
171: Node node = search(assignment);
172: if (node != null) {
173: remove(node, EVENT, false);
174: if ((objectEvent.getInfo() == null || (objectEvent
175: .getInfo() != null && objectEvent
176: .getInfo().isUndo()))
177: && dataFactory instanceof Project) {
178: UndoableEditSupport undoableEditSupport = getUndoableEditSupport();
179: if (undoableEditSupport != null) {
180: undoableEditSupport
181: .postEdit(new AssignmentDeletionEdit(
182: node));
183: }
184: }
185: }
186:
187: } else { //update
188: }
189: }
190: }
191: }
192:
193: protected void finalize() throws Throwable {
194: super .finalize();
195: document.removeObjectListener(this );
196: }
197:
198: public boolean isContainsLeftObjects() {
199: return containsLeftObjects;
200: }
201:
202: public void setContainsLeftObjects(boolean containsLeftObjects) {
203: this .containsLeftObjects = containsLeftObjects;
204: }
205:
206: public Document getDocument() {
207: return document;
208: }
209:
210: public void setDocument(Document document) {
211: if (this .document != null)
212: this .document.removeObjectListener(this );
213: this .document = document;
214: if (document != null)
215: document.addObjectListener(this );
216: }
217:
218: public void addAssignments() {
219: addAssignments(iterator());
220: }
221:
222: public void addAssignments(Iterator i) {
223: Iterator j;
224: Node parent;
225: Node child;
226: Map assignments = new HashMap();
227: while (i.hasNext()) { // go thru tasks or resources
228: parent = (Node) i.next();
229: if (!(parent.getImpl() instanceof HasAssignments)) {
230: continue; //TODO currently getting voidNodeImpl's. This should go away when fixed
231: }
232: HasAssignments hasAssignments = (HasAssignments) parent
233: .getImpl();
234: for (j = hasAssignments.getAssignments().iterator(); j
235: .hasNext();) {
236: Assignment assignment = (Assignment) j.next();
237: if (assignment.isDefault())
238: continue;
239: child = NodeFactory.getInstance()
240: .createNode(assignment);
241: assignments.put(child, parent);
242: }
243: }
244: boolean found;
245: for (Iterator k = assignments.keySet().iterator(); k.hasNext();) {
246: child = (Node) k.next();
247: parent = (Node) assignments.get(child);
248:
249: //search if assignment already exists in hierarchy
250: //fixes bug about adding a second assignment when the view is first shown
251: found = false;
252: for (Enumeration e = parent.children(); e.hasMoreElements();) {
253: Node c = (Node) e.nextElement();
254: if (c.getImpl() == child.getImpl()) {
255: child = c;
256: found = true;
257: break;
258: }
259: }
260:
261: if (!found)
262: add(parent, child, SILENT);
263: }
264: }
265:
266: public boolean confirmRemove(List nodes) {
267: return true;
268: // This code is commented out since the user was getting prompted multiple times. With Undo, it's less important
269: // if (Environment.isBatchMode())
270: // return true;
271: // Iterator i = nodes.iterator();
272: // Object impl;
273: // boolean hasActuals = false;
274: // while (i.hasNext()) {
275: // impl = ((Node)i.next()).getImpl();
276: // if (impl instanceof Schedule) {
277: // if (((Schedule)impl).getPercentComplete() > 0.0D) {
278: // hasActuals = true;
279: // break;
280: // }
281: // }
282: // }
283: // if (hasActuals)
284: // return Alert.okCancel(Messages.getString("Message.allowDeleteActuals"));
285: // else
286: // return true;
287: }
288:
289: public void paste(Node parent, List nodes, int position,
290: int actionType) {
291: super .paste(parent, nodes, position, actionType);
292: ArrayList roots = new ArrayList();
293: HierarchyUtils.extractParents(nodes, roots);
294: final List freeAssignments = new ArrayList();
295: for (Iterator i = roots.iterator(); i.hasNext();)
296: hierarchy.visitLeaves((Node) i.next(), new Closure() {
297: public void execute(Object o) {
298: Node node = (Node) o;
299: if (node.getImpl() instanceof Assignment) {
300: Assignment assignment = (Assignment) node
301: .getImpl();
302: Node parent = (Node) node.getParent();
303: if (parent.getImpl() instanceof NormalTask) {
304: NormalTask task = (NormalTask) parent
305: .getImpl();
306: if (task.findAssignment(assignment
307: .getResource()) == null) {
308: freeAssignments.add(node);
309: }
310: }
311: }
312: }
313: });
314: for (Iterator i = freeAssignments.iterator(); i.hasNext();) {
315: Node node = (Node) i.next();
316: node.removeFromParent();
317: System.out.println("restoring assignment: "
318: + node.getImpl());
319: AssignmentService.getInstance().connect(node, this,
320: isUndo(actionType));
321: }
322:
323: }
324:
325: }
|