1 /*******************************************************************************
2 * Copyright (c) 2007, 2011 Association for Decentralized Information Management in
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.graph.utils;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.HashMap;
17 import java.util.List;
19 import java.util.Stack;
21 import org.simantics.databoard.Accessors;
22 import org.simantics.databoard.Bindings;
23 import org.simantics.databoard.accessor.Accessor;
24 import org.simantics.databoard.accessor.ArrayAccessor;
25 import org.simantics.databoard.accessor.LongAccessor;
26 import org.simantics.databoard.accessor.MapAccessor;
27 import org.simantics.databoard.accessor.OptionalAccessor;
28 import org.simantics.databoard.accessor.RecordAccessor;
29 import org.simantics.databoard.accessor.UnionAccessor;
30 import org.simantics.databoard.accessor.VariantAccessor;
31 import org.simantics.databoard.accessor.error.AccessorConstructionException;
32 import org.simantics.databoard.accessor.error.AccessorException;
33 import org.simantics.databoard.accessor.reference.ChildReference;
34 import org.simantics.databoard.accessor.reference.ComponentReference;
35 import org.simantics.databoard.accessor.reference.IndexReference;
36 import org.simantics.databoard.binding.Binding;
37 import org.simantics.databoard.type.ArrayType;
38 import org.simantics.databoard.type.Datatype;
39 import org.simantics.databoard.type.LongType;
40 import org.simantics.databoard.type.MapType;
41 import org.simantics.databoard.type.OptionalType;
42 import org.simantics.databoard.type.RecordType;
43 import org.simantics.databoard.type.UnionType;
44 import org.simantics.databoard.type.VariantType;
45 import org.simantics.databoard.util.DatatypeVisitorAdapter;
48 * Util for converting all the Long values in a TG, that have metadata "resource=true".
50 * @author toni.kalajainen
52 public class TGResourceUtil {
54 public static final Datatype RESOURCE_TYPE;
56 Map<Datatype, Item> items = new HashMap<Datatype, Item>();
60 * Add type to the cache and get some info.
65 public Item createItem( Datatype type )
67 Item item = new Item();
70 HasResVisitor v = new HasResVisitor();
71 type.accept( v, item );
72 if ( v.hasRes || v.hasVariant ) {
73 GetRefsVisitor vv = new GetRefsVisitor();
74 type.accept( vv, item );
81 * Find all resources in the value. The resources are added to the result-collection.
82 * It may be good to idea to use a Set to avoid duplicate values.
87 * @throws AccessorException
88 * @throws AccessorConstructionException
90 public void findResources( Datatype type, byte[] value, final Collection<Long> result) throws AccessorConstructionException, AccessorException
92 LongAdapter la = new LongAdapter() {
94 public long adapt(long in) {
101 adaptValue( type, value, la );
104 public void findResources( Binding binding, Object value, final Collection<Long> result) throws AccessorConstructionException, AccessorException
106 LongAdapter la = new LongAdapter() {
108 public long adapt(long in) {
115 adaptValue( binding, value, la );
119 * Add type to the util.
123 public Item addType( Datatype type )
125 Item i = items.get( type );
127 i = createItem(type);
133 public void adaptValue( Datatype type, byte[] value, LongAdapter adapter ) throws AccessorException
135 Item i = addType( type );
136 if (!i.mayHaveResource()) return;
138 Accessor a = Accessors.getAccessor(value, type);
139 adaptValue(i, a, adapter);
140 } catch (AccessorConstructionException e) {
141 throw new AccessorException(e);
145 public boolean mayHaveResource( Datatype type ) {
146 Item i = addType( type );
147 return i.mayHaveResource();
150 public void adaptValue( Binding binding, Object value, LongAdapter adapter ) throws AccessorException
152 Item i = addType( binding.type() );
153 if (!i.mayHaveResource()) return;
155 Accessor a = Accessors.getAccessor(binding, value);
156 adaptValue(i, a, adapter);
157 } catch (AccessorConstructionException e) {
158 throw new AccessorException(e);
162 void adaptValue( Item i, Accessor a, LongAdapter adapter ) throws AccessorException, AccessorConstructionException
164 if ( i.resources != null ) {
165 for (ChildReference r : i.resources)
167 adaptValue(a, r, adapter);
170 if ( i.variants != null ) {
171 for (ChildReference r : i.variants)
173 adaptValue(a, r, adapter);
178 void adaptValue( Accessor a, ChildReference r, LongAdapter adapter ) throws AccessorException, AccessorConstructionException
180 if ( a instanceof LongAccessor ) {
181 LongAccessor x = (LongAccessor) a;
182 long value = x.getValue();
183 long newValue = adapter.adapt( value );
184 if ( newValue != value ) x.setValue( newValue );
187 if ( a instanceof VariantAccessor ) {
188 VariantAccessor x = (VariantAccessor) a;
189 Item i = createItem( x.getContentType() );
190 adaptValue(i, x.getContentAccessor(), adapter);
193 if ( a instanceof MapAccessor ) {
194 MapAccessor x = (MapAccessor) a;
195 if (r instanceof IndexReference) {
196 IndexReference ir = (IndexReference) r;
197 // Resource is in the Key
199 // Read the key as whole
200 Binding keyBinding = Bindings.getBinding( x.type().keyType );
201 Binding valueBinding = Bindings.getBinding( x.type().valueType );
202 Object[] keys = x.getKeys(keyBinding);
203 for ( Object key : keys ) {
204 Object value = x.get(keyBinding, key, valueBinding);
206 Accessor ka = Accessors.getAccessor(keyBinding, key);
207 adaptValue(ka, r.childReference, adapter);
210 x.remove(keyBinding, key);
211 x.put(keyBinding, key, valueBinding, value);
215 // Resource is in the value
217 Binding keyBinding = Bindings.getBinding( x.type().keyType );
218 Object[] keys = x.getKeys(keyBinding);
219 for ( Object key : keys ) {
220 Accessor va = x.getValueAccessor(keyBinding, key);
221 adaptValue(va, r.childReference, adapter);
227 if ( a instanceof ArrayAccessor ) {
228 ArrayAccessor x = (ArrayAccessor) a;
230 for (int i=0; i<len; i++) {
231 Accessor sa = x.getAccessor(i);
232 adaptValue(sa, r.childReference, adapter);
236 if ( a instanceof UnionAccessor ) {
237 UnionAccessor x = (UnionAccessor) a;
238 IndexReference ir = (IndexReference) r;
239 if ( x.getTag() == ir.index ) {
240 Accessor sa = x.getComponentAccessor();
241 adaptValue(sa, ir.childReference, adapter);
245 if ( a instanceof RecordAccessor ) {
246 RecordAccessor x = (RecordAccessor) a;
247 IndexReference ir = (IndexReference) r;
248 Accessor sa = x.getFieldAccessor(ir.index);
249 adaptValue(sa, ir.childReference, adapter);
252 if ( a instanceof OptionalAccessor ) {
253 OptionalAccessor x = (OptionalAccessor) a;
255 Accessor sa = x.getComponentAccessor();
256 adaptValue(sa, r.childReference, adapter);
262 public interface LongAdapter {
266 public static class Item {
268 public Datatype type;
271 // Locations of variants in Datatype
272 List<ChildReference> variants;
273 // Locations of resources in Datatype
274 List<ChildReference> resources;
276 public boolean mayHaveResource() {
277 return (variants!=null&&!variants.isEmpty()) ||
278 (resources!=null&&!resources.isEmpty());
281 void addVariant(ChildReference ref) {
282 if ( variants == null ) variants = new ArrayList<ChildReference>();
286 void addResource(ChildReference ref) {
287 if ( resources == null ) resources = new ArrayList<ChildReference>();
288 resources.add( ref );
293 RESOURCE_TYPE = new LongType();
294 RESOURCE_TYPE.metadata.put("resource", "true");
298 * This visitor makes a quick peek to see if there is resource or variants.
300 static class HasResVisitor extends DatatypeVisitorAdapter {
302 boolean hasRes = false, hasVariant = false;
305 public void visit(VariantType b, Object obj) {
310 public void visit(LongType b, Object obj) {
311 String s = b.metadata.get("unit");
312 hasRes |= s!=null && s.equals("resource");
317 static class GetRefsVisitor extends DatatypeVisitorAdapter {
319 Stack<ChildReference> stack = new Stack<ChildReference>();
322 public void visit(ArrayType b, Object obj) {
323 if ( !visited.add(b) ) return;
325 ComponentReference r = new ComponentReference();
327 b.componentType.accept(this, obj);
332 public void visit(LongType b, Object obj) {
333 String s = b.metadata.get("unit");
334 boolean isRes = s!=null && s.equals("resource");
336 Item item = (Item) obj;
337 item.addResource( toRef() );
341 public void visit(MapType b, Object obj) {
342 if ( !visited.add(b) ) return;
344 IndexReference r = new IndexReference(0);
346 b.keyType.accept(this, obj);
350 b.valueType.accept(this, obj);
354 public void visit(OptionalType b, Object obj) {
355 if ( !visited.add(b) ) return;
357 ComponentReference r = new ComponentReference();
359 b.componentType.accept(this, obj);
363 public void visit(RecordType b, Object obj) {
364 if ( !visited.add(b) ) return;
366 IndexReference r = new IndexReference(0);
368 for (int i=0; i<b.getComponentCount(); i++) {
370 b.getComponent(i).type.accept(this, obj);
375 public void visit(UnionType b, Object obj) {
376 if ( !visited.add(b) ) return;
378 IndexReference r = new IndexReference(0);
380 for (int i=0; i<b.getComponentCount(); i++) {
382 b.getComponent(i).type.accept(this, obj);
387 public void visit(VariantType b, Object obj) {
388 Item item = (Item) obj;
389 item.addVariant( toRef() );
391 ChildReference toRef() {
392 return ChildReference.compile(stack);