]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.graph/src/org/simantics/graph/utils/TGResourceUtil.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.graph / src / org / simantics / graph / utils / TGResourceUtil.java
diff --git a/bundles/org.simantics.graph/src/org/simantics/graph/utils/TGResourceUtil.java b/bundles/org.simantics.graph/src/org/simantics/graph/utils/TGResourceUtil.java
new file mode 100644 (file)
index 0000000..245f268
--- /dev/null
@@ -0,0 +1,398 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 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.graph.utils;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Stack;\r
+\r
+import org.simantics.databoard.Accessors;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.accessor.Accessor;\r
+import org.simantics.databoard.accessor.ArrayAccessor;\r
+import org.simantics.databoard.accessor.LongAccessor;\r
+import org.simantics.databoard.accessor.MapAccessor;\r
+import org.simantics.databoard.accessor.OptionalAccessor;\r
+import org.simantics.databoard.accessor.RecordAccessor;\r
+import org.simantics.databoard.accessor.UnionAccessor;\r
+import org.simantics.databoard.accessor.VariantAccessor;\r
+import org.simantics.databoard.accessor.error.AccessorConstructionException;\r
+import org.simantics.databoard.accessor.error.AccessorException;\r
+import org.simantics.databoard.accessor.reference.ChildReference;\r
+import org.simantics.databoard.accessor.reference.ComponentReference;\r
+import org.simantics.databoard.accessor.reference.IndexReference;\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.databoard.type.ArrayType;\r
+import org.simantics.databoard.type.Datatype;\r
+import org.simantics.databoard.type.LongType;\r
+import org.simantics.databoard.type.MapType;\r
+import org.simantics.databoard.type.OptionalType;\r
+import org.simantics.databoard.type.RecordType;\r
+import org.simantics.databoard.type.UnionType;\r
+import org.simantics.databoard.type.VariantType;\r
+import org.simantics.databoard.util.DatatypeVisitorAdapter;\r
+\r
+/**\r
+ * Util for converting all the Long values in a TG, that have metadata "resource=true".\r
+ * \r
+ * @author toni.kalajainen\r
+ */\r
+public class TGResourceUtil {\r
+       \r
+       public static final Datatype RESOURCE_TYPE;\r
+       \r
+       Map<Datatype, Item> items = new HashMap<Datatype, Item>();\r
+       int index = 0;\r
+\r
+       /**\r
+        * Add type to the cache and get some info.\r
+        * \r
+        * @param type\r
+        * @return\r
+        */\r
+       public Item createItem( Datatype type )\r
+       {\r
+               Item item = new Item();\r
+               item.index = index++;\r
+               item.type = type;\r
+               HasResVisitor v = new HasResVisitor();\r
+               type.accept( v, item );\r
+               if ( v.hasRes || v.hasVariant ) {\r
+                       GetRefsVisitor vv = new GetRefsVisitor();\r
+                       type.accept( vv, item );\r
+               }\r
+               return item;\r
+       }\r
+       \r
+       \r
+       /**\r
+        * Find all resources in the value. The resources are added to the result-collection.\r
+        * It may be good to idea to use a Set to avoid duplicate values.  \r
+        * \r
+        * @param type\r
+        * @param value\r
+        * @param result\r
+        * @throws AccessorException \r
+        * @throws AccessorConstructionException \r
+        */\r
+       public void findResources( Datatype type, byte[] value, final Collection<Long> result) throws AccessorConstructionException, AccessorException\r
+       {\r
+               LongAdapter la = new LongAdapter() {\r
+                       @Override\r
+                       public long adapt(long in) {\r
+                               result.add(in);\r
+                               // Return same value\r
+                               return in;\r
+                       }                       \r
+               };\r
+               \r
+               adaptValue( type, value, la );\r
+       }\r
+\r
+       public void findResources( Binding binding, Object value, final Collection<Long> result) throws AccessorConstructionException, AccessorException\r
+       {\r
+               LongAdapter la = new LongAdapter() {\r
+                       @Override\r
+                       public long adapt(long in) {\r
+                               result.add(in);\r
+                               // Return same value\r
+                               return in;\r
+                       }                       \r
+               };\r
+               \r
+               adaptValue( binding, value, la );\r
+       }\r
+       \r
+       /**\r
+        * Add type to the util.\r
+        * @param type\r
+        * @return\r
+        */\r
+       public Item addType( Datatype type )\r
+       {\r
+               Item i = items.get( type );\r
+               if ( i==null ) {\r
+                       i = createItem(type);\r
+                       items.put(type, i);\r
+               }\r
+               return i;\r
+       }\r
+       \r
+       public void adaptValue( Datatype type, byte[] value, LongAdapter adapter ) throws AccessorException\r
+       {\r
+               Item i = addType( type );\r
+               if (!i.mayHaveResource()) return;\r
+               try {\r
+                       Accessor a = Accessors.getAccessor(value, type);\r
+                       adaptValue(i, a, adapter);\r
+               } catch (AccessorConstructionException e) {\r
+                       throw new AccessorException(e);\r
+               }\r
+       }\r
+       \r
+       public boolean mayHaveResource( Datatype type ) {\r
+        Item i = addType( type );\r
+        return i.mayHaveResource();\r
+       }\r
+       \r
+       public void adaptValue( Binding binding, Object value, LongAdapter adapter ) throws AccessorException\r
+       {\r
+               Item i = addType( binding.type() );\r
+               if (!i.mayHaveResource()) return;\r
+               try {\r
+                       Accessor a = Accessors.getAccessor(binding, value);\r
+                       adaptValue(i, a, adapter);\r
+               } catch (AccessorConstructionException e) {\r
+                       throw new AccessorException(e);\r
+               }\r
+       }\r
+       \r
+       void adaptValue( Item i, Accessor a, LongAdapter adapter ) throws AccessorException, AccessorConstructionException\r
+       {\r
+               if ( i.resources != null ) {\r
+                       for (ChildReference r : i.resources)\r
+                       {\r
+                               adaptValue(a, r, adapter);\r
+                       }\r
+               }\r
+               if ( i.variants != null ) {\r
+                       for (ChildReference r : i.variants)\r
+                       {\r
+                               adaptValue(a, r, adapter);\r
+                       }\r
+               }\r
+       }\r
+       \r
+       void adaptValue( Accessor a, ChildReference r, LongAdapter adapter ) throws AccessorException, AccessorConstructionException\r
+       {\r
+               if ( a instanceof LongAccessor ) {\r
+                       LongAccessor x = (LongAccessor) a;\r
+                       long value = x.getValue();\r
+                       long newValue = adapter.adapt( value );\r
+                       if ( newValue != value ) x.setValue( newValue );\r
+               }\r
+\r
+               if ( a instanceof VariantAccessor ) {\r
+                       VariantAccessor x = (VariantAccessor) a;\r
+                       Item i = createItem( x.getContentType() );\r
+                       adaptValue(i, x.getContentAccessor(), adapter);\r
+               }\r
+               \r
+               if ( a instanceof MapAccessor ) {\r
+                       MapAccessor x = (MapAccessor) a;\r
+                       if (r instanceof IndexReference) {\r
+                               IndexReference ir = (IndexReference) r;\r
+                               // Resource is in the Key\r
+                               if (ir.index==0) {\r
+                                       // Read the key as whole\r
+                                       Binding keyBinding = Bindings.getBinding( x.type().keyType );\r
+                                       Binding valueBinding = Bindings.getBinding( x.type().valueType );\r
+                                       Object[] keys = x.getKeys(keyBinding);\r
+                                       for ( Object key : keys ) {\r
+                                               Object value = x.get(keyBinding, key, valueBinding);\r
+                                               // Fix the key\r
+                                               Accessor ka = Accessors.getAccessor(keyBinding, key);\r
+                                               adaptValue(ka, r.childReference, adapter);\r
+                                               \r
+                                               // Write \r
+                                               x.remove(keyBinding, key);\r
+                                               x.put(keyBinding, key, valueBinding, value);\r
+                                       }\r
+                               }\r
+                               \r
+                               // Resource is in the value\r
+                               if (ir.index==1) {\r
+                                       Binding keyBinding = Bindings.getBinding( x.type().keyType );\r
+                                       Object[] keys = x.getKeys(keyBinding);\r
+                                       for ( Object key : keys ) {\r
+                                               Accessor va = x.getValueAccessor(keyBinding, key);\r
+                                               adaptValue(va, r.childReference, adapter);\r
+                                       }\r
+                               }\r
+                       }                       \r
+               }\r
+               \r
+               if ( a instanceof ArrayAccessor ) {\r
+                       ArrayAccessor x = (ArrayAccessor) a;\r
+                       int len = x.size();\r
+                       for (int i=0; i<len; i++) {\r
+                               Accessor sa = x.getAccessor(i);                         \r
+                               adaptValue(sa, r.childReference, adapter);\r
+                       }\r
+               }\r
+               \r
+               if ( a instanceof UnionAccessor ) {\r
+                       UnionAccessor x = (UnionAccessor) a;\r
+                       IndexReference ir = (IndexReference) r;\r
+                       if ( x.getTag() == ir.index ) {\r
+                               Accessor sa = x.getComponentAccessor();\r
+                               adaptValue(sa, ir.childReference, adapter);\r
+                       }\r
+               }\r
+               \r
+               if ( a instanceof RecordAccessor ) {\r
+                       RecordAccessor x = (RecordAccessor) a;\r
+                       IndexReference ir = (IndexReference) r;\r
+                       Accessor sa = x.getFieldAccessor(ir.index);\r
+                       adaptValue(sa, ir.childReference, adapter);\r
+               }\r
+               \r
+               if ( a instanceof OptionalAccessor ) {\r
+                       OptionalAccessor x = (OptionalAccessor) a;\r
+                       if (x.hasValue()) {\r
+                               Accessor sa = x.getComponentAccessor();\r
+                               adaptValue(sa, r.childReference, adapter);\r
+                       }\r
+               }\r
+               \r
+       }\r
+       \r
+       public interface LongAdapter {\r
+               long adapt(long in);\r
+       }\r
+       \r
+       public static class Item {\r
+               // The datatype\r
+               public Datatype type;\r
+               // Index of the type\r
+               public int index;\r
+               // Locations of variants in Datatype  \r
+               List<ChildReference> variants; \r
+               // Locations of resources in Datatype  \r
+               List<ChildReference> resources;\r
+               \r
+               public boolean mayHaveResource() {\r
+                       return (variants!=null&&!variants.isEmpty()) || \r
+                                       (resources!=null&&!resources.isEmpty());\r
+               }\r
+               \r
+               void addVariant(ChildReference ref) {\r
+                       if ( variants == null ) variants = new ArrayList<ChildReference>();\r
+                       variants.add(ref);\r
+               }\r
+               \r
+               void addResource(ChildReference ref) {\r
+                       if ( resources == null ) resources = new ArrayList<ChildReference>();\r
+                       resources.add( ref );\r
+               }\r
+       }\r
+       \r
+    static {\r
+       RESOURCE_TYPE = new LongType();\r
+       RESOURCE_TYPE.metadata.put("resource", "true");\r
+    }\r
+    \r
+    /**\r
+     * This visitor makes a quick peek to see if there is resource or variants.\r
+     */\r
+    static class HasResVisitor extends DatatypeVisitorAdapter {\r
+\r
+       boolean hasRes = false, hasVariant = false;\r
+       \r
+       @Override\r
+       public void visit(VariantType b, Object obj) {\r
+               hasVariant = true;\r
+       }\r
+       \r
+       @Override\r
+       public void visit(LongType b, Object obj) {\r
+               String s = b.metadata.get("unit");\r
+               hasRes |= s!=null && s.equals("resource");\r
+       }\r
+       \r
+    }\r
+    \r
+    static class GetRefsVisitor extends DatatypeVisitorAdapter {\r
+       \r
+       Stack<ChildReference> stack = new Stack<ChildReference>(); \r
+    \r
+       @Override\r
+       public void visit(ArrayType b, Object obj) {                    \r
+               if ( !visited.add(b) ) return; \r
+               \r
+               ComponentReference r = new ComponentReference();\r
+               stack.push(r);\r
+               b.componentType.accept(this, obj);\r
+               stack.pop();\r
+       }\r
+       \r
+       @Override\r
+       public void visit(LongType b, Object obj) {\r
+               String s = b.metadata.get("unit");\r
+               boolean isRes = s!=null && s.equals("resource");\r
+               if ( isRes ) {\r
+                       Item item = (Item) obj;\r
+                       item.addResource( toRef() );\r
+               }\r
+       }\r
+       @Override\r
+       public void visit(MapType b, Object obj) {\r
+               if ( !visited.add(b) ) return;                  \r
+               \r
+               IndexReference r = new IndexReference(0);\r
+               stack.push(r);\r
+               b.keyType.accept(this, obj);\r
+               stack.pop();\r
+               r.index = 1;\r
+               stack.push(r);\r
+               b.valueType.accept(this, obj);\r
+               stack.pop();\r
+       }\r
+       @Override\r
+       public void visit(OptionalType b, Object obj) {\r
+               if ( !visited.add(b) ) return; \r
+               \r
+               ComponentReference r = new ComponentReference();\r
+               stack.push(r);\r
+               b.componentType.accept(this, obj);\r
+               stack.pop();\r
+       }\r
+       @Override\r
+       public void visit(RecordType b, Object obj) {\r
+               if ( !visited.add(b) ) return; \r
+               \r
+                       IndexReference r = new IndexReference(0);\r
+                       stack.push(r);\r
+               for (int i=0; i<b.getComponentCount(); i++) {\r
+                       r.index = i;\r
+                       b.getComponent(i).type.accept(this, obj);\r
+               }\r
+               stack.pop();\r
+       }\r
+       @Override\r
+       public void visit(UnionType b, Object obj) {\r
+               if ( !visited.add(b) ) return;                  \r
+               \r
+                       IndexReference r = new IndexReference(0);\r
+                       stack.push(r);\r
+               for (int i=0; i<b.getComponentCount(); i++) {\r
+                       r.index = i;\r
+                       b.getComponent(i).type.accept(this, obj);\r
+               }\r
+               stack.pop();\r
+       }\r
+       @Override\r
+       public void visit(VariantType b, Object obj) {\r
+                       Item item = (Item) obj;\r
+                       item.addVariant( toRef() );\r
+       }\r
+       ChildReference toRef() {\r
+               return ChildReference.compile(stack);\r
+       }\r
+       \r
+    }\r
+       \r
+\r
+}\r