| /******************************************************************************* |
| * Copyright (c) 2005, 2012 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.bpel.ui.adapters.delegates; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| |
| import org.eclipse.emf.ecore.EObject; |
| |
| /** |
| * An abstract IContainer implementation for containers composed of one or more Lists |
| * of children in a particular relative order. |
| * |
| * NOTE: insertBefore references across all sub-containers are valid, but child objects |
| * are constrained to be in the proper list. |
| */ |
| public class MultiContainer extends AbstractContainer { |
| |
| boolean allowMixedTypeReplace = false; |
| |
| protected List<AbstractContainer> fContainers = new ArrayList<AbstractContainer>(); |
| |
| /** |
| * Add the container. |
| * @param container |
| */ |
| public void add (AbstractContainer container) { |
| fContainers.add(container); |
| } |
| |
| /** |
| * Return the sub container for the given container. |
| * |
| * @param object the container object |
| * @param child the child objects |
| * |
| * @return the sub container for the child |
| * |
| */ |
| |
| public final AbstractContainer getSubContainer(EObject object, Object child) { |
| |
| if (child instanceof EObject == false) { |
| return null; |
| } |
| for(AbstractContainer sub : fContainers) { |
| if (sub.isValidChild(object, (EObject)child)) { |
| return sub; |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| protected final boolean isValidChild(EObject object, EObject child) { |
| return getSubContainer(object, child) != null; |
| } |
| |
| /** |
| * @see org.eclipse.bpel.ui.adapters.IContainer#addChild(java.lang.Object, java.lang.Object, java.lang.Object) |
| */ |
| public boolean addChild(EObject object, EObject child, EObject insertBefore) { |
| |
| AbstractContainer childContainer = getSubContainer(object, child); |
| if (insertBefore == null) { |
| /** This happens during copy/paste operations */ |
| if (childContainer == null) { |
| return false; |
| } |
| return childContainer.addChild(object, child, null); |
| } |
| |
| AbstractContainer insertBeforeContainer = getSubContainer(object, insertBefore); |
| if (childContainer == insertBeforeContainer) { |
| return childContainer.addChild(object, child, insertBefore); |
| } |
| |
| // Child either belongs at the beginning of its sub-container, or the end. |
| // Which sub-container comes first? |
| int childRange = 0; |
| int insertBeforeRange = 0; |
| Object[] containers = fContainers.toArray(); |
| for (int i = 0; i<containers.length; i++) { |
| if (containers[i] == childContainer) childRange = i; |
| if (containers[i] == insertBeforeContainer) insertBeforeRange = i; |
| } |
| if (childRange > insertBeforeRange) { |
| // child should go at beginning of sub-container. |
| List<EObject> children = childContainer.getChildren(object); |
| if (children.size() > 0) { |
| return childContainer.addChild(object, child, children.get(0)); |
| } |
| } |
| // put child at end of sub-container. |
| return childContainer.addChild(object, child, null); |
| } |
| |
| /** |
| * @param object |
| * @return |
| * @see org.eclipse.bpel.ui.adapters.IContainer#getChildren(java.lang.Object) |
| */ |
| |
| public List<EObject> getChildren(EObject object) { |
| |
| List<EObject> result = new ArrayList<EObject>(); |
| for (AbstractContainer container : fContainers) { |
| result.addAll( container.getChildren( object ) ) ; |
| } |
| if (result.isEmpty()) { |
| return Collections.emptyList(); |
| } |
| return Collections.unmodifiableList(result); |
| } |
| |
| |
| /** |
| * @see org.eclipse.bpel.ui.adapters.IContainer#removeChild(java.lang.Object, java.lang.Object) |
| */ |
| |
| public boolean removeChild(EObject object, EObject child) { |
| return getSubContainer(object, child).removeChild(object, child); |
| } |
| |
| /** |
| * @see org.eclipse.bpel.ui.adapters.IContainer#replaceChild(java.lang.Object, java.lang.Object, java.lang.Object) |
| */ |
| public boolean replaceChild(EObject object, EObject oldChild, EObject newChild) |
| { |
| AbstractContainer oldSubContainer = getSubContainer(object, oldChild); |
| AbstractContainer newSubContainer = getSubContainer(object, newChild); |
| if (oldSubContainer == newSubContainer) { |
| return oldSubContainer.replaceChild(object, oldChild, newChild); |
| } |
| // the elements are in different subContainers. |
| if (!allowMixedTypeReplace) { |
| return false; |
| } |
| return replaceMixedTypeChild(object, oldChild, newChild); |
| } |
| |
| // subclasses might want to override this to check types (e.g. to return null instead) |
| protected boolean replaceMixedTypeChild(EObject object, EObject oldChild, |
| EObject newChild) |
| { |
| AbstractContainer oldSubContainer = getSubContainer(object, oldChild); |
| AbstractContainer newSubContainer = getSubContainer(object, newChild); |
| |
| oldSubContainer.removeChild(object, oldChild); |
| newSubContainer.addChild(object, newChild, null); |
| return true; |
| } |
| |
| |
| /** |
| * @see org.eclipse.bpel.ui.adapters.delegates.AbstractContainer#canAddObject(java.lang.Object, java.lang.Object, java.lang.Object) |
| */ |
| |
| @Override |
| public boolean canAddObject (EObject object, EObject child, EObject insertBefore) { |
| AbstractContainer ac = getSubContainer(object, child); |
| return (ac == null)? false : ac.canAddObject(object, child, insertBefore); |
| } |
| |
| /** |
| * @param object |
| * @param child |
| * @return |
| * @see org.eclipse.bpel.ui.adapters.IContainer#canRemoveChild(java.lang.Object, java.lang.Object) |
| */ |
| |
| public boolean canRemoveChild(EObject object, EObject child) { |
| AbstractContainer ac = getSubContainer(object, child); |
| return (ac == null)? false : ac.canRemoveChild( object, child ); |
| } |
| |
| } |