blob: 2603a4fb1c6aeaa352416cfc72a0cad8ae28d8ba [file] [log] [blame]
/*******************************************************************************
* 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 );
}
}