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