+/*******************************************************************************\r
+ * Copyright (c) 2010, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.browsing.ui.model.nodetypes;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.List;\r
+import java.util.WeakHashMap;\r
+\r
+import org.simantics.browsing.ui.NodeContext;\r
+import org.simantics.browsing.ui.common.NodeContextBuilder;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.ui.selection.WorkbenchSelectionElement;\r
+\r
+/**\r
+ * A node type that corresponds to some entity type.\r
+ * @author Hannu Niemistö\r
+ */\r
+public class EntityNodeType implements NodeType {\r
+ public List<Resource> entityTypes;\r
+ private static final WeakHashMap<List<Resource>, EntityNodeType> nodeTypeCache =\r
+ new WeakHashMap<List<Resource>, EntityNodeType>();\r
+\r
+ private EntityNodeType(List<Resource> entityTypes) {\r
+ this.entityTypes = entityTypes;\r
+ }\r
+ \r
+ public static EntityNodeType create(Resource entityType) {\r
+ List<Resource> entityTypes = Collections.singletonList(entityType);\r
+ synchronized(nodeTypeCache) {\r
+ EntityNodeType result = nodeTypeCache.get(entityTypes);\r
+ if(result == null) {\r
+ result = new EntityNodeType(entityTypes);\r
+ nodeTypeCache.put(entityTypes, result);\r
+ }\r
+ return result;\r
+ }\r
+ }\r
+ \r
+ public static EntityNodeType create(Collection<Resource> entityTypes) {\r
+ return createInternal(new ArrayList<Resource>(entityTypes));\r
+ }\r
+ \r
+ private static EntityNodeType createInternal(ArrayList<Resource> entityTypes) {\r
+ if(entityTypes.isEmpty())\r
+ throw new IllegalArgumentException();\r
+ else if(entityTypes.size() == 1)\r
+ return create(entityTypes.get(0));\r
+ else {\r
+ Collections.sort(entityTypes);\r
+ synchronized(nodeTypeCache) {\r
+ EntityNodeType result = nodeTypeCache.get(entityTypes);\r
+ if(result == null) {\r
+ result = new EntityNodeType(entityTypes);\r
+ nodeTypeCache.put(entityTypes, result);\r
+ }\r
+ return result;\r
+ }\r
+ }\r
+ }\r
+ \r
+ public static NodeType getNodeTypeFor(ReadGraph graph, Resource resource) throws DatabaseException {\r
+ ArrayList<Resource> types = new ArrayList<Resource>(graph.getPrincipalTypes(resource));\r
+ if(types.isEmpty())\r
+ return null;\r
+ else\r
+ return createInternal(types);\r
+ }\r
+ \r
+ public NodeType getNodeTypeOf(ReadGraph graph, Resource resource) throws DatabaseException {\r
+ ArrayList<Resource> types = new ArrayList<Resource>();\r
+ loop:\r
+ for(Resource t : graph.getPrincipalTypes(resource)) {\r
+ for(Resource et : entityTypes)\r
+ if(!graph.isInheritedFrom(t, et))\r
+ continue loop;\r
+ types.add(t);\r
+ }\r
+ \r
+ if(types.isEmpty())\r
+ return null;\r
+ \r
+ return createInternal(types);\r
+ }\r
+ \r
+ @Override\r
+ public NodeContext createNodeContext(ReadGraph graph, Object content)\r
+ throws DatabaseException {\r
+ if(content instanceof Resource) {\r
+ Resource resource = (Resource)content;\r
+ NodeType nodeType = getNodeTypeOf(graph, resource); \r
+ if(nodeType != null)\r
+ return NodeContextBuilder.buildWithData(KEY_SEQUENCE,\r
+ new Object[] {content, nodeType}); \r
+ }\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public Class<?> getContentType() {\r
+ return Resource.class;\r
+ }\r
+ \r
+ @Override\r
+ public int hashCode() {\r
+ return entityTypes.hashCode();\r
+ }\r
+\r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ if (this == obj)\r
+ return true;\r
+ if (obj == null)\r
+ return false;\r
+ if (getClass() != obj.getClass())\r
+ return false;\r
+ EntityNodeType other = (EntityNodeType) obj;\r
+ return entityTypes.equals(other.entityTypes);\r
+ }\r
+\r
+ @Override\r
+ public boolean inherits(ReadGraph graph, NodeType superType) throws DatabaseException {\r
+ if(this == superType)\r
+ return true;\r
+ if (superType.getClass() != EntityNodeType.class)\r
+ return false;\r
+ loop:\r
+ for(Resource st : ((EntityNodeType)superType).entityTypes) {\r
+ for(Resource t : entityTypes)\r
+ if(graph.isInheritedFrom(t, st))\r
+ continue loop;\r
+ return false;\r
+ }\r
+ return true;\r
+ }\r
+\r
+ @Override\r
+ public Collection<NodeType> getSuper(ReadGraph g) throws DatabaseException {\r
+ if(entityTypes.size() == 1) {\r
+ Layer0 l0 = Layer0.getInstance(g);\r
+ Collection<Resource> supertypes = g.getObjects(entityTypes.get(0), l0.Inherits);\r
+ ArrayList<NodeType> supernodetypes = new ArrayList<NodeType>(supertypes.size());\r
+ for(Resource supertype : supertypes)\r
+ supernodetypes.add(create(supertype));\r
+ return supernodetypes;\r
+ }\r
+ else {\r
+ ArrayList<NodeType> supernodetypes = new ArrayList<NodeType>(entityTypes.size());\r
+ for(Resource t : entityTypes)\r
+ supernodetypes.add(create(t));\r
+ return supernodetypes;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public String toString(ReadGraph graph) throws DatabaseException {\r
+ StringBuilder b = new StringBuilder();\r
+ b.append('[');\r
+ boolean first = true;\r
+ for(Resource t : entityTypes) {\r
+ if(first)\r
+ first = false;\r
+ else\r
+ b.append(", ");\r
+ b.append(NameUtils.getSafeName(graph, t));\r
+ }\r
+ b.append(']');\r
+ return b.toString();\r
+ }\r
+\r
+ @Override\r
+ public WorkbenchSelectionElement getWorkbenchSelectionElement(NodeContext context) {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+\r
+}\r