• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /barrelfish-2018-10-04/usr/eclipseclp/Visualisation/src/com/parctechnologies/eclipse/visualisation/
1// BEGIN LICENSE BLOCK
2// Version: CMPL 1.1
3//
4// The contents of this file are subject to the Cisco-style Mozilla Public
5// License Version 1.1 (the "License"); you may not use this file except
6// in compliance with the License.  You may obtain a copy of the License
7// at www.eclipse-clp.org/license.
8//
9// Software distributed under the License is distributed on an "AS IS"
10// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
11// the License for the specific language governing rights and limitations
12// under the License.
13//
14// The Original Code is  The ECLiPSe Constraint Logic Programming System.
15// The Initial Developer of the Original Code is  Cisco Systems, Inc.
16// Portions created by the Initial Developer are
17// Copyright (C) 2006 Cisco Systems, Inc.  All Rights Reserved.
18//
19// Contributor(s):
20//
21// END LICENSE BLOCK
22
23package com.parctechnologies.eclipse.visualisation;
24
25import java.util.*;
26import java.beans.*;
27import javax.swing.table.*;
28import com.parctechnologies.eclipse.*;
29
30/**
31 * A ViewletArray is a recursive data structure intended to mirror the number,
32 * size and fixity of the dimensions of a viewable on the eclipse side.
33 *
34 * Instead of viewable elements, it contains viewlets. Each viewlet is produced
35 * from a ViewletFactory.
36 * <p>
37 * Note that ViewletArray is not responsible for maintaining location names,
38 * only for keeping references to them and providing access to them.
39 */
40public class ViewletArray extends AbstractViewletDataStore implements MultiViewletDataStore
41{
42  /**
43   * This is a list of Integers which denotes this ViewletArray's location
44   * within the outermost ViewletArray. E.g. a top-level ViewletArray with
45   * size [4,3] would have location [], and its elements would have location
46   * [1], [2], [3], [4] and the elments of the first of these would have
47   * locations [1,1], [1,2] and [1,3].
48   */
49  private List location;
50
51  /**
52   * subFixity lists the fixities of Elements recursively. So a ViewletArray
53   * which mirrored a viewable with fixity [fixed, fixed, flexible] would have
54   * subFixity [fixed, flexible].
55   *
56   * */
57  private List subFixity;
58
59  /**
60   * elements is an instance of inner class Elements. If this ViewletArray is
61   * one-dimensional, the contents of elements are the viewlets of the
62   * ViewletArray. If this ViewletArray is multi-dimensional, then the contents
63   * of elements are the sub-ViewletArrays.
64   *
65   */
66  private Elements elements;
67
68  /**
69   *Hold the individual ViewletDataStores on a per type basis
70   */
71  private Map wrappedStoreMap;
72
73  /**
74   * Construct a ViewletArray given a list of integers (size), a fixity list
75   * (fixity) and a ViewletFactory to be used to populate it with Viewlets.
76   *
77   */
78  public ViewletArray(List size,
79		      List fixity,
80                      Viewable viewable,
81		      ViewletFactory viewletFactory)
82  {
83    this(size, fixity, viewable, viewletFactory, Collections.EMPTY_LIST);
84  }
85
86
87  /**
88   * Construct a ViewletArray given a list of integers (size), a fixity list
89   * (fixity), a ViewletFactory to be used to populate it with Viewlets and a
90   * list of integers to be the top level location (location).
91   * The sub-ViewletArrays will then have locations location @ [1], location @
92   * [2] etc. (where @ means append).
93   * <p>
94   * After setting up a few instance members based on the constructor's
95   * parameters, we initialise the elements member by inspecting the fixity of
96   * the top-level dimension. If it is 'fixed' we use FixedElements, and if it
97   * is 'flexible' we use FlexibleElements. These are both subclasses of
98   * Elements: FixedElements is optimized for fast access whereas
99   * FlexibleElements allows expansion.
100   * <p>
101   * To populate elements, we use createSubArray which will either fill it with
102   * Viewlets (in the one-dimensional case) or ViewletArrays in the
103   * multi-dimensional case. So, the ViewletArray constructor is mutually
104   * recursive with this static method.
105   *
106   */
107  private ViewletArray(List size, List fixity, Viewable viewable,
108                       ViewletFactory viewletFactory,
109                       List location)
110  {
111    super(size, fixity, viewable, viewletFactory);
112    int topLevelSize = ((Integer) size.get(0)).intValue();
113    this.wholeSize = new LinkedList(size);
114    this.topLevelFixity = (String) fixity.get(0);
115    List subSize = size.subList(1, size.size());
116    subFixity = fixity.subList(1, fixity.size());
117    this.viewletFactory = viewletFactory;
118    this.location = location;
119    if(topLevelFixity.equals(fixedString))
120    {
121      elements = new FixedElements(topLevelSize);
122    }
123    else
124    {
125      elements = new FlexibleElements(topLevelSize);
126    }
127    List subLocation;
128    for(int i = 0; i < topLevelSize; i++)
129    {
130      subLocation = new LinkedList(location);
131      subLocation.add(new Integer(i+1));
132      elements.set(i, createSubArray(subSize, subFixity, getViewable(), viewletFactory, subLocation));
133    }
134  }
135
136  /**
137   * dimNumber starts from 1. List should be a list of Strings.
138   */
139  public void setLocationNames(int dimNumber, List locationNames)
140  {
141      super.setLocationNames(dimNumber, locationNames);
142  }
143
144  /**
145   * dimNumber starts from 1.
146   */
147  public void finishExpandDimension(int dimNumber)
148  {
149      super.finishExpandDimension(dimNumber);
150  }
151
152  /**
153   * Traverses the entire structure recursively to collect together all the
154   * element indices.
155   */
156  public ViewletRange getEntireViewletRange()
157  {
158      return super.getEntireViewletRange();
159//      List elementsList = elements.toList();
160//      if(wholeSize.size() == 1)
161//      {
162//  	ViewletRange res = new ViewletRangeCollection();
163//  	res.addAll(elementsList);
164//        return(res);
165//      }
166//      Iterator elementsIterator = elementsList.iterator();
167//      ViewletArray viewletArray;
168//      ViewletRange result = new ViewletRangeCollection();
169//      while(elementsIterator.hasNext())
170//      {
171//        viewletArray = (ViewletArray) elementsIterator.next();
172//        result.addAll(viewletArray.getAllViewletData());
173//      }
174//      return(result);
175  }
176
177  /**
178   * Returns an Object to be inserted into the elements member of a
179   * ViewletArray. This method is mutually recursive with the ViewletArray
180   * constructor.<p>
181   * If size isEmpty then the elements object being populated is one-dimensional
182   * and so the method uses the ViewletFactory parameter to build a Viewlet and
183   * returns the Viewlet. The newViewlet's elementReference is set based on
184   * its location within the top level ViewletArray. <p>
185   * Otherwise, the elements object being populated is multi-dimensional and so
186   * the returned object is a ViewletArray, returned by the constructor.
187   *
188   */
189  private static Object createSubArray(List size, List fixity,
190                                       Viewable viewable,
191                                       ViewletFactory viewletFactory,
192                                       List location)
193  {
194    if(size.isEmpty())
195    {
196
197	if (DebuggingSupport.logMessages) {
198	    DebuggingSupport.logMessage(null,
199					"building viewlet with location: "+
200					location);
201	}
202
203      ViewletData newViewlet = viewletFactory.build();
204      return(newViewlet);
205    }
206    else
207    {
208      return(new ViewletArray(size, fixity, viewable, viewletFactory,
209			      location));
210    }
211  }
212
213  /**
214   * Shrinks the ViewletArray to size newSize. Assumes the top-level fixity is
215   * flexible.
216   */
217  public void shrinkTo(List newSize)
218  {
219      super.shrinkTo(newSize);
220    if(wholeSize.equals(newSize)) // no change necessary
221    {
222      return;
223    }
224    // First shrink the top level dimension.
225    int newTopLevelSize = ((Integer) newSize.get(0)).intValue();
226    elements.shrinkTo(newTopLevelSize);
227    if(wholeSize.size() > 1) // recursion necessary
228    {
229      // Cast each element to a Viewlet array and shrink recursively.
230      List subNewSize = newSize.subList(1, newSize.size());
231      for(int i = 0; i < elements.size(); i++)
232      {
233        ((ViewletArray) elements.get(i)).shrinkTo(subNewSize);
234      }
235    }
236    wholeSize = new LinkedList(newSize);
237    // Indicate to the table that rows/columns have been removed
238    fireTableStructureChanged();
239  }
240
241  /**
242   * Expand dimension nested at level <code>dimension</code> by one. If the
243   * parameter dimension is greater than 1 this means that this.elements stays
244   * the same size and it is the sub-ViewletArrays which expand. Otherwise, we
245   * have to expand the top level by adding a new object to elements. This is
246   * created using createSubArray.
247   */
248  public void startExpandDimension(int dimension)
249  {
250      super.startExpandDimension(dimension);
251    Integer oldDimSize = (Integer) wholeSize.get(dimension-1);
252    Integer newDimSize =
253      new Integer(oldDimSize.intValue() + 1);
254    if(dimension > 1)
255    {
256      for(int i = 0; i < elements.size(); i++)
257      {
258        ((ViewletArray) elements.get(i)).startExpandDimension(dimension - 1);
259      }
260    }
261    else
262    {
263      List subSize = wholeSize.subList(1, wholeSize.size());
264      List subLocation = new LinkedList(location);
265      subLocation.add(newDimSize);
266      elements.expand(createSubArray(subSize, subFixity,
267                                     getViewable(),
268                                     viewletFactory, subLocation));
269    }
270  }
271
272
273    /**
274     * Implements the abstract getViewletDataAt method
275     */
276  public ViewletData getViewletDataAt(List index)
277  {
278    if(index.size() != getSize().size())
279    {
280      throw(new IllegalArgumentException());
281    }
282    return((ViewletData) getElement(index));
283  }
284
285    /**
286     * Implements the abstract setViewletDataAt method
287     */
288  public void setViewletDataAt(List index, ViewletData data)
289  {
290    if(index.size() != getSize().size())
291    {
292      throw(new IllegalArgumentException());
293    }
294    setElement(index, data);
295  }
296
297  /**
298   * Get element with location index within the ViewletArray. Result may be a
299   * ViewletArray or a Viewlet, depending on the length of the index parameter.
300   */
301  private Object getElement(List index)
302  {
303    Object sub =
304      elements.get(((Integer) index.get(0)).intValue() - 1);
305    if(index.size() == 1)
306    {
307      return(sub);
308    }
309    List subIndex = index.subList(1, index.size());
310    return(((ViewletArray) sub).getElement(subIndex));
311  }
312
313  /**
314   * Sets the element with location index within the ViewletArray. */
315  private void setElement(List index, Object data)
316  {
317    if (index.size() == 1) {
318      elements.set(((Integer) index.get(0)).intValue() - 1, data);
319    } else {
320      Object sub =
321	elements.get(((Integer) index.get(0)).intValue() - 1);
322      List subIndex = index.subList(1, index.size());
323      ((ViewletArray) sub).setElement(subIndex, data);
324    }
325  }
326
327  /**
328   * Abstract superclass of the two classes which the elements member may
329   * instantiate.
330   */
331  private abstract class Elements
332  {
333    abstract Object get(int index);
334    abstract void set(int index, Object element);
335    void expand(Object newElement){}
336    void shrinkTo(int newSize){}
337    abstract int size();
338    abstract List toList();
339  }
340
341  /**
342   * FixedElements is basically just a bridge between an Object array and
343   * Elements
344   */
345  private class FixedElements extends Elements
346  {
347    private Object[] elements;
348    FixedElements(int size)
349    {
350      elements = new Object[size];
351    }
352    Object get(int index)
353    {
354      return(elements[index]);
355    }
356    void set(int index, Object element)
357    {
358      elements[index] = element;
359    }
360    int size()
361    {
362      return(elements.length);
363    }
364    List toList()
365    {
366      LinkedList result = new LinkedList();
367      for(int i = 0; i < elements.length; i++)
368      {
369        result.add(elements[i]);
370      }
371      return(result);
372    }
373  }
374
375  /**
376   * FlexibleElements is basically just a bridge between a Vector and
377   * Elements. If there is a better class which supports expanding and
378   * shrinking (maybe LinkedList?), this could be substituted for Vector.
379   */
380  private class FlexibleElements extends Elements
381  {
382    private Vector elements;
383    FlexibleElements(int size)
384    {
385      elements = new Vector(size);
386      elements.setSize(size);
387    }
388    Object get(int index)
389    {
390      return(elements.get(index));
391    }
392    void set(int index, Object element)
393    {
394      elements.set(index, element);
395    }
396    int size()
397    {
398      return(elements.size());
399    }
400    void expand(Object newElement)
401    {
402      elements.add(newElement);
403    }
404    void shrinkTo(int newSize)
405    {
406      while(size() > newSize)
407      {
408        elements.remove(newSize);
409      }
410    }
411    List toList()
412    {
413      return(new LinkedList(elements));
414    }
415  }
416
417
418    /**
419     * Returns a wrapper store which intercedes whenever viewlet data
420     * is get or set.
421     *
422     * Implements method from the MultiViewletDataStore interface
423     * */
424    public ViewletDataStore getViewletDataStore(ViewletType type) {
425      // Note the outer test is not synchronized to speed up normal code flow
426      // but the test is duplicated within
427      if (wrappedStoreMap == null) {
428        synchronized(this) {
429          if (wrappedStoreMap == null) {
430            wrappedStoreMap=new HashMap();
431          }
432        }
433      }
434      ViewletDataStore result = (ViewletDataStore)wrappedStoreMap.get(type);
435      if (result == null) {
436        synchronized(this) {
437          if (result == null) {
438            result =
439              new WrappedMultiViewletDataStore(this, type);
440            result.setSymRef(new SymRef(result,this.getSymRef(),type.getClass().getName()));
441            wrappedStoreMap.put(type, result);
442          }
443        }
444      }
445      return result;
446    }
447
448}
449
450
451
452
453
454
455