| //------------------------------------------------------------------------------ |
| // Copyright (c) 2005, 2006, 2007 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.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.LinkedHashSet; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.emf.common.util.AbstractTreeIterator; |
| import org.eclipse.emf.common.util.BasicEList; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.xmi.XMLResource; |
| import org.eclipse.epf.library.edit.util.model.ModelFactory; |
| import org.eclipse.epf.library.edit.util.model.OrderInfo; |
| import org.eclipse.epf.library.edit.util.model.OrderInfoCollection; |
| import org.eclipse.epf.library.edit.util.model.util.StringResource; |
| import org.eclipse.epf.uma.DescribableElement; |
| import org.eclipse.epf.uma.VariabilityElement; |
| import org.eclipse.epf.uma.VariabilityType; |
| import org.eclipse.epf.uma.util.AssociationHelper; |
| import org.eclipse.epf.uma.util.UmaUtil; |
| |
| /** |
| * |
| * This class encapsulates all the logics used to retrieve the list of all |
| * contributed/inherited sections of the given element as well as allows |
| * manipulate this list. |
| * |
| * 1.5: Refactored to work on any VariabilityElement |
| * |
| * @author Lokanath Jagga |
| * @author Phong Nguyen Le |
| * @since 1.0 |
| */ |
| public class ContentElementOrderList extends BasicEList { |
| |
| /** |
| * |
| */ |
| private static final long serialVersionUID = 3257572797487069233L; |
| |
| public static final String ORDER_INFO_NAME = "content elements"; //$NON-NLS-1$ |
| |
| private static final Map DEFAULT_SAVE_OPTIONS = new HashMap(); |
| |
| public static final int CONTENT_ELEMENTS__FOR_ELEMENT_ONLY = 1; |
| |
| public static final int CONTENT_ELEMENTS__FOR_ELEMENT_AND_PARENTS = 2; |
| |
| static { |
| DEFAULT_SAVE_OPTIONS.put(XMLResource.OPTION_ENCODING, "ASCII"); //$NON-NLS-1$ |
| } |
| |
| private VariabilityElement editElement; |
| |
| private boolean mixed = true; |
| |
| private boolean changed = false; |
| |
| private EStructuralFeature feature; |
| |
| private static boolean isContributor(VariabilityElement e) { |
| return TngUtil.isContributor(e); |
| } |
| |
| public ContentElementOrderList(VariabilityElement e, int scope, EStructuralFeature feature) { |
| this.feature = feature; |
| editElement = e; |
| if (scope == CONTENT_ELEMENTS__FOR_ELEMENT_ONLY) { |
| mixed = false; |
| } else if (scope == CONTENT_ELEMENTS__FOR_ELEMENT_AND_PARENTS) { |
| calculateParentsOnly(e); |
| } else { |
| mixed = false; |
| } |
| } |
| |
| private void calculateParentsOnly(VariabilityElement e) { |
| Iterator iter = null; |
| if (isContributor(e) || isExtended(e)) { |
| List supers = new ArrayList(); |
| UmaUtil.getAllSupersBoth(supers, e, |
| VariabilityType.CONTRIBUTES, |
| VariabilityType.EXTENDS); |
| supers.add(e); |
| iter = supers.iterator(); |
| } else { |
| mixed = false; |
| } |
| |
| if (mixed) { |
| // create a map of GUID / contributor |
| |
| OrderInfo latestInfo = null; |
| Map guidMap = new HashMap(); |
| Set elements = new LinkedHashSet(); |
| while (iter.hasNext()) { |
| VariabilityElement element = (VariabilityElement) iter.next(); |
| List contentElements = new ArrayList(); |
| Object eGet = ((VariabilityElement) element).eGet(feature); |
| if (eGet instanceof List) { |
| contentElements.addAll((List) eGet); |
| } |
| for (Iterator iterator = contentElements.iterator(); iterator |
| .hasNext();) { |
| DescribableElement categorizedElement = (DescribableElement) iterator |
| .next(); |
| guidMap.put(categorizedElement.getGuid(), |
| categorizedElement); |
| elements.add(categorizedElement); |
| } |
| |
| OrderInfo orderInfo = TngUtil.getOrderInfo(element, |
| ORDER_INFO_NAME); |
| if (orderInfo != null) { |
| if (latestInfo == null |
| || orderInfo.getTimestamp() > latestInfo |
| .getTimestamp()) { |
| latestInfo = orderInfo; |
| } |
| } |
| } |
| |
| if (latestInfo != null) { |
| // reorder the sections based on the latest order info |
| int size = latestInfo.getGUIDs().size(); |
| for (int i = 0; i < size; i++) { |
| Object guid = latestInfo.getGUIDs().get(i); |
| Object element = guidMap.get(guid); |
| if (element != null) { |
| super.add(element); |
| elements.remove(element); |
| } |
| } |
| } |
| super.addAll(elements); |
| } |
| } |
| |
| // deprecate the following constructor |
| public ContentElementOrderList(VariabilityElement e) { |
| editElement = e; |
| Iterator iter = null; |
| if (isContributor(e) || TngUtil.hasContributor(e)) { |
| VariabilityElement base = TngUtil.getBase(e); |
| iter = new AbstractTreeIterator(base) { |
| |
| protected Iterator getChildren(Object object) { |
| List children = new ArrayList(); |
| for (Iterator iterator = AssociationHelper |
| .getImmediateVarieties((VariabilityElement) object) |
| .iterator(); iterator.hasNext();) { |
| VariabilityElement element = (VariabilityElement) iterator |
| .next(); |
| if (element.getVariabilityType() == VariabilityType.CONTRIBUTES) { |
| children.add(element); |
| } |
| } |
| return children.iterator(); |
| } |
| |
| }; |
| } else if (isExtended(e)) { |
| System.out |
| .println("$$$ for " + e.getName() + " = extended is true"); //$NON-NLS-1$ //$NON-NLS-2$ |
| List supers = new ArrayList(); |
| UmaUtil.getAllSupers(supers, e, VariabilityType.EXTENDS); |
| supers.add(e); |
| iter = supers.iterator(); |
| } else { |
| mixed = false; |
| } |
| |
| if (mixed) { |
| // create a map of GUID / contributor |
| OrderInfo latestInfo = null; |
| Map guidMap = new HashMap(); |
| List elements = new LinkedList(); |
| while (iter.hasNext()) { |
| VariabilityElement element = (VariabilityElement) iter.next(); |
| guidMap.put(element.getGuid(), element); |
| elements.add(element); |
| |
| OrderInfo orderInfo = TngUtil.getOrderInfo(element, |
| ORDER_INFO_NAME); |
| if (orderInfo != null) { |
| if (latestInfo == null |
| || orderInfo.getTimestamp() > latestInfo |
| .getTimestamp()) { |
| latestInfo = orderInfo; |
| } |
| } |
| } |
| |
| if (latestInfo != null) { |
| // reorder the sections based on the latest order info |
| // |
| int size = latestInfo.getGUIDs().size(); |
| for (int i = 0; i < size; i++) { |
| Object guid = latestInfo.getGUIDs().get(i); |
| Object element = guidMap.get(guid); |
| if (element != null) { |
| super.add(element); |
| elements.remove(element); |
| } |
| } |
| } |
| super.addAll(elements); |
| } |
| // else { |
| // // addAll(editElement.getPresentation().getSections()); |
| // mixed = false; |
| // } |
| } |
| |
| private static boolean isExtended(VariabilityElement e) { |
| return e.getVariabilityBasedOnElement() != null |
| && e.getVariabilityType() == VariabilityType.EXTENDS; |
| } |
| |
| /** |
| * Applies recent changes in the list |
| * |
| */ |
| public void apply() { |
| if (!mixed || !changed) |
| return; |
| |
| // save the order info to the orderingGuide of the editElement |
| // |
| String str = editElement.getOrderingGuide(); |
| OrderInfoCollection orderInfos = null; |
| StringResource res = null; |
| if (str == null || str.length() == 0) { |
| orderInfos = ModelFactory.eINSTANCE.createOrderInfoCollection(); |
| } else { |
| res = new StringResource(str); |
| try { |
| res.load(null); |
| if (res.getContents().isEmpty()) { |
| orderInfos = ModelFactory.eINSTANCE |
| .createOrderInfoCollection(); |
| } else { |
| orderInfos = (OrderInfoCollection) res.getContents().get(0); |
| } |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| // find the order infor for sections |
| // |
| OrderInfo sectOrderInfo = null; |
| for (Iterator iter = orderInfos.getOrderInfos().iterator(); iter |
| .hasNext();) { |
| OrderInfo orderInfo = (OrderInfo) iter.next(); |
| if (ORDER_INFO_NAME.equalsIgnoreCase(orderInfo.getName())) { |
| sectOrderInfo = orderInfo; |
| break; |
| } |
| } |
| |
| if (sectOrderInfo == null) { |
| sectOrderInfo = ModelFactory.eINSTANCE.createOrderInfo(); |
| sectOrderInfo.setName(ORDER_INFO_NAME); |
| orderInfos.getOrderInfos().add(sectOrderInfo); |
| } else { |
| sectOrderInfo.getGUIDs().clear(); |
| } |
| |
| int size = size(); |
| for (int i = 0; i < size; i++) { |
| DescribableElement sect = (DescribableElement) get(i); |
| sectOrderInfo.getGUIDs().add(sect.getGuid()); |
| } |
| sectOrderInfo.setTimestamp(System.currentTimeMillis()); |
| if (res == null) { |
| res = new StringResource(null); |
| res.getContents().add(orderInfos); |
| } |
| try { |
| res.save(DEFAULT_SAVE_OPTIONS); |
| str = res.getString(); |
| // System.out.println("SectionList.apply(): new ordering guide"); |
| // System.out.println("------ orderingGuide start ------"); |
| // System.out.println(str); |
| // System.out.println("------ orderingGuide end ------"); |
| editElement.setOrderingGuide(str); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } catch (RuntimeException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| public boolean canRemove(VariabilityElement contentElement) { |
| if (eGet().contains(contentElement)) { |
| return true; |
| } |
| return false; |
| } |
| |
| public Object remove(int index) { |
| if (mixed) { |
| if (!canRemove((VariabilityElement) get(index))) |
| return null; |
| Object removed = super.remove(index); |
| eGet().remove(removed); |
| return removed; |
| } else { |
| return eGet().remove(index); |
| } |
| } |
| |
| public boolean remove(Object o) { |
| if (!canRemove((VariabilityElement) o)) |
| return false; |
| if (mixed) { |
| if (super.remove(o)) { |
| eGet().remove(o); |
| return true; |
| } |
| return false; |
| } |
| return eGet().remove(o); |
| } |
| |
| public boolean removeAll(Collection c) { |
| if (mixed) { |
| boolean modified = false; |
| Iterator e = iterator(); |
| while (e.hasNext()) { |
| Object o = e.next(); |
| if (c.contains(o) && canRemove((VariabilityElement) o)) { |
| e.remove(); |
| eGet().remove(o); |
| modified = true; |
| } |
| } |
| return modified; |
| } else { |
| return eGet().removeAll(c); |
| } |
| } |
| |
| public void add(int index, Object element) { |
| if (mixed) { |
| super.add(index, element); |
| eGet().add(element); |
| changed = true; |
| } else { |
| eGet().add(index, element); |
| } |
| } |
| |
| public boolean add(Object o) { |
| boolean b = eGet().add(o); |
| if (mixed) { |
| b = super.add(o); |
| if (b) |
| changed = true; |
| } |
| return b; |
| } |
| |
| public boolean addAll(Collection c) { |
| boolean b = eGet().addAll(c); |
| ; |
| if (mixed) { |
| b = super.addAll(c); |
| if (b) |
| changed = true; |
| } |
| return b; |
| } |
| |
| public boolean addAll(int index, Collection c) { |
| if (mixed) { |
| eGet().addAll(c); |
| ; |
| boolean b = super.addAll(index, c); |
| if (b) |
| changed = true; |
| } |
| return eGet().addAll(c); |
| } |
| |
| public Object set(int index, Object element) { |
| if (mixed) |
| throw new UnsupportedOperationException(); |
| return eGet().set(index, element); |
| } |
| |
| public void clear() { |
| if (mixed) |
| throw new UnsupportedOperationException(); |
| eGet().clear(); |
| } |
| |
| public void move(int index, Object object) { |
| if (mixed) { |
| super.move(index, object); |
| changed = true; |
| } else { |
| ((EList) eGet()).move(index, object); |
| } |
| } |
| |
| public Object move(int targetIndex, int sourceIndex) { |
| if (mixed) { |
| Object moved = super.move(targetIndex, sourceIndex); |
| changed = true; |
| return moved; |
| } else { |
| return eGet().move(targetIndex, sourceIndex); |
| } |
| } |
| |
| public Object get(int index) { |
| if (mixed) { |
| return super.get(index); |
| } else { |
| return eGet().get(index); |
| } |
| } |
| |
| public int size() { |
| if (mixed) { |
| return super.size(); |
| } else { |
| return eGet().size(); |
| } |
| } |
| |
| public Iterator iterator() { |
| if (mixed) { |
| return super.iterator(); |
| } else { |
| return eGet().iterator(); |
| } |
| } |
| |
| public boolean contains(Object object) { |
| if (mixed) { |
| return super.contains(object); |
| } |
| return eGet().contains(object); |
| } |
| |
| public boolean containsAll(Collection collection) { |
| if (mixed) |
| return super.containsAll(collection); |
| return eGet().containsAll(collection); |
| } |
| |
| public Object[] toArray() { |
| if (mixed) { |
| return super.toArray(); |
| } |
| return eGet().toArray(); |
| } |
| |
| public Object[] toArray(Object[] array) { |
| if (mixed) |
| return super.toArray(array); |
| return eGet().toArray(array); |
| } |
| |
| public int indexOf(Object object) { |
| if (mixed) |
| return super.indexOf(object); |
| return eGet().indexOf(object); |
| } |
| |
| public int lastIndexOf(Object object) { |
| if (mixed) |
| return super.lastIndexOf(object); |
| return eGet().lastIndexOf(object); |
| } |
| |
| public boolean isMixed() { |
| return mixed; |
| } |
| |
| private EList eGet() { |
| EList list = null; |
| Object object = editElement.eGet(feature); |
| if (object instanceof EList) { |
| list = (EList) object; |
| } |
| if (list == null) { |
| list = new BasicEList(); |
| } |
| return list; |
| } |
| } |