//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 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 implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.library.edit.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.provider.AdapterFactoryTreeIterator;
import org.eclipse.emf.edit.provider.IChangeNotifier;
import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
import org.eclipse.emf.edit.provider.IWrapperItemProvider;
import org.eclipse.emf.edit.provider.ItemProviderAdapter;
import org.eclipse.emf.edit.provider.ViewerNotification;
import org.eclipse.epf.library.edit.IFilter;
import org.eclipse.epf.library.edit.LibraryEditResources;
import org.eclipse.epf.library.edit.process.BreakdownElementWrapperItemProvider;
import org.eclipse.epf.library.edit.process.IBSItemProvider;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.BreakdownElement;
import org.eclipse.epf.uma.Descriptor;
import org.eclipse.epf.uma.MethodElementProperty;
import org.eclipse.epf.uma.Milestone;
import org.eclipse.epf.uma.Process;
import org.eclipse.epf.uma.ProcessPackage;
import org.eclipse.epf.uma.UmaFactory;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.VariabilityElement;
import org.eclipse.epf.uma.VariabilityType;
import org.eclipse.epf.uma.WorkBreakdownElement;
import org.eclipse.epf.uma.WorkOrder;
import org.eclipse.epf.uma.WorkOrderType;

/**
 * This class represents a predecessor list of an item provider for a work
 * breakdown element. It calculates the predecessors based on the currently
 * selected configuration and according to variability rules. It can refresh
 * itself upon change in predecessor list of work breakdown element.
 * 
 * @author Phong Nguyen Le
 * @since 1.0
 */
public class PredecessorList extends ArrayList<Object> {
	/**
	 * Comment for <code>serialVersionUID</code>
	 */
	private static final long serialVersionUID = 3617853092570412082L;	
	
	private static final String FINISH_TO_START = LibraryEditResources.WorkOrderTypeAbbreviation_FINISH_TO_START; 
	private static final String FINISH_TO_FINISH = LibraryEditResources.WorkOrderTypeAbbreviation_FINISH_TO_FINISH; 
	private static final String START_TO_START = LibraryEditResources.WorkOrderTypeAbbreviation_START_TO_START; 
	private static final String START_TO_FINISH = LibraryEditResources.WorkOrderTypeAbbreviation_START_TO_FINISH; 
	private Map map4LinkType = new HashMap();

	public static final PredecessorList EMPTY_LIST = new PredecessorList() {

		/**
		 * Comment for <code>serialVersionUID</code>
		 */
		private static final long serialVersionUID = 3904676098217097016L;

		public void refresh() {

		}

		public void add(int index, Object element) {

		}

		public boolean add(Object o) {
			throw new UnsupportedOperationException();
		}

		public boolean addAll(java.util.Collection c) {
			throw new UnsupportedOperationException();
		}

		public boolean addAll(int index, java.util.Collection c) {
			throw new UnsupportedOperationException();
		}

	};

	private AdapterFactory adapterFactory;

	private Object object;

	private Adapter listener = new AdapterImpl() {
		public void notifyChanged(org.eclipse.emf.common.notify.Notification msg) {
			switch (msg.getFeatureID(BreakdownElement.class)) {
			case UmaPackage.WORK_BREAKDOWN_ELEMENT__LINK_TO_PREDECESSOR:
				refresh();
				return;
			}
		}
	};
	
	private Adapter customPredecessorListener = new AdapterImpl() {
		@Override
		public void notifyChanged(Notification msg) {
			switch(msg.getFeatureID(ProcessPackage.class)) {
			case UmaPackage.PROCESS_PACKAGE__PROCESS_ELEMENTS:
				Object object = null;
				switch(msg.getEventType()) {
				case Notification.ADD:
				case Notification.ADD_MANY:
					object = msg.getNewValue();
					break;
				case Notification.REMOVE:
				case Notification.REMOVE_MANY:
					object = msg.getOldValue();
					break;
				}
				boolean shouldRefresh = false;
				if(object != null) {
					WorkBreakdownElement succ = (WorkBreakdownElement) TngUtil.unwrap(PredecessorList.this.object);
					if(object instanceof WorkOrder) {
						if(ProcessUtil.isCustomWorkOrderOf((WorkOrder) object, succ)) {
							shouldRefresh = true;
						}
					} else if (object instanceof Collection<?>) {
						findCustomWorkOrder:
							for (Object e : (Collection<?>) object) {
								if(e instanceof WorkOrder && ProcessUtil.isCustomWorkOrderOf((WorkOrder) e, succ)) {
									shouldRefresh = true;
									break findCustomWorkOrder;
								}
							}
					}
				}
				if(shouldRefresh) {
					refresh();
					Object ip = adapterFactory.adapt(PredecessorList.this.object, ITreeItemContentProvider.class);
					if(ip instanceof IChangeNotifier) {
						((IChangeNotifier) ip).fireNotifyChanged(new ViewerNotification(msg,
								PredecessorList.this.object, false, true));
					}
				}
				return;
			}
		}
	};

	private Object top;

	private ArrayList<ProcessPackage> parentPackages;

	private PredecessorList() {

	}

	public PredecessorList(AdapterFactory adapterFactory, Object object) {
		this.adapterFactory = adapterFactory;
		this.object = object;
		BreakdownElement e = (BreakdownElement) TngUtil.unwrap(object);
		e.eAdapters().add(0, listener);
		for (ProcessPackage parentPackage : getParentPackages()) {
			parentPackage.eAdapters().add(0, customPredecessorListener);
		}
		if (!map4LinkType.isEmpty())
			map4LinkType.clear();
		initialize();
	}

	public void dispose() {
		Object e = TngUtil.unwrap(object);
		if (e instanceof EObject) {
			((EObject) e).eAdapters().remove(listener);
		}
		for (ProcessPackage parentPackage : getParentPackages()) {
			parentPackage.eAdapters().remove(customPredecessorListener);
		}
		clear();
	}

	/**
	 * Gets the right top item in the breakdown structure tree to search for
	 * item providers of predecessors
	 * 
	 * @return
	 */
	protected Object getTopItem() {
		if (object instanceof BreakdownElementWrapperItemProvider) {
			BreakdownElementWrapperItemProvider itemProvider = (BreakdownElementWrapperItemProvider) object;
			if (itemProvider.isReadOnly()) {
				// this represents an inherited breakdown element
				//
				BreakdownElement e = (BreakdownElement) TngUtil.unwrap(object);
				Process proc = TngUtil.getOwningProcess(e);

				Object top = itemProvider;
				for (Object parent = itemProvider.getParent(object); parent != null;) {
					top = parent;
					BreakdownElement parentElement = (BreakdownElement) TngUtil
							.unwrap(parent);
					Process parentProc = TngUtil
							.getOwningProcess(parentElement);
					if (parentProc != proc) {
						break;
					}
					if (parent instanceof ITreeItemContentProvider) {
						parent = ((ITreeItemContentProvider) parent)
								.getParent(parent);
					} else {
						ITreeItemContentProvider adapter = (ITreeItemContentProvider) adapterFactory
								.adapt(parent, ITreeItemContentProvider.class);
						parent = adapter.getParent(parent);
					}
				}
				return top;
			} else {
				return itemProvider.getTopItem();
			}
		} else {
			IBSItemProvider adapter = (IBSItemProvider) adapterFactory.adapt(
					object, ITreeItemContentProvider.class);
			return adapter.getTopItem();
		}
	}
	
	public static class DepthLevelItemProvider {
		private int depthLevel;
		private Object itemProvider;
		private Object object;
		private Object element;
		
		private DepthLevelItemProvider(Object object, int depthLevel, Object itemProvider, Object element) {
			super();
			this.object = object;
			this.depthLevel = depthLevel;
			this.itemProvider = itemProvider;
			this.element = element;
		}	
		
		public Object getItemProvider() {
			return itemProvider;
		}
	}
	
	static List<DepthLevelItemProvider> createItemProviderList(Object top, AdapterFactory adapterFactory) {
		List<DepthLevelItemProvider> list = new ArrayList<DepthLevelItemProvider>();
		DepthLevelAdapterFactoryTreeIterator<Object> iter = new DepthLevelAdapterFactoryTreeIterator<Object>(
				adapterFactory, top) {
					private static final long serialVersionUID = 1L;
					@Override
					protected Iterator<Object> getChildren(Object o) {
						Object e = TngUtil.unwrap(o); 
						if(e instanceof Descriptor || e instanceof Milestone) {
							return Collections.emptyList().iterator();
						}
						return super.getChildren(o);
					}			
		};
		for(; iter.hasNext();) {
			Object object = iter.next();
			Object element = TngUtil.unwrap(object);
			if(element instanceof WorkBreakdownElement) {
				int depthLevel = iter.getDepthLevel();
				Object itemProvider = adapterFactory.adapt(object, ITreeItemContentProvider.class);
				list.add(new DepthLevelItemProvider(object, depthLevel, itemProvider, element));
			}
		}
		return list;
	}
	
	private static void updateElementToItemProvidersMap(Map<Object, Collection<Object>> map, Object element, Object itemProvider) {
		Collection<Object> itemProviders = map.get(element);
		if(itemProviders == null) {
			itemProviders = new ArrayList<Object>();
			map.put(element, itemProviders);
		}
		itemProviders.add(itemProvider);
		if (element instanceof VariabilityElement) {
			VariabilityElement ve = (VariabilityElement) element;
			if (ve.getVariabilityBasedOnElement() != null) {
				itemProviders = map.get(ve.getVariabilityBasedOnElement());
				if(itemProviders == null) {
					itemProviders = new ArrayList<Object>();
					map.put(ve.getVariabilityBasedOnElement(), itemProviders);
				}
				itemProviders.add(itemProvider);
			}
		}
	}
	
	Map<?, Collection<Object>> createBreakdownElementToItemProviderMap(List<DepthLevelItemProvider> list) {
		Object top = getTopItem();
		// find top's item provider
		//
		DepthLevelItemProvider topIp = null;
		int startIndex = 0;
		for (DepthLevelItemProvider itemProvider : list) {
			if(itemProvider.object == top) {
				topIp = itemProvider;
				break;
			}
			else {
				startIndex++;
			}
		}
		assert topIp != null : "Could not find item provider of top object in the given item provider list."; //$NON-NLS-1$
		// find the index of last item provider in the subtree of top
		//
		int size = list.size();
		int lastIndex = startIndex + 1;
		for (; lastIndex < size && list.get(lastIndex).depthLevel > topIp.depthLevel; lastIndex++);		
			
		// copy the tree to a map of breakdown element / item provider for
		// reuse
		//
		HashMap<Object, Collection<Object>> map = new HashMap<Object, Collection<Object>>();
		for (DepthLevelItemProvider itemProvider : list.subList(startIndex, lastIndex)) {
			updateElementToItemProvidersMap(map, itemProvider.element, itemProvider.itemProvider);
		}
		return map;
	}
	
	static Map<Object, Collection<Object>> createBreakdownElementToItemProviderMap(Object top, AdapterFactory adapterFactory) {
		AdapterFactoryTreeIterator<Object> iter = new AdapterFactoryTreeIterator<Object>(
				adapterFactory, top) {
			private static final long serialVersionUID = 1L;
			@Override
			protected Iterator<Object> getChildren(Object o) {
				Object e = TngUtil.unwrap(o); 
				if(e instanceof Descriptor || e instanceof Milestone) {
					return Collections.emptyList().iterator();
				}
				return super.getChildren(o);
			}			
		};
		
		// copy the tree to a map of breakdown element / item provider for
		// reuse
		//
		HashMap<Object, Collection<Object>> map = new HashMap<Object, Collection<Object>>();
		while (iter.hasNext()) {
			Object obj = iter.next();
			Object be = TngUtil.unwrap(obj);
			if(be instanceof WorkBreakdownElement) {
				IBSItemProvider ip = (IBSItemProvider) (obj instanceof IBSItemProvider ? obj :
					adapterFactory.adapt(obj, ITreeItemContentProvider.class));
				updateElementToItemProvidersMap(map, be, ip);
			}
		}
		return map;
	}
	
	private void initialize() {
		Object unwrapped = TngUtil.unwrap(object);
		if (unwrapped instanceof WorkBreakdownElement) {
			WorkBreakdownElement e = (WorkBreakdownElement) unwrapped;
			List<WorkOrder> workOrders = e.getLinkToPredecessor();
			List<WorkOrder> customWorkOrders = getCustomWorkOrders();
			if (workOrders.isEmpty() && customWorkOrders.isEmpty()) {
				return;
			}
			top = getTopItem();	
			initialize(createBreakdownElementToItemProviderMap(top, adapterFactory), customWorkOrders);
		}
	}
	
	private List<ProcessPackage> getParentPackages() {
		if(parentPackages == null) {
			parentPackages = new ArrayList<ProcessPackage>();
			Activity parent = null;
			if(object instanceof WorkBreakdownElement) {
				parent = ((WorkBreakdownElement) object).getSuperActivities();
			} else if (object instanceof ITreeItemContentProvider) {
				Object parentObject = ((ITreeItemContentProvider) object).getParent(object);
				parentObject = TngUtil.unwrap(parentObject);
				if(parentObject instanceof Activity) {
					parent = (Activity) parentObject;
				}
			}
			if(parent != null) {
				for(Activity activity = parent; activity != null;) {
					Object container = activity.eContainer();
					if(container != null) {
						parentPackages.add((ProcessPackage) container);
					}
					if (activity.getVariabilityType() == VariabilityType.EXTENDS
							|| activity.getVariabilityType() == VariabilityType.LOCAL_CONTRIBUTION) {
						activity = (Activity) activity.getVariabilityBasedOnElement();
					} else {
						activity = null;
					}
				}
			}

		}
		return parentPackages;
	}
	
	private List<WorkOrder> getCustomWorkOrders() {
		Object unwrapped = TngUtil.unwrap(object);
		if (unwrapped instanceof WorkBreakdownElement) {
			WorkBreakdownElement owner = (WorkBreakdownElement) unwrapped;
			ArrayList<WorkOrder> customWorkOrders = new ArrayList<WorkOrder>();
			for (ProcessPackage pkg : getParentPackages()) {
				for (Object element : pkg.getProcessElements()) {
					if (element instanceof WorkOrder) {
						WorkOrder workOrder = (WorkOrder) element;
						MethodElementProperty prop = MethodElementPropertyHelper
						.getProperty(
								workOrder,
								MethodElementPropertyHelper.WORK_ORDER__SUCCESSOR);
						if (prop != null
								&& owner.getGuid().equals(
										prop.getValue())) {
							customWorkOrders.add(workOrder);
						}
					}
				}
			}
			return customWorkOrders;
		} else {
			return Collections.emptyList();
		}
	}
	
	private void initialize(Map<?, Collection<Object>> map, List<WorkOrder> customWorkOrders) {
		Object unwrapped = TngUtil.unwrap(object);
		if (unwrapped instanceof WorkBreakdownElement) {
			WorkBreakdownElement owner = (WorkBreakdownElement) unwrapped;
			List workOrders = owner.getLinkToPredecessor();
			if (workOrders.isEmpty() && customWorkOrders.isEmpty())
				return;
			WorkBreakdownElement topElement = (WorkBreakdownElement) TngUtil.unwrap(top);
			String topGUID = topElement.getGuid();
			
			int n = workOrders.size();
			for (int i = 0; i < n; i++) {
				WorkOrder workOrder = (WorkOrder) workOrders.get(i);					

				//System.out.println(workOrder.getLinkType().getLiteral());

				BreakdownElement pred = workOrder.getPred();
				Collection<Object> itemProviders = map.get(pred);
				if(itemProviders != null && !itemProviders.isEmpty()) {
					IBSItemProvider bsItemProvider = null;
					MethodElementProperty prop = MethodElementPropertyHelper.getProperty(workOrder, 
							MethodElementPropertyHelper.WORK_ORDER__PREDECESSOR_PROCESS_PATH);
					if(prop == null) {
						prop = MethodElementPropertyHelper.getProperty(workOrder, MethodElementPropertyHelper.WORK_ORDER__PREDECESSOR_IS_SIBLING);
						if (prop == null) {
							// predecessor is local or WorkOrder is created before support for 'green' predecessor
							// by saving its process path in methodElementProperty of the work order
							//
							bsItemProvider = (IBSItemProvider) itemProviders.iterator().next();
						} else {
							// predecessor is not local but a sibling
							//
							Object parent = object instanceof IWrapperItemProvider ? ((IWrapperItemProvider) object).getOwner() : owner.getSuperActivities();
							find_wrapper:
							for (Object ip : itemProviders) {
								if(ip instanceof BreakdownElementWrapperItemProvider && ((BreakdownElementWrapperItemProvider) ip).getOwner() == parent) {
									bsItemProvider = (BreakdownElementWrapperItemProvider) ip;
									break find_wrapper;
								}
							}
						}
					}
					else {
						String procPath = prop.getValue();
						
						// calculate the path in this process
						//						
						int index;
						String guid = topGUID;
						VariabilityElement base = topElement instanceof VariabilityElement ? ((VariabilityElement)topElement).getVariabilityBasedOnElement() : null;
						for(index = procPath.indexOf(guid); index == -1 && base != null; index = procPath.indexOf(guid)) {
							if(base != null) {
								guid = base.getGuid(); 
								base = base.getVariabilityBasedOnElement();
							}
						}
						if(index != -1) {
							StringBuffer strBuff = new StringBuffer(procPath.substring(index + guid.length()));
							Object topObject = top;
							for(WorkBreakdownElement wbe = topElement; wbe != null;) {
								strBuff.insert(0, wbe.getGuid());
								strBuff.insert(0, '/');
								if(topObject instanceof WorkBreakdownElement) {
									topObject = wbe = ((WorkBreakdownElement)topObject).getSuperActivities();
								}
								else {
									topObject = adapterFactory.adapt(topObject, ITreeItemContentProvider.class);
									if (topObject instanceof ITreeItemContentProvider) {
										topObject = ((ITreeItemContentProvider)topObject).getParent(topObject);
									}
									wbe = (WorkBreakdownElement) TngUtil.unwrap(topObject);	
								}
							}
							strBuff.insert(0, ":/").insert(0, Suppression.WBS); //$NON-NLS-1$
							String path = strBuff.toString();
							find_wrapper:
							for (Object itemProvider : itemProviders) {
								if(itemProvider instanceof BreakdownElementWrapperItemProvider) {
									String p = Suppression.getPath((BreakdownElementWrapperItemProvider) itemProvider);
									if(path.equals(p)) {
										bsItemProvider = (IBSItemProvider) itemProvider;
										break find_wrapper;
									}
								}
							}
						}
					}
					if (bsItemProvider != null) {
						add(bsItemProvider);
						map4LinkType.put(bsItemProvider.getId(), workOrder.getLinkType().getValue());
					}
				}
			}
			
			// process custom work order (see
			// org.eclipse.epf.library.edit.util.ProcessUtil.findWorkOrder(Activity,
			// WorkBreakdownElement, WorkBreakdownElement))
			//
			if(!customWorkOrders.isEmpty()) {
				Object parentObject = null;
				if(object instanceof WorkBreakdownElement) {
					parentObject = ((WorkBreakdownElement) object).getSuperActivities();
				} else if (object instanceof ITreeItemContentProvider) {
					parentObject = ((ITreeItemContentProvider) object).getParent(object);
				}
				if (parentObject != null) {
					// collect all child item providers
					//
					ITreeItemContentProvider parentItemProvider = (ITreeItemContentProvider) adapterFactory.adapt(parentObject, ITreeItemContentProvider.class);
					Map<Object, Object> elementToItemProviderMap = new HashMap<Object, Object>();
					for (Object child : parentItemProvider.getChildren(parentObject)) {
						elementToItemProviderMap.put(TngUtil.unwrap(child), adapterFactory.adapt(child, ITreeItemContentProvider.class));
					}
					for (WorkOrder workOrder : customWorkOrders) {
						BreakdownElement pred = workOrder.getPred();
						Object ip = elementToItemProviderMap.get(pred);
						if(ip != null) {
							add(ip);
							map4LinkType.put(((IBSItemProvider) ip).getId(), workOrder.getLinkType().getValue());
						}
					}
				}
			}
		}
	}
	
	@Override
	public void clear() {
		super.clear();
		if (!map4LinkType.isEmpty())
			map4LinkType.clear();
	}

	protected void refresh() {
		clear();
		initialize();
	}
	
	void refresh(List<DepthLevelItemProvider> list) {
		clear();
		initialize(createBreakdownElementToItemProviderMap(list), getCustomWorkOrders());
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see java.util.AbstractCollection#toString()
	 */
	public String toString() {
		return toUnSuppressedString(null);
	}

	public String toUnSuppressedString(Suppression sup) {
		// remove the item providers of the deleted elements
		//
		for (Iterator iter = iterator(); iter.hasNext();) {
			Object e = TngUtil.unwrap(iter.next());
			if (e instanceof ItemProviderAdapter) {
				e = ((ItemProviderAdapter) e).getTarget();
				if (e == null) {
					// object deleted
					//
					iter.remove();
				}
			}
			if (e instanceof BreakdownElement) {
				BreakdownElement be = (BreakdownElement) e;
				Activity superAct = be.getSuperActivities();
				if (superAct == null && TngUtil.getOwningProcess(be) != be) {
					iter.remove();
				}
			}
		}

		if (isEmpty())
			return ""; //$NON-NLS-1$

		StringBuffer strBuf = new StringBuffer();
		int n = size() - 1;
		for (int i = 0; i < n; i++) {
			IBSItemProvider bsItemProvider = (IBSItemProvider) get(i);
			if ((sup == null) || !sup.isSuppressed(bsItemProvider)) {
				strBuf.append(bsItemProvider.getId()).append(',');				
			}
		}
		IBSItemProvider bsItemProvider = (IBSItemProvider) get(n);
		if ((sup == null) || !sup.isSuppressed(bsItemProvider)) {
			strBuf.append(bsItemProvider.getId());
		}

		return strBuf.toString();
	}
	
	public String toUnSuppressedString(Suppression sup, boolean isLinkTypeRequired) {
		// remove the item providers of the deleted elements
		//
		for (Iterator iter = iterator(); iter.hasNext();) {
			Object e = TngUtil.unwrap(iter.next());
			if (e instanceof ItemProviderAdapter) {
				e = ((ItemProviderAdapter) e).getTarget();
				if (e == null) {
					// object deleted
					//
					iter.remove();
				}
			}
			if (e instanceof BreakdownElement) {
				BreakdownElement be = (BreakdownElement) e;
				Activity superAct = be.getSuperActivities();
				if (superAct == null && TngUtil.getOwningProcess(be) != be) {
					iter.remove();
				}
			}
		}

		if (isEmpty())
			return ""; //$NON-NLS-1$

		StringBuffer strBuf = new StringBuffer();
		int n = size() - 1;
		for (int i = 0; i < n; i++) {
			IBSItemProvider bsItemProvider = (IBSItemProvider) get(i);
			if ((sup == null) || !sup.isSuppressed(bsItemProvider)) {
				strBuf.append(bsItemProvider.getId());
			    Object value = map4LinkType.get(bsItemProvider.getId());
			    if (value != null && isLinkTypeRequired) {
			    	int v = Integer.parseInt(value.toString());
			    	String abbrev = toWorkOrderTypeAbbreviation(v);
			    	if(abbrev != null) {
			    		strBuf.append(abbrev);
			    	}
			    }
				strBuf.append(',');
			}
		}
		IBSItemProvider bsItemProvider = (IBSItemProvider) get(n);
		if ((sup == null) || !sup.isSuppressed(bsItemProvider)) {
			strBuf.append(bsItemProvider.getId());
			//System.out.println(map4LinkType.get(bsItemProvider.getId()));
			Object value = map4LinkType.get(bsItemProvider.getId());
		    if (value != null && isLinkTypeRequired) {
		    	int v = Integer.parseInt(value.toString());
		    	String abbrev = toWorkOrderTypeAbbreviation(v);
		    	if(abbrev != null) {
		    		strBuf.append(abbrev);
		    	}
		    }
		}

		return strBuf.toString();
	}
	
	public static boolean prepareUpdatePredecessors(AdapterFactory adapterFactory, WorkBreakdownElement wbe,
			List<Object> predecessors, List<WorkOrder> addList, List<WorkOrder> predToBeDeleted) {
		WorkOrder wo = null;
		int size = wbe.getLinkToPredecessor().size();
		
		// remove WorkOrders for predecessors that are not in predecessor list and accepted by the filter
		//
		IFilter filter = ProcessUtil.getFilter(adapterFactory);
		boolean nullFilter = filter == null;
		for (Iterator iter = wbe.getLinkToPredecessor().iterator(); iter
				.hasNext();) {
			wo = (WorkOrder) iter.next();
			if ((nullFilter || filter.accept(wo.getPred()))) {
				boolean found = false;
				find_pred:						
				for(Object pred : predecessors) {
					if(pred instanceof WorkBreakdownElement) {
						if(wo.getPred() == pred) {
							found = true;
							break find_pred;
						}
					}
					else if(pred instanceof BreakdownElementWrapperItemProvider) {
						if(isPredecessor((BreakdownElementWrapperItemProvider) pred, wo, wbe)) {
							found = true;
							break find_pred;
						}
					}
				}
				if(!found) {
					predToBeDeleted.add(wo);
				}
			}
		}

		size = predecessors.size();
		for (int i = 0; i < size; i++) {
			Object obj = predecessors.get(i);
			WorkBreakdownElement element = (WorkBreakdownElement) TngUtil.unwrap(obj);
			boolean found = false;
			BreakdownElementWrapperItemProvider wrapper = (BreakdownElementWrapperItemProvider) (obj instanceof BreakdownElementWrapperItemProvider ? obj : null);
			String procPath = null;
			find_pred: for (Iterator iterator = wbe
					.getLinkToPredecessor().iterator(); iterator
					.hasNext();) {
				wo = (WorkOrder) iterator.next();
				if (wo.getPred() == element) {
					if(wrapper != null) {
						if(isPredecessor(wrapper, wo, wbe)) {
							found = true;
							break find_pred;
						}
					}
					else {
						// the predecessor is local, no need to look for wrapper
						//
						found = true;
						break find_pred;
					}
				}
			}
			if (!found) {					
				wo = UmaFactory.eINSTANCE.createWorkOrder();
				wo.setPred(element);
				if(wrapper != null) {
					if(wrapper.getOwner() == wbe.getSuperActivities()) {
						MethodElementPropertyHelper.setProperty(wo, MethodElementPropertyHelper.WORK_ORDER__PREDECESSOR_IS_SIBLING, "true"); //$NON-NLS-1$
					} else {
						if(procPath == null) {
							procPath = Suppression.getPath(wrapper);
						}
						MethodElementPropertyHelper.setProperty(wo, MethodElementPropertyHelper.WORK_ORDER__PREDECESSOR_PROCESS_PATH, procPath);
					}
				}
				addList.add(wo);
			}
		}
		return true;
	}
	
	/**
	 * Parses a command-separated list of predecessor indexes into lists of
	 * predecessorss to be added and deleted for update.
	 * 
	 * @param adapterFactory
	 * @param wbe
	 * @param indexList
	 *            a comma-separated list of predecessor indexes
	 * @param addList
	 * @param predToBeDeleted
	 * @return
	 */
	public static boolean prepareUpdatePredecessors(
			AdapterFactory adapterFactory, WorkBreakdownElement wbe,
			String indexList, List<WorkOrder> addList, List<WorkOrder> predToBeDeleted) {
		Process process = TngUtil.getOwningProcess(wbe);
		List<Object> predecessors = new ArrayList<Object>();
		if (ProcessUtil.checkPredecessorList(wbe, indexList, adapterFactory,
				process, predecessors) == null) {
			return prepareUpdatePredecessors(adapterFactory, wbe, predecessors, addList, predToBeDeleted);
		}
		return false;
	}

	public static String toWorkOrderTypeAbbreviation(int workOrderType) {
		switch(workOrderType) {
		case WorkOrderType.FINISH_TO_FINISH_VALUE:
			return FINISH_TO_FINISH;
		case WorkOrderType.START_TO_FINISH_VALUE:
			return START_TO_FINISH;
		case WorkOrderType.START_TO_START_VALUE:
			return START_TO_START;
		}
		return null;
	}
	
	/**
	 * Checks if the given wrapper is a predecessor defined by the given WorkOrder.
	 * 
	 * @param wrapper
	 * @param workOrder
	 * @return
	 */
	public static boolean isPredecessor(BreakdownElementWrapperItemProvider wrapper, WorkOrder workOrder, WorkBreakdownElement wbe) {
		if(workOrder.getPred() == TngUtil.unwrap(wrapper)) {
			MethodElementProperty prop = MethodElementPropertyHelper.getProperty(workOrder, 
					MethodElementPropertyHelper.WORK_ORDER__PREDECESSOR_PROCESS_PATH);
			if(prop == null) {
				prop = MethodElementPropertyHelper.getProperty(workOrder, MethodElementPropertyHelper.WORK_ORDER__PREDECESSOR_IS_SIBLING);
				if(prop == null) {
					return wbe.getSuperActivities() == wrapper.getOwner();
				}
				return false;
			}
			else {
				String procPath = prop.getValue();
				String p = Suppression.getPath(wrapper);
				return procPath.equals(p);
			}
		}
		return false;
	}
}
