]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 /*******************************************************************************
2  * Copyright (c) 2007, 2011 Association for Decentralized Information Management in
3  * Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.graph.utils;
13
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.HashMap;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Stack;
20
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;
46
47 /**
48  * Util for converting all the Long values in a TG, that have metadata "resource=true".
49  * 
50  * @author toni.kalajainen
51  */
52 public class TGResourceUtil {
53         
54         public static final Datatype RESOURCE_TYPE;
55         
56         Map<Datatype, Item> items = new HashMap<Datatype, Item>();
57         int index = 0;
58
59         /**
60          * Add type to the cache and get some info.
61          * 
62          * @param type
63          * @return
64          */
65         public Item createItem( Datatype type )
66         {
67                 Item item = new Item();
68                 item.index = index++;
69                 item.type = type;
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 );
75                 }
76                 return item;
77         }
78         
79         
80         /**
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.  
83          * 
84          * @param type
85          * @param value
86          * @param result
87          * @throws AccessorException 
88          * @throws AccessorConstructionException 
89          */
90         public void findResources( Datatype type, byte[] value, final Collection<Long> result) throws AccessorConstructionException, AccessorException
91         {
92                 LongAdapter la = new LongAdapter() {
93                         @Override
94                         public long adapt(long in) {
95                                 result.add(in);
96                                 // Return same value
97                                 return in;
98                         }                       
99                 };
100                 
101                 adaptValue( type, value, la );
102         }
103
104         public void findResources( Binding binding, Object value, final Collection<Long> result) throws AccessorConstructionException, AccessorException
105         {
106                 LongAdapter la = new LongAdapter() {
107                         @Override
108                         public long adapt(long in) {
109                                 result.add(in);
110                                 // Return same value
111                                 return in;
112                         }                       
113                 };
114                 
115                 adaptValue( binding, value, la );
116         }
117         
118         /**
119          * Add type to the util.
120          * @param type
121          * @return
122          */
123         public Item addType( Datatype type )
124         {
125                 Item i = items.get( type );
126                 if ( i==null ) {
127                         i = createItem(type);
128                         items.put(type, i);
129                 }
130                 return i;
131         }
132         
133         public void adaptValue( Datatype type, byte[] value, LongAdapter adapter ) throws AccessorException
134         {
135                 Item i = addType( type );
136                 if (!i.mayHaveResource()) return;
137                 try {
138                         Accessor a = Accessors.getAccessor(value, type);
139                         adaptValue(i, a, adapter);
140                 } catch (AccessorConstructionException e) {
141                         throw new AccessorException(e);
142                 }
143         }
144         
145         public boolean mayHaveResource( Datatype type ) {
146         Item i = addType( type );
147         return i.mayHaveResource();
148         }
149         
150         public void adaptValue( Binding binding, Object value, LongAdapter adapter ) throws AccessorException
151         {
152                 Item i = addType( binding.type() );
153                 if (!i.mayHaveResource()) return;
154                 try {
155                         Accessor a = Accessors.getAccessor(binding, value);
156                         adaptValue(i, a, adapter);
157                 } catch (AccessorConstructionException e) {
158                         throw new AccessorException(e);
159                 }
160         }
161         
162         void adaptValue( Item i, Accessor a, LongAdapter adapter ) throws AccessorException, AccessorConstructionException
163         {
164                 if ( i.resources != null ) {
165                         for (ChildReference r : i.resources)
166                         {
167                                 adaptValue(a, r, adapter);
168                         }
169                 }
170                 if ( i.variants != null ) {
171                         for (ChildReference r : i.variants)
172                         {
173                                 adaptValue(a, r, adapter);
174                         }
175                 }
176         }
177         
178         void adaptValue( Accessor a, ChildReference r, LongAdapter adapter ) throws AccessorException, AccessorConstructionException
179         {
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 );
185                 }
186
187                 if ( a instanceof VariantAccessor ) {
188                         VariantAccessor x = (VariantAccessor) a;
189                         Item i = createItem( x.getContentType() );
190                         adaptValue(i, x.getContentAccessor(), adapter);
191                 }
192                 
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
198                                 if (ir.index==0) {
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);
205                                                 // Fix the key
206                                                 Accessor ka = Accessors.getAccessor(keyBinding, key);
207                                                 adaptValue(ka, r.childReference, adapter);
208                                                 
209                                                 // Write 
210                                                 x.remove(keyBinding, key);
211                                                 x.put(keyBinding, key, valueBinding, value);
212                                         }
213                                 }
214                                 
215                                 // Resource is in the value
216                                 if (ir.index==1) {
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);
222                                         }
223                                 }
224                         }                       
225                 }
226                 
227                 if ( a instanceof ArrayAccessor ) {
228                         ArrayAccessor x = (ArrayAccessor) a;
229                         int len = x.size();
230                         for (int i=0; i<len; i++) {
231                                 Accessor sa = x.getAccessor(i);                         
232                                 adaptValue(sa, r.childReference, adapter);
233                         }
234                 }
235                 
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);
242                         }
243                 }
244                 
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);
250                 }
251                 
252                 if ( a instanceof OptionalAccessor ) {
253                         OptionalAccessor x = (OptionalAccessor) a;
254                         if (x.hasValue()) {
255                                 Accessor sa = x.getComponentAccessor();
256                                 adaptValue(sa, r.childReference, adapter);
257                         }
258                 }
259                 
260         }
261         
262         public interface LongAdapter {
263                 long adapt(long in);
264         }
265         
266         public static class Item {
267                 // The datatype
268                 public Datatype type;
269                 // Index of the type
270                 public int index;
271                 // Locations of variants in Datatype  
272                 List<ChildReference> variants; 
273                 // Locations of resources in Datatype  
274                 List<ChildReference> resources;
275                 
276                 public boolean mayHaveResource() {
277                         return (variants!=null&&!variants.isEmpty()) || 
278                                         (resources!=null&&!resources.isEmpty());
279                 }
280                 
281                 void addVariant(ChildReference ref) {
282                         if ( variants == null ) variants = new ArrayList<ChildReference>();
283                         variants.add(ref);
284                 }
285                 
286                 void addResource(ChildReference ref) {
287                         if ( resources == null ) resources = new ArrayList<ChildReference>();
288                         resources.add( ref );
289                 }
290         }
291         
292     static {
293         RESOURCE_TYPE = new LongType();
294         RESOURCE_TYPE.metadata.put("resource", "true");
295     }
296     
297     /**
298      * This visitor makes a quick peek to see if there is resource or variants.
299      */
300     static class HasResVisitor extends DatatypeVisitorAdapter {
301
302         boolean hasRes = false, hasVariant = false;
303         
304         @Override
305         public void visit(VariantType b, Object obj) {
306                 hasVariant = true;
307         }
308         
309         @Override
310         public void visit(LongType b, Object obj) {
311                 String s = b.metadata.get("unit");
312                 hasRes |= s!=null && s.equals("resource");
313         }
314         
315     }
316     
317     static class GetRefsVisitor extends DatatypeVisitorAdapter {
318         
319         Stack<ChildReference> stack = new Stack<ChildReference>(); 
320     
321         @Override
322         public void visit(ArrayType b, Object obj) {                    
323                 if ( !visited.add(b) ) return; 
324                 
325                 ComponentReference r = new ComponentReference();
326                 stack.push(r);
327                 b.componentType.accept(this, obj);
328                 stack.pop();
329         }
330         
331         @Override
332         public void visit(LongType b, Object obj) {
333                 String s = b.metadata.get("unit");
334                 boolean isRes = s!=null && s.equals("resource");
335                 if ( isRes ) {
336                         Item item = (Item) obj;
337                         item.addResource( toRef() );
338                 }
339         }
340         @Override
341         public void visit(MapType b, Object obj) {
342                 if ( !visited.add(b) ) return;                  
343                 
344                 IndexReference r = new IndexReference(0);
345                 stack.push(r);
346                 b.keyType.accept(this, obj);
347                 stack.pop();
348                 r.index = 1;
349                 stack.push(r);
350                 b.valueType.accept(this, obj);
351                 stack.pop();
352         }
353         @Override
354         public void visit(OptionalType b, Object obj) {
355                 if ( !visited.add(b) ) return; 
356                 
357                 ComponentReference r = new ComponentReference();
358                 stack.push(r);
359                 b.componentType.accept(this, obj);
360                 stack.pop();
361         }
362         @Override
363         public void visit(RecordType b, Object obj) {
364                 if ( !visited.add(b) ) return; 
365                 
366                         IndexReference r = new IndexReference(0);
367                         stack.push(r);
368                 for (int i=0; i<b.getComponentCount(); i++) {
369                         r.index = i;
370                         b.getComponent(i).type.accept(this, obj);
371                 }
372                 stack.pop();
373         }
374         @Override
375         public void visit(UnionType b, Object obj) {
376                 if ( !visited.add(b) ) return;                  
377                 
378                         IndexReference r = new IndexReference(0);
379                         stack.push(r);
380                 for (int i=0; i<b.getComponentCount(); i++) {
381                         r.index = i;
382                         b.getComponent(i).type.accept(this, obj);
383                 }
384                 stack.pop();
385         }
386         @Override
387         public void visit(VariantType b, Object obj) {
388                         Item item = (Item) obj;
389                         item.addVariant( toRef() );
390         }
391         ChildReference toRef() {
392                 return ChildReference.compile(stack);
393         }
394         
395     }
396         
397
398 }