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