KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tonbeller > jpivot > table > span > PropertySpanBuilder


1 /*
2  * ====================================================================
3  * This software is subject to the terms of the Common Public License
4  * Agreement, available at the following URL:
5  * http://www.opensource.org/licenses/cpl.html .
6  * Copyright (C) 2003-2004 TONBELLER AG.
7  * All Rights Reserved.
8  * You must accept the terms of that agreement to use this software.
9  * ====================================================================
10  *
11  *
12  */

13 package com.tonbeller.jpivot.table.span;
14
15 import java.beans.PropertyChangeListener JavaDoc;
16 import java.beans.PropertyChangeSupport JavaDoc;
17 import java.util.ArrayList JavaDoc;
18 import java.util.Collection JavaDoc;
19 import java.util.Collections JavaDoc;
20 import java.util.HashMap JavaDoc;
21 import java.util.HashSet JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.util.Set JavaDoc;
26
27 import javax.servlet.http.HttpSession JavaDoc;
28
29 import org.apache.log4j.Logger;
30
31 import com.tonbeller.jpivot.core.ModelChangeEvent;
32 import com.tonbeller.jpivot.core.ModelChangeListener;
33 import com.tonbeller.jpivot.olap.model.Member;
34 import com.tonbeller.jpivot.olap.model.MemberPropertyMeta;
35 import com.tonbeller.jpivot.olap.model.OlapModel;
36 import com.tonbeller.jpivot.olap.model.Property;
37 import com.tonbeller.jpivot.olap.model.impl.PropertyImpl;
38 import com.tonbeller.jpivot.olap.navi.MemberProperties;
39 import com.tonbeller.jpivot.ui.Available;
40 import com.tonbeller.wcf.controller.RequestContext;
41
42 /**
43  * adds Span elements to a SpanCalc containing Member Properties.
44  * @author av
45  */

46 public class PropertySpanBuilder implements PropertyConfig, ModelChangeListener, Available {
47
48   private MemberProperties extension;
49   private OlapModel model;
50   
51   private List JavaDoc[] propertyColumns;
52   private int PCOUNT;
53   private int HCOUNT;
54   private SpanCalc spanCalc;
55   private PropertyChangeSupport JavaDoc propertyChangeSupport = new PropertyChangeSupport JavaDoc(this);
56   private static Logger logger = Logger.getLogger(PropertySpanBuilder.class);
57
58   /** List of all visible Properties - these may be filled in by some GUI */
59   private List JavaDoc visiblePropertyMetas = null;
60   private boolean showProperties = false;
61
62   /**
63    * for every property name contains an empty property with that name
64    */

65   private Map JavaDoc emptyPropertyMap = new HashMap JavaDoc();
66
67   /**
68    * for every hierarchyIndex contains the names of all properties of all members
69    */

70   private ScopedPropertyMetaSet metaSet;
71
72   private AllPropertiesMap allPropertiesMap;
73
74   /**
75    * collects the normalized propertiy instances of all members.
76    * <ol>
77    * <li>The map only includes top-level properties,
78    * nested properties (properties of properties) are <em>not</em> included</li>
79    * <li>Inline properties, that result in decoration of the member
80    * (like hyperlinks), are <em>not</em> included.</li>
81    * </ol>
82    */

83   static class AllPropertiesMap {
84     private Map JavaDoc map = new HashMap JavaDoc();
85     private Set JavaDoc set = new HashSet JavaDoc();
86
87     void add(Member member) {
88       if (member == null)
89         return;
90
91       if (set.contains(member))
92         return;
93       set.add(member);
94
95       Property[] props = member.getProperties();
96       props = PropertyUtils.normalize(props);
97       List JavaDoc list = new ArrayList JavaDoc();
98       for (int i = 0; i < props.length; i++) {
99         Property p = props[i];
100         // ignore inline properties
101
if (PropertyUtils.isInline(p.getName()))
102           continue;
103         list.add(p);
104       }
105       map.put(member, list);
106     }
107
108     List JavaDoc getProperties(Member member) {
109       return (List JavaDoc) map.get(member);
110     }
111   }
112
113   class PropertyLookup {
114     Map JavaDoc map = new HashMap JavaDoc();
115     void clear() {
116       map.clear();
117     }
118     void addAll(Collection JavaDoc properties) {
119       for (Iterator JavaDoc it = properties.iterator(); it.hasNext();) {
120         Property p = (Property) it.next();
121         map.put(p.getName(), p);
122       }
123     }
124     Property getProperty(String JavaDoc name) {
125       return (Property) map.get(name);
126     }
127   }
128
129   /**
130    * for testing only
131    */

132   PropertySpanBuilder(MemberProperties extension) {
133     this.model = null;
134     this.extension = extension;
135   }
136
137   public PropertySpanBuilder(OlapModel model) {
138     this.model = model;
139     this.extension = (MemberProperties) model.getExtension(MemberProperties.ID);
140   }
141
142   public void initialize(RequestContext context) {
143     model.addModelChangeListener(this);
144   }
145   public void destroy(HttpSession JavaDoc session) {
146     model.removeModelChangeListener(this);
147   }
148   
149   public void modelChanged(ModelChangeEvent e) {
150   }
151
152   public void structureChanged(ModelChangeEvent e) {
153     extension = (MemberProperties) model.getExtension(MemberProperties.ID);
154     setVisiblePropertyMetas(null);
155     setShowProperties(false);
156   }
157
158   public boolean isAvailable() {
159     return model.getExtension(MemberProperties.ID) != null;
160   }
161   
162   /** initializes fields */
163   private void reset(SpanCalc spanCalc) {
164     // initialize instance variables
165
this.emptyPropertyMap.clear();
166     this.allPropertiesMap = new AllPropertiesMap();
167     this.metaSet = new ScopedPropertyMetaSet(extension);
168     this.spanCalc = spanCalc;
169     this.HCOUNT = spanCalc.getHierarchyCount();
170     this.PCOUNT = spanCalc.getPositionCount();
171
172     collectProperties();
173     initializePropertyColumns();
174   }
175
176   /**
177    * collects all properties and their metadata from result
178    */

179   void collectProperties() {
180     Span[][] spans = spanCalc.getSpans();
181
182     for (int hi = 0; hi < HCOUNT; hi++) {
183       for (int pi = 0; pi < PCOUNT; pi++) {
184         Span s = spans[pi][hi];
185         if (s.isMember()) {
186           Member m = s.getMember();
187           metaSet.addMember(m);
188           allPropertiesMap.add(m);
189         }
190       }
191     }
192   }
193
194   /**
195    * initializes the propertyColumns field.
196    * Computes the visible MemberPropertyMetas for
197    * every column.
198    */

199   void initializePropertyColumns() {
200     propertyColumns = new List JavaDoc[HCOUNT];
201     for (int i = 0; i < HCOUNT; i++)
202       propertyColumns[i] = Collections.EMPTY_LIST;
203
204     // no positions -> no properties
205
if (PCOUNT == 0)
206       return;
207
208     // for every column compute the set of
209
// valid scopes, e.g. levels
210
Set JavaDoc[] scopes = new Set JavaDoc[HCOUNT];
211     Span[][] spans = spanCalc.getSpans();
212     for (int hi = 0; hi < HCOUNT; hi++) {
213       Set JavaDoc set = new HashSet JavaDoc();
214       for (int pi = 0; pi < PCOUNT; pi++)
215         set.add(getScope(spans[pi][hi]));
216       scopes[hi] = set;
217     }
218
219     // for every column compute the visible MemberPropertyMetas
220
Set JavaDoc done = new HashSet JavaDoc();
221     for (int hi = 0; hi < HCOUNT; hi++) {
222       // from all MemberPropertyMetas keep only those that match the scopes
223
// of this column. Also remove all metas that denote inline properties.
224
// Finally intersect with the list of all visible properties
225
MemberPropertyMetaFilter scopesFilter = metaSet.createScopesFilter(scopes[hi]);
226       MemberPropertyMetaFilter inlineFilter = metaSet.createIgnoreInlineFilter();
227
228       if (hi == (HCOUNT - 1) || !scopes[hi].equals(scopes[hi + 1])) {
229         ScopedPropertyMetaSet sub = metaSet.metaSet(scopesFilter);
230         sub.removeAll(done);
231         if (visiblePropertyMetas == null)
232           propertyColumns[hi] = sub.metaList(inlineFilter);
233         else
234           propertyColumns[hi] = sub.intersectList(visiblePropertyMetas);
235         done.addAll(propertyColumns[hi]);
236       }
237     }
238   }
239
240   Object JavaDoc getScope(Span s) {
241     // if its not a member, the span itself is the scope
242
if (!s.isMember())
243       return s;
244     return extension.getPropertyScope((Member) s.getMember().getRootDecoree());
245   }
246
247   /**
248    * adds property columns to sc
249    * @param sc the SpanCalc to modify
250    */

251   public void addPropertySpans(SpanCalc sc) {
252     if (extension == null || !showProperties)
253       return;
254     logger.info("adding properties");
255
256     // initialize the PropertyConfig model
257
reset(sc);
258
259     // compute result size
260
int newHierCount = spanCalc.getHierarchyCount();
261     for (int hi = 0; hi < HCOUNT; hi++)
262       newHierCount += propertyColumns[hi].size();
263
264     // create matrix
265
Span[][] dst = new Span[PCOUNT][];
266     for (int pi = 0; pi < PCOUNT; pi++)
267       dst[pi] = new Span[newHierCount];
268     Span[][] src = spanCalc.getSpans();
269
270     // fill matrix
271
PropertyLookup lookup = new PropertyLookup();
272     for (int pi = 0; pi < PCOUNT; pi++) {
273       int dstHierIndex = 0;
274       lookup.clear();
275       for (int hi = 0; hi < HCOUNT; hi++) {
276         Span span = src[pi][hi];
277         dst[pi][dstHierIndex++] = span;
278
279         if (span.isMember())
280           lookup.addAll(allPropertiesMap.getProperties(span.getMember()));
281
282         // copy the properties
283
Object JavaDoc scope = getScope(span);
284         for (Iterator JavaDoc it = propertyColumns[hi].iterator(); it.hasNext();) {
285           MemberPropertyMeta mpm = (MemberPropertyMeta) it.next();
286           Property prop = null;
287           if (mpm.getScope().equals(scope))
288             prop = lookup.getProperty(mpm.getName());
289           if (prop == null)
290             prop = emptyProperty(mpm.getName(), mpm.getLabel());
291           dst[pi][dstHierIndex++] = new Span(span.getAxis(), span.getPosition(), prop);
292         }
293       }
294     }
295
296     spanCalc.setSpans(dst);
297   }
298
299   /**
300    * returns an empty Property instance for a given name.
301    * If queried multiple times for the same name, the same
302    * object instance is returned (necessary for
303    * span computation when a single property spans multiple cells of the table axis).
304    */

305   Property emptyProperty(String JavaDoc name, String JavaDoc label) {
306     Property p = (Property) emptyPropertyMap.get(name);
307     if (p != null)
308       return p;
309     PropertyImpl pi = new PropertyImpl();
310     pi.setName(name);
311     pi.setLabel(label);
312     pi.setValue("");
313     emptyPropertyMap.put(name, pi);
314     return pi;
315   }
316
317   /* ----------------------- PropertyConfig methods ------------------------------- */
318   
319   public boolean isShowProperties() {
320     return showProperties;
321   }
322
323   public void setShowProperties(boolean b) {
324     Object JavaDoc oldValue = new Boolean JavaDoc(showProperties);
325     this.showProperties = b;
326     setVisiblePropertiesExtension();
327     Object JavaDoc newValue = new Boolean JavaDoc(showProperties);
328     propertyChangeSupport.firePropertyChange("showProperties", oldValue, newValue);
329   }
330
331   public void setVisiblePropertyMetas(List JavaDoc metas) {
332     Object JavaDoc oldValue = visiblePropertyMetas;
333     this.visiblePropertyMetas = metas;
334     setVisiblePropertiesExtension();
335     Object JavaDoc newValue = visiblePropertyMetas;
336     propertyChangeSupport.firePropertyChange("visiblePropertyMetas", oldValue, newValue);
337   }
338
339   public List JavaDoc getVisiblePropertyMetas() {
340     return visiblePropertyMetas;
341   }
342
343   public void addPropertyChangeListener(PropertyChangeListener JavaDoc l) {
344     propertyChangeSupport.addPropertyChangeListener(l);
345   }
346   public void removePropertyChangeListener(PropertyChangeListener JavaDoc l) {
347     propertyChangeSupport.removePropertyChangeListener(l);
348   }
349
350   public static class BookmarkState {
351     boolean showProperties = false;
352     List JavaDoc visibleProperties = null;
353     public boolean isShowProperties() {
354       return showProperties;
355     }
356     public List JavaDoc getVisibleProperties() {
357       return visibleProperties;
358     }
359     public void setShowProperties(boolean b) {
360       showProperties = b;
361     }
362     public void setVisibleProperties(List JavaDoc list) {
363       visibleProperties = list;
364     }
365   }
366
367   public Object JavaDoc getBookmarkState(int levelOfDetail) {
368     BookmarkState x = new BookmarkState();
369     x.setShowProperties(isShowProperties());
370     if (visiblePropertyMetas != null) {
371       ArrayList JavaDoc metas = new ArrayList JavaDoc();
372       metas.addAll(visiblePropertyMetas);
373       x.setVisibleProperties(metas);
374     }
375     return x;
376   }
377
378   public void setBookmarkState(Object JavaDoc state) {
379     if (!(state instanceof BookmarkState))
380       return;
381     BookmarkState x = (BookmarkState) state;
382     setVisiblePropertyMetas(x.getVisibleProperties());
383     setShowProperties(x.isShowProperties());
384   }
385
386
387   /**
388    * updates the visibleProperties in the extension
389    */

390   protected void setVisiblePropertiesExtension() {
391     if (extension == null)
392       return;
393     if (!showProperties || visiblePropertyMetas == null) {
394       extension.setVisibleProperties(new MemberPropertyMeta[0]);
395       return;
396     }
397     MemberPropertyMeta[] mps = new MemberPropertyMeta[visiblePropertyMetas.size()];
398     mps = (MemberPropertyMeta[]) visiblePropertyMetas.toArray(mps);
399     extension.setVisibleProperties(mps);
400   }
401
402
403 }
404
Popular Tags