/******************************************************************************* * Copyright (c) 2009 Conselleria de Infraestructuras y Transporte, Generalitat * de la Comunitat Valenciana . 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: Francisco Javier Cano Muñoz (Prodevelop) – Initial implementation * ******************************************************************************/ package org.eclipse.papyrus.uml.diagram.common.providers; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; /** * A basic implementation of {@link ViewInfo}. This class is used to parse the * 'es.cv.gvcase.mdt.common.viewInfo' extension point. It can handle the additions of child nodes * that have parents that have not yet been added; these nodes are stores in a temporary storage. * Upon a later addition of a node, nodes in the temporary storage are revisited to put them in * their correct place. * * @author <a href="mailto:fjcano@prodevelop.es">Francisco Javier Cano Muñoz</a> * @NOT-generated */ public class BaseViewInfo implements ViewInfo { // // attributes /** The parent ViewInfo in the hierarchy. */ private ViewInfo parentViewInfo = null; /** The visual id in String form. */ public String visualID = "-1"; /** The type in String form. */ public String type; /** The type in integer form. */ private int typeViewInfo = ViewInfo.None; /** The label that will be shown. */ public String label = null; /** The children of this ViewInfo in the hierarchy. */ private Collection<ViewInfo> children = null; /** Temporary storage of ViewInfo elements to be added. */ private static Map<Integer, Collection<ViewInfo>> toAdd = null; /** Identifier of the IElementType this ViewInfo represents. */ // @unused public String elementType; /** VisualID in String form of this ViewInfo's parent. */ public String parent; /** Pointer to the RootInfo which this ViewInfo belong to. */ public RootViewInfo rootViewInfo; /** Flag that indicates if this ViewInfo can be selected to be filtered. */ public Boolean selectable = true; // // constructors /** * Instantiates a new base view info. */ // @unused public BaseViewInfo() { // empty constructor } /** * Instantiates a new base view info. * * @param visualID * the visual id * @param type * the type * @param label * the label */ public BaseViewInfo(int visualID, int type, String label) { this(visualID, type, label, null, null); } /** * Instantiates a new base view info. * * @param visualID * the visual id * @param type * the type * @param label * the label * @param children * the children * @param parent * the parent */ public BaseViewInfo(int visualID, int type, String label, Collection<ViewInfo> children, ViewInfo parent) { this.visualID = String.valueOf(visualID); this.typeViewInfo = type; this.label = label; this.children = children; this.parentViewInfo = parent; } // // getters /** * @see es.cv.gvcase.mdt.common.provider.ViewInfo#getChildren() */ public Collection<ViewInfo> getChildren() { if(children == null) { children = new ArrayList<ViewInfo>(); } return children; } /** * @see es.cv.gvcase.mdt.common.provider.ViewInfo#getLabel() */ public String getLabel() { return label; } /** * @see es.cv.gvcase.mdt.common.provider.ViewInfo#getType() */ public int getType() { // type by its integer form switch(typeViewInfo) { case ViewInfo.Head: case ViewInfo.Node: case ViewInfo.Edge: case ViewInfo.Label: return typeViewInfo; default: { // type by its String form if(type != null && type.length() > 0) { if(ViewInfo.NONE_LITERAL.equals(type)) { return ViewInfo.None; } else if(ViewInfo.HEAD_LITERAL.equals(type)) { return ViewInfo.Head; } else if(ViewInfo.NODE_LITERAL.equals(type)) { return ViewInfo.Node; } else if(ViewInfo.EDGE_LITERAL.equals(type)) { return ViewInfo.Edge; } else if(ViewInfo.LABEL_LITERAL.equals(type)) { return ViewInfo.Label; } else { return ViewInfo.None; } } else { // unknown return -1; } } } } /** * @see es.cv.gvcase.mdt.common.provider.ViewInfo#getVisualID() */ public int getVisualID() { return Integer.valueOf(visualID); } /** * @see es.cv.gvcase.mdt.common.provider.ViewInfo#getParent() */ public ViewInfo getParent() { return parentViewInfo; } /** * Indicates whether this ViewInfo can be selected to be filtered. */ public boolean isSelectable() { return selectable; } /** * Gets the temporary storage for nodes without parents in the hierarchy. * * @return the to add */ protected static Map<Integer, Collection<ViewInfo>> getToAdd() { if(toAdd == null) { toAdd = new HashMap<Integer, Collection<ViewInfo>>(); } return toAdd; } // // setters /** * @see es.cv.gvcase.mdt.common.provider.ViewInfo#setChildren(java.util.Collection ) */ public void setChildren(Collection<ViewInfo> children) { this.children = children; } /** * @see es.cv.gvcase.mdt.common.provider.ViewInfo#setLabel(java.lang.String) */ public void setLabel(String label) { this.label = label; } /** * @see es.cv.gvcase.mdt.common.provider.ViewInfo#setParent(es.cv.gvcase.mdt. common.provider.ViewInfo) */ public void setParent(ViewInfo parent) { this.parentViewInfo = parent; } /** * @see es.cv.gvcase.mdt.common.provider.ViewInfo#setType(int) */ public void setType(int type) { this.typeViewInfo = type; } /** * @see es.cv.gvcase.mdt.common.provider.ViewInfo#setVisualID(int) */ public void setVisualID(int visualID) { this.visualID = String.valueOf(visualID); } /** * Gets the root info which this ViewInfo belong to. * * @return the root info */ protected ViewInfo getRootInfo() { ViewInfo parent = null, aux = this; while((parent = aux.getParent()) != null) { aux = parent; } return aux; } /** * Checks whether ViewInfo is the higher in the hierarchy. * * @return true, if is root */ protected boolean isRoot() { ViewInfo root = getRootInfo(); if(root != null && root == this) { return true; } return false; } // // add a node /** * Adds a node in its corresponding place in the hierarchy. The parent node * needs not exist yet in the hierarchy. Orphan nodes are stored in a * temporary storage, that is revisited when a new node is added. * * @see es.cv.gvcase.mdt.common.provider.ViewInfo#addNode(int, es.cv.gvcase.mdt.common.provider.ViewInfo) */ public boolean addNode(int parentVisualID, ViewInfo info) { if(isAlreadyContained(info)) { return true; } if(internalAddNode(parentVisualID, info)) { if(isRoot()) { revisePendentNodes(info); } return true; } else { if(isRoot()) { addPendentNode(parentVisualID, info); } return false; } } /** * Checks if a ViewInfo is already contained in the hierarchy. * * @param info * the info * * @return true, if is already contained */ protected boolean isAlreadyContained(ViewInfo info) { if(info == null) { return true; } return lookInChildren(this, info); } /** * Look in children for a given ViewInfo. * * @param info * the info * @param lookFor * the look for * * @return true, if successful */ protected boolean lookInChildren(ViewInfo info, ViewInfo lookFor) { if(info == lookFor) { return true; } for(ViewInfo child : info.getChildren()) { if(lookInChildren(child, lookFor)) { return true; } } return false; } /** * Adds a node that was in the temporary storage and its parent node has * just been added to the hierarchy. * * @param parentID * the parent id * @param info * the info */ private void addPendentNode(int parentID, ViewInfo info) { Map<Integer, Collection<ViewInfo>> toAdd = getToAdd(); if(toAdd.containsKey(parentID) == false) { toAdd.put(parentID, new ArrayList<ViewInfo>()); } if(toAdd.get(parentID).contains(info) == false) { toAdd.get(parentID).add(info); } } /** * Revise pending nodes in the temporary storage. Nodes whose parent has * been added will be put in their corresponding in the hierarchy. * * @param info * the info */ private void revisePendentNodes(ViewInfo info) { int parentVisualID = info.getVisualID(); Map<Integer, Collection<ViewInfo>> toAdd = getToAdd(); if(toAdd.containsKey(parentVisualID)) { for(ViewInfo viewInfo : toAdd.get(parentVisualID)) { if(info.getChildren().contains(viewInfo) == false && info != viewInfo && isAlreadyContained(viewInfo) == false) { info.getChildren().add(viewInfo); if(viewInfo.getParent() == null) { viewInfo.setParent(info); } } } toAdd.remove(parentVisualID); } } /** * Internal add node. * * @param parentVisualID * the parent visual id * @param info * the info * * @return true, if successful */ protected boolean internalAddNode(int parentVisualID, ViewInfo info) { if(info == null) { return true; } if(getVisualID() == parentVisualID) { if(getChildren().contains(info) == false && this != info) { getChildren().add(info); } if(info.getParent() == null) { info.setParent(this); } return true; } for(ViewInfo viewInfo : getChildren()) { if(viewInfo.addNode(parentVisualID, info)) { return true; } } return false; } // // for debugging purposes /** * A Debugging method. Shows some info. * * @see java.lang.Object#toString() */ @Override public String toString() { String superString = super.toString(); String myString = getVisualID() + ", " + getLabel(); superString = superString != null ? superString + " :: " + myString : myString; return superString; } }