| /******************************************************************************* |
| * Copyright (c) 2009,2010 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.stem.definitions; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.SortedSet; |
| import java.util.TreeSet; |
| |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.common.util.EMap; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.stem.core.STEMURI; |
| import org.eclipse.stem.core.Utility; |
| import org.eclipse.stem.core.common.Identifiable; |
| import org.eclipse.stem.core.graph.Edge; |
| import org.eclipse.stem.core.graph.Graph; |
| import org.eclipse.stem.core.graph.LabelValue; |
| import org.eclipse.stem.core.graph.Node; |
| import org.eclipse.stem.core.model.Model; |
| import org.eclipse.stem.definitions.labels.CommonBorderRelationshipLabelValue; |
| import org.eclipse.stem.definitions.labels.RelativePhysicalRelationshipLabel; |
| import org.eclipse.stem.definitions.labels.RelativePhysicalRelationshipLabelValue; |
| |
| |
| /** |
| * Utility to extract node keys from a project |
| */ |
| public class LocationUtility { |
| |
| static Map<String, Set<String>> [] treeISOKeyMaps = new Map[4]; |
| static Map<String, URI> isoKeyURIMap = new HashMap<String, URI>(); |
| static List<Model> processedModels = new ArrayList<Model>(); |
| |
| static boolean loaded = false; |
| |
| public static void reset() {treeISOKeyMaps = new Map[4];isoKeyURIMap.clear();processedModels.clear();loaded=false;} |
| |
| public static Set<String> getKeys(IProject project, int level, String parent) { |
| |
| if(!loaded) { |
| for(int i=0;i<4;++i) treeISOKeyMaps[i] = new HashMap<String, Set<String>>(); |
| IContainer modelFolder = project.getFolder("models"); |
| |
| IResource[] models = null; |
| try { |
| models = modelFolder.members(); |
| } catch(Exception e) { |
| e.printStackTrace(); |
| } |
| if (models != null) { |
| for(IResource r:models) { |
| // ignore system files |
| if(r.getName().startsWith(".")) continue; |
| |
| try { |
| URI uri = URI.createURI(r.getLocationURI().toString()); |
| Identifiable id = Utility.getIdentifiable(uri); |
| if(id instanceof Model) processModel((Model)id); |
| |
| } catch(Exception e) { |
| // Skip bad file |
| } |
| } |
| } |
| |
| IContainer graphsFolder = project.getFolder("graphs"); |
| IResource[] graphs = null; |
| try { |
| graphs = graphsFolder.members(); |
| } catch(Exception e) { |
| e.printStackTrace(); |
| } |
| if (graphs != null) { |
| for(IResource r:graphs) { |
| // ignore system files |
| if(r.getName().startsWith(".")) continue; |
| |
| try { |
| URI uri = URI.createURI(r.getLocationURI().toString()); |
| Identifiable id = Utility.getIdentifiable(uri); |
| if(id instanceof Graph) processGraph((Graph)id); |
| |
| } catch(Exception e) { |
| // Skip bad file |
| } |
| |
| } |
| } |
| loaded = true; |
| } |
| |
| Set<String>result = null; |
| |
| if(parent != null) result = treeISOKeyMaps[level-1].get(parent); |
| else result = treeISOKeyMaps[level].keySet(); |
| if(result!= null) |
| return result; |
| return new HashSet<String>(); // return empty array |
| } |
| |
| private static void processModel(Model m) { |
| processedModels.add(m); |
| // First get sub models |
| for(Model m2:m.getModels()) |
| if(!processedModels.contains(m2)) processModel(m2); |
| |
| // To the graphs in the model |
| EList<Graph>graphs = m.getGraphs(); |
| for(Graph g:graphs) |
| processGraph(g); |
| } |
| |
| private static void processGraph(Graph g) { |
| // Do the edges first to get the hierarchy |
| |
| for(Edge e:g.getEdges().values()) { |
| if(e.getLabel().getCurrentValue() instanceof RelativePhysicalRelationshipLabelValue) { |
| |
| int sourceLevel = Utility.keyLevel(e.getNodeAURI().lastSegment()); |
| int targetLevel = Utility.keyLevel(e.getNodeBURI().lastSegment()); |
| String sourceKey = e.getNodeAURI().lastSegment(); |
| String targetKey = e.getNodeBURI().lastSegment(); |
| |
| if(treeISOKeyMaps[sourceLevel].containsKey(sourceKey)) |
| treeISOKeyMaps[sourceLevel].get(sourceKey).add(targetKey); |
| else { |
| SortedSet<String>nl = new TreeSet<String>(); |
| treeISOKeyMaps[sourceLevel].put(sourceKey, nl); |
| nl.add(targetKey); |
| } |
| |
| if(!treeISOKeyMaps[targetLevel].containsKey(targetKey)) { |
| // Add with empty child set |
| TreeSet<String>nl = new TreeSet<String>(); |
| treeISOKeyMaps[targetLevel].put(targetKey, nl); |
| } |
| |
| isoKeyURIMap.put(sourceKey, e.getNodeAURI()); |
| isoKeyURIMap.put(targetKey, e.getNodeBURI()); |
| |
| } |
| } |
| |
| // Now find dangling nodes |
| EMap<URI, Node> map = g.getNodes(); |
| for(URI u:map.keySet()) { |
| int l = Utility.keyLevel(u.lastSegment()); |
| if(l == -1) continue; // no world |
| String key = u.lastSegment(); |
| if(!treeISOKeyMaps[l].containsKey(key)) { |
| TreeSet<String>nl = new TreeSet<String>(); |
| treeISOKeyMaps[l].put(key, nl); |
| isoKeyURIMap.put(key, u); |
| } |
| } |
| } |
| |
| |
| /** |
| * Place the edges from the graph in a Map keyed by the URI of the edge. |
| * This avoids duplicates in case same graph exists in multiple models |
| * @param project |
| * @return |
| */ |
| public static Set<Edge> getCommonBorderEdges(IProject project, URI location) { |
| Map<String,Edge> cbEdges = new HashMap<String,Edge>(); |
| |
| IContainer modelFolder = project.getFolder("models"); |
| IResource[] models = null; |
| try { |
| models = modelFolder.members(); |
| } catch(Exception e) { |
| e.printStackTrace(); |
| } |
| if (models != null) { |
| for(IResource r:models) { |
| // ignore system files |
| if(r.getName().startsWith(".")) continue; |
| |
| try { |
| URI uri = URI.createURI(r.getLocationURI().toString()); |
| Identifiable id = Utility.getIdentifiable(uri); |
| Graph g = ((Model)id).getCanonicalGraph(STEMURI.createURI(""), null, null); |
| if(id instanceof Model) cbEdges.putAll(getGraphCommonBorderEdges(g, location)); |
| |
| } catch(Exception e) { |
| // Skip bad file |
| } |
| } |
| } |
| |
| // Only do the edges in the graphs folder if the user hasn't specified a |
| // location, since we need to resolve the URI's to support locations |
| if(location == null || location.toString().trim().equals("")) { |
| IContainer graphsFolder = project.getFolder("graphs"); |
| IResource[] graphs = null; |
| try { |
| graphs = graphsFolder.members(); |
| } catch(Exception e) { |
| e.printStackTrace(); |
| } |
| if (graphs != null) { |
| for(IResource r:graphs) { |
| // ignore system files |
| if(r.getName().startsWith(".")) continue; |
| |
| try { |
| URI uri = URI.createURI(r.getLocationURI().toString()); |
| Identifiable id = Utility.getIdentifiable(uri); |
| if(id instanceof Graph) cbEdges.putAll(getGraphCommonBorderEdges((Graph)id, location)); |
| |
| } catch(Exception e) { |
| // Skip bad file |
| } |
| } |
| } |
| } |
| Set<Edge> retVal = new HashSet<Edge>(); |
| retVal.addAll(cbEdges.values()); |
| return retVal; |
| } |
| |
| /*** |
| * Place the edges from the graph in a Map keyed by the URI of the edge. |
| * This avoids duplicates in case same graph exists in multiple models |
| * @param g |
| */ |
| private static Map<String,Edge> getGraphCommonBorderEdges(Graph g, URI location) { |
| |
| Map<String,Edge> cbEdges = new HashMap<String,Edge>(); |
| for(Edge e:g.getEdges().values()) { |
| if(e.getLabel().getCurrentValue() instanceof CommonBorderRelationshipLabelValue) { |
| String uriKey = e.getURI().lastSegment(); |
| if(location != null && !location.toString().trim().equals("") |
| && isSelfOrChild(e.getA(), location.lastSegment()) && isSelfOrChild(e.getB(), location.lastSegment())) |
| cbEdges.put(uriKey,e); |
| else if(location == null || location.toString().trim().equals("")) |
| cbEdges.put(uriKey,e); |
| } |
| } |
| return cbEdges; |
| }//getGraphCommonBorderEdges |
| |
| /** |
| * Retrieve all nodes in a project |
| * @param project |
| * @param location The parent location |
| * @return Set<Node> All nodes in parent and children |
| */ |
| public static Set<Node> getNodes(IProject project, URI location) { |
| Set<Node> allNodes = new HashSet<Node>(); |
| |
| IContainer modelFolder = project.getFolder("models"); |
| IResource[] models = null; |
| try { |
| models = modelFolder.members(); |
| } catch(Exception e) { |
| e.printStackTrace(); |
| } |
| if (models != null) { |
| for(IResource r:models) { |
| // ignore system files |
| if(r.getName().startsWith(".")) continue; |
| |
| try { |
| URI uri = URI.createURI(r.getLocationURI().toString()); |
| Model mod = (Model)Utility.getIdentifiable(uri); |
| Graph g = mod.getCanonicalGraph(STEMURI.createURI(""), null, null); |
| addGraphNodes(g, allNodes, location); |
| |
| } catch(Exception e) { |
| // Skip bad file |
| } |
| } |
| } |
| return allNodes; |
| } |
| |
| /*** |
| * Retrieve all nodes for the location in the graph |
| * @param g |
| * @param allNodes Results are stored here |
| * @param location The location, or null if all nodes should be retrieved |
| */ |
| private static void addGraphNodes(Graph g, Set<Node>allNodes, URI location) { |
| for(Node n:g.getNodes().values()) { |
| String uriKey = n.getURI().lastSegment(); |
| if(location != null && !location.toString().trim().equals("") |
| && isSelfOrChild(n, location.lastSegment()) && |
| !containsNodeURI(n.getURI(), allNodes)) |
| allNodes.add(n); |
| else if(location == null || location.toString().trim().equals("") && ! allNodes.contains(n) |
| && !containsNodeURI(n.getURI(), allNodes)) |
| allNodes.add(n); |
| |
| } |
| }//getGraphCommonBorderEdges |
| |
| private static boolean containsNodeURI(URI uri, Set<Node>nodes) { |
| for(Node n:nodes) if(n.getURI().equals(uri)) return true; |
| return false; |
| } |
| |
| |
| public static URI getURIFromISOKey(String key) { |
| return isoKeyURIMap.get(key); |
| } |
| |
| protected static boolean isSelfOrChild(Node n, String parent) { |
| if(n.getURI().lastSegment().equals(parent)) return true; |
| return hasParent(n, parent); |
| } |
| |
| protected static boolean hasParent(Node n, String key) { |
| for(Edge e:n.getEdges()) { |
| // Make sure it's a physical containment edge |
| boolean phys = e.getLabel() instanceof RelativePhysicalRelationshipLabel; |
| if(!phys) |
| continue; |
| if(e.getA().getURI().lastSegment().equals(key)) return true; |
| else if(Utility.keyLevel(e.getA().getURI().lastSegment()) < Utility.keyLevel(n.getURI().lastSegment())) |
| return hasParent(e.getA(), key); |
| } |
| return false; |
| } |
| |
| /** |
| * finds all the child nodes of a parent (direct children and children of children etc...) |
| * and returns them in a set. |
| * Child is defined by a containment relationship |
| * @param parent |
| */ |
| public static Set<Node> getAllChildren(Node parent) { |
| Set<Node> allChildren = new HashSet<Node>(); |
| Set<Node> toDoSet = getChildSet(parent); |
| toDoSet.remove(parent); |
| Set<Node> directChildren = new HashSet<Node>(); |
| |
| while(toDoSet.size() >=1) { |
| directChildren.addAll(toDoSet); |
| Iterator<Node> iter = directChildren.iterator(); |
| while(iter!=null && iter.hasNext()) { |
| Node next = iter.next(); |
| allChildren.add(next); |
| Set<Node> nextSet = getChildSet(next); |
| nextSet.removeAll(allChildren); |
| toDoSet.addAll(nextSet); |
| } |
| toDoSet.removeAll(directChildren); |
| directChildren.clear(); |
| } |
| return allChildren; |
| } |
| |
| |
| /** |
| * finds all the direct child nodes of a parent and returns them in a set. |
| * Child is defined by a containment relationship |
| * @param parent |
| */ |
| public static Set<Node> getChildSet(Node parent) { |
| Set<Node> children = new HashSet<Node>(); |
| if(parent == null) return children; |
| String parentID = parent.getURI().lastSegment(); |
| //RelativePhysicalRelationshipLabelValue |
| EList<Edge> allEdges = parent.getEdges(); |
| for (int i = 0; i < allEdges.size(); i ++) { |
| Edge e = allEdges.get(i); |
| LabelValue lv = e.getLabel().getCurrentValue(); |
| if(lv instanceof RelativePhysicalRelationshipLabelValue) { |
| RelativePhysicalRelationshipLabelValue containment = (RelativePhysicalRelationshipLabelValue)lv; |
| Node neighborNode = e.getOtherNode(parent); |
| String neighborID= neighborNode.getURI().lastSegment(); |
| // is it really a child |
| if(neighborID.length() > parentID.length() || parentID.equals("ZZZ")) { |
| //yes |
| children.add(neighborNode); |
| }// is child |
| }// is containment relationship |
| }// for all edges |
| //just to be sure |
| children.remove(parent); |
| return children; |
| } |
| |
| } |