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.presenters.actions;
042:
043: import org.netbeans.modules.vmd.api.model.DesignComponent;
044: import org.netbeans.modules.vmd.api.model.DesignDocument;
045:
046: import java.util.Collection;
047: import java.util.Collections;
048: import java.util.HashSet;
049:
050: /**
051: * Support class for component deletion.
052: * <p>
053: * DeleteSupport.canDeleteAsUser:
054: * <ul>
055: * <li>DeletePresenter.canDelete == ALLOWED on selected components
056: * <li>Gather all components (within the tree) with DeleteDependencyPresenter.requiresToLive (selectedComponent) == true or is as a selected component
057: * <li>DeletePresenter.canDelete != DISALLOWED on all gathered and selected components
058: * </ul>
059: * <p>
060: * DeleteSupport.deleteAsUser:
061: * <ul>
062: * <li>DeletePresenter.canDelete == ALLOWED on selected components
063: * <li>Gather all components (within the tree) with DeleteDependencyPresenter.requiresToLive (selectedComponent) == true or is as a selected component
064: * <li>DeletePresenter.canDelete != DISALLOWED on all gathered and selected components
065: * <li>DeleteDependencyPresenter.componentsDeleting on all components in tree
066: * <li>DeletePresenter.delete on all gathered and selected components
067: * <li>DesignDocument.removeComponent on all gathered and selected components
068: * </ul>
069: *
070: * @author David Kaspar
071: */
072: public final class DeleteSupport {
073:
074: private DeleteSupport() {
075: }
076:
077: private static DeletableState canDelete(
078: Collection<DesignComponent> components) {
079: boolean disallowedForUserOnly = false;
080: for (DesignComponent component : components) {
081: for (DeletePresenter presenter : component
082: .getPresenters(DeletePresenter.class)) {
083: DeletableState state = presenter.canDelete();
084: switch (state) {
085: case DISALLOWED:
086: return DeletableState.DISALLOWED;
087: case DISALLOWED_FOR_USER_ONLY:
088: disallowedForUserOnly = true;
089: }
090: }
091: }
092:
093: return disallowedForUserOnly ? DeletableState.DISALLOWED_FOR_USER_ONLY
094: : DeletableState.ALLOWED;
095: }
096:
097: static boolean isSilent(DesignComponent component) {
098: for (DeletePresenter presenter : component
099: .getPresenters(DeletePresenter.class))
100: if (presenter.isSilent())
101: return true;
102: return false;
103: }
104:
105: private static Collection<DesignComponent> gatherAllComponentsToDelete(
106: DesignDocument document,
107: Collection<DesignComponent> baseComponents) {
108: HashSet<DesignComponent> componentsToDelete = new HashSet<DesignComponent>(
109: baseComponents);
110: Collection<DesignComponent> componentsToDeleteUm = Collections
111: .unmodifiableCollection(componentsToDelete);
112:
113: while (findNewlyRequired(document.getRootComponent(),
114: componentsToDelete, componentsToDeleteUm))
115: ;
116:
117: return componentsToDelete;
118: }
119:
120: private static boolean findNewlyRequired(DesignComponent component,
121: Collection<DesignComponent> componentsToDelete,
122: Collection<DesignComponent> componentsToDeleteUm) {
123: boolean changed = false;
124: if (!componentsToDelete.contains(component))
125: if (requiresToLive(component, componentsToDeleteUm)) {
126: componentsToDelete.add(component);
127: changed = true;
128: }
129:
130: for (DesignComponent child : component.getComponents())
131: if (findNewlyRequired(child, componentsToDelete,
132: componentsToDeleteUm))
133: changed = true;
134:
135: return changed;
136: }
137:
138: private static boolean requiresToLive(DesignComponent component,
139: Collection<DesignComponent> componentsToDelete) {
140: for (DeleteDependencyPresenter presenter : component
141: .getPresenters(DeleteDependencyPresenter.class)) {
142: if (presenter.requiresToLive(componentsToDelete))
143: return true;
144: }
145: return false;
146: }
147:
148: private static void notifyComponentsDeleting(
149: DesignComponent component,
150: Collection<DesignComponent> componentsToDeleteUm) {
151: for (DeleteDependencyPresenter presenter : component
152: .getPresenters(DeleteDependencyPresenter.class))
153: presenter.componentsDeleting(componentsToDeleteUm);
154: for (DesignComponent child : component.getComponents())
155: notifyComponentsDeleting(child, componentsToDeleteUm);
156: }
157:
158: public static boolean canDeleteAsUser(DesignDocument document,
159: Collection<DesignComponent> componentsToDelete) {
160: if (canDelete(componentsToDelete) != DeletableState.ALLOWED)
161: return false;
162:
163: Collection<DesignComponent> allComponentsToDelete = gatherAllComponentsToDelete(
164: document, componentsToDelete);
165: return canDelete(allComponentsToDelete) != DeletableState.DISALLOWED;
166: }
167:
168: public static void invokeDirectUserDeletion(
169: DesignDocument document,
170: Collection<DesignComponent> componentsToDelete,
171: boolean showConfirmation) {
172: if (canDelete(componentsToDelete) != DeletableState.ALLOWED)
173: return;
174:
175: Collection<DesignComponent> allComponentsToDelete = gatherAllComponentsToDelete(
176: document, componentsToDelete);
177: if (canDelete(allComponentsToDelete) == DeletableState.DISALLOWED)
178: return;
179:
180: if (showConfirmation
181: && !ConfirmDeletionPanel.show(componentsToDelete,
182: allComponentsToDelete))
183: return;
184:
185: notifyComponentsDeleting(document.getRootComponent(),
186: Collections
187: .unmodifiableCollection(allComponentsToDelete));
188:
189: for (DesignComponent component : allComponentsToDelete)
190: for (DeletePresenter presenter : component
191: .getPresenters(DeletePresenter.class))
192: presenter.delete();
193:
194: document.deleteComponents(allComponentsToDelete);
195: }
196:
197: }
|