📄 propertyspanbuilder.java
字号:
/*
* ====================================================================
* This software is subject to the terms of the Common Public License
* Agreement, available at the following URL:
* http://www.opensource.org/licenses/cpl.html .
* Copyright (C) 2003-2004 TONBELLER AG.
* All Rights Reserved.
* You must accept the terms of that agreement to use this software.
* ====================================================================
*
*
*/
package com.tonbeller.jpivot.table.span;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
import com.tonbeller.jpivot.core.ModelChangeEvent;
import com.tonbeller.jpivot.core.ModelChangeListener;
import com.tonbeller.jpivot.olap.model.Member;
import com.tonbeller.jpivot.olap.model.MemberPropertyMeta;
import com.tonbeller.jpivot.olap.model.OlapModel;
import com.tonbeller.jpivot.olap.model.Property;
import com.tonbeller.jpivot.olap.model.impl.PropertyImpl;
import com.tonbeller.jpivot.olap.navi.MemberProperties;
import com.tonbeller.jpivot.ui.Available;
import com.tonbeller.wcf.controller.RequestContext;
/**
* adds Span elements to a SpanCalc containing Member Properties.
* @author av
*/
public class PropertySpanBuilder implements PropertyConfig, ModelChangeListener, Available {
private MemberProperties extension;
private OlapModel model;
private List[] propertyColumns;
private int PCOUNT;
private int HCOUNT;
private SpanCalc spanCalc;
private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
private static Logger logger = Logger.getLogger(PropertySpanBuilder.class);
/** List of all visible Properties - these may be filled in by some GUI */
private List visiblePropertyMetas = null;
private boolean showProperties = false;
/**
* for every property name contains an empty property with that name
*/
private Map emptyPropertyMap = new HashMap();
/**
* for every hierarchyIndex contains the names of all properties of all members
*/
private ScopedPropertyMetaSet metaSet;
private AllPropertiesMap allPropertiesMap;
/**
* collects the normalized propertiy instances of all members.
* <ol>
* <li>The map only includes top-level properties,
* nested properties (properties of properties) are <em>not</em> included</li>
* <li>Inline properties, that result in decoration of the member
* (like hyperlinks), are <em>not</em> included.</li>
* </ol>
*/
static class AllPropertiesMap {
private Map map = new HashMap();
private Set set = new HashSet();
void add(Member member) {
if (member == null)
return;
if (set.contains(member))
return;
set.add(member);
Property[] props = member.getProperties();
props = PropertyUtils.normalize(props);
List list = new ArrayList();
for (int i = 0; i < props.length; i++) {
Property p = props[i];
// ignore inline properties
if (PropertyUtils.isInline(p.getName()))
continue;
list.add(p);
}
map.put(member, list);
}
List getProperties(Member member) {
return (List) map.get(member);
}
}
class PropertyLookup {
Map map = new HashMap();
void clear() {
map.clear();
}
void addAll(Collection properties) {
for (Iterator it = properties.iterator(); it.hasNext();) {
Property p = (Property) it.next();
map.put(p.getName(), p);
}
}
Property getProperty(String name) {
return (Property) map.get(name);
}
}
/**
* for testing only
*/
PropertySpanBuilder(MemberProperties extension) {
this.model = null;
this.extension = extension;
}
public PropertySpanBuilder(OlapModel model) {
this.model = model;
this.extension = (MemberProperties) model.getExtension(MemberProperties.ID);
}
public void initialize(RequestContext context) {
model.addModelChangeListener(this);
}
public void destroy(HttpSession session) {
model.removeModelChangeListener(this);
}
public void modelChanged(ModelChangeEvent e) {
}
public void structureChanged(ModelChangeEvent e) {
extension = (MemberProperties) model.getExtension(MemberProperties.ID);
setVisiblePropertyMetas(null);
setShowProperties(false);
}
public boolean isAvailable() {
return model.getExtension(MemberProperties.ID) != null;
}
/** initializes fields */
private void reset(SpanCalc spanCalc) {
// initialize instance variables
this.emptyPropertyMap.clear();
this.allPropertiesMap = new AllPropertiesMap();
this.metaSet = new ScopedPropertyMetaSet(extension);
this.spanCalc = spanCalc;
this.HCOUNT = spanCalc.getHierarchyCount();
this.PCOUNT = spanCalc.getPositionCount();
collectProperties();
initializePropertyColumns();
}
/**
* collects all properties and their metadata from result
*/
void collectProperties() {
Span[][] spans = spanCalc.getSpans();
for (int hi = 0; hi < HCOUNT; hi++) {
for (int pi = 0; pi < PCOUNT; pi++) {
Span s = spans[pi][hi];
if (s.isMember()) {
Member m = s.getMember();
metaSet.addMember(m);
allPropertiesMap.add(m);
}
}
}
}
/**
* initializes the propertyColumns field.
* Computes the visible MemberPropertyMetas for
* every column.
*/
void initializePropertyColumns() {
propertyColumns = new List[HCOUNT];
for (int i = 0; i < HCOUNT; i++)
propertyColumns[i] = Collections.EMPTY_LIST;
// no positions -> no properties
if (PCOUNT == 0)
return;
// for every column compute the set of
// valid scopes, e.g. levels
Set[] scopes = new Set[HCOUNT];
Span[][] spans = spanCalc.getSpans();
for (int hi = 0; hi < HCOUNT; hi++) {
Set set = new HashSet();
for (int pi = 0; pi < PCOUNT; pi++)
set.add(getScope(spans[pi][hi]));
scopes[hi] = set;
}
// for every column compute the visible MemberPropertyMetas
Set done = new HashSet();
for (int hi = 0; hi < HCOUNT; hi++) {
// from all MemberPropertyMetas keep only those that match the scopes
// of this column. Also remove all metas that denote inline properties.
// Finally intersect with the list of all visible properties
MemberPropertyMetaFilter scopesFilter = metaSet.createScopesFilter(scopes[hi]);
MemberPropertyMetaFilter inlineFilter = metaSet.createIgnoreInlineFilter();
if (hi == (HCOUNT - 1) || !scopes[hi].equals(scopes[hi + 1])) {
ScopedPropertyMetaSet sub = metaSet.metaSet(scopesFilter);
sub.removeAll(done);
if (visiblePropertyMetas == null)
propertyColumns[hi] = sub.metaList(inlineFilter);
else
propertyColumns[hi] = sub.intersectList(visiblePropertyMetas);
done.addAll(propertyColumns[hi]);
}
}
}
Object getScope(Span s) {
// if its not a member, the span itself is the scope
if (!s.isMember())
return s;
return extension.getPropertyScope((Member) s.getMember().getRootDecoree());
}
/**
* adds property columns to sc
* @param sc the SpanCalc to modify
*/
public void addPropertySpans(SpanCalc sc) {
if (extension == null || !showProperties)
return;
logger.info("adding properties");
// initialize the PropertyConfig model
reset(sc);
// compute result size
int newHierCount = spanCalc.getHierarchyCount();
for (int hi = 0; hi < HCOUNT; hi++)
newHierCount += propertyColumns[hi].size();
// create matrix
Span[][] dst = new Span[PCOUNT][];
for (int pi = 0; pi < PCOUNT; pi++)
dst[pi] = new Span[newHierCount];
Span[][] src = spanCalc.getSpans();
// fill matrix
PropertyLookup lookup = new PropertyLookup();
for (int pi = 0; pi < PCOUNT; pi++) {
int dstHierIndex = 0;
lookup.clear();
for (int hi = 0; hi < HCOUNT; hi++) {
Span span = src[pi][hi];
dst[pi][dstHierIndex++] = span;
if (span.isMember())
lookup.addAll(allPropertiesMap.getProperties(span.getMember()));
// copy the properties
Object scope = getScope(span);
for (Iterator it = propertyColumns[hi].iterator(); it.hasNext();) {
MemberPropertyMeta mpm = (MemberPropertyMeta) it.next();
Property prop = null;
if (mpm.getScope().equals(scope))
prop = lookup.getProperty(mpm.getName());
if (prop == null)
prop = emptyProperty(mpm.getName());
dst[pi][dstHierIndex++] = new Span(span.getAxis(), span.getPosition(), prop);
}
}
}
spanCalc.setSpans(dst);
}
/**
* returns an empty Property instance for a given name.
* If queried multiple times for the same name, the same
* object instance is returned (necessary for
* span computation when a single property spans multiple cells of the table axis).
*/
Property emptyProperty(String name) {
Property p = (Property) emptyPropertyMap.get(name);
if (p == null) {
p = new PropertyImpl(name, "");
emptyPropertyMap.put(name, p);
}
return p;
}
/* ----------------------- PropertyConfig methods ------------------------------- */
public boolean isShowProperties() {
return showProperties;
}
public void setShowProperties(boolean b) {
Object oldValue = new Boolean(showProperties);
this.showProperties = b;
setVisiblePropertiesExtension();
Object newValue = new Boolean(showProperties);
propertyChangeSupport.firePropertyChange("showProperties", oldValue, newValue);
}
public void setVisiblePropertyMetas(List metas) {
Object oldValue = visiblePropertyMetas;
this.visiblePropertyMetas = metas;
setVisiblePropertiesExtension();
Object newValue = visiblePropertyMetas;
propertyChangeSupport.firePropertyChange("visiblePropertyMetas", oldValue, newValue);
}
public List getVisiblePropertyMetas() {
return visiblePropertyMetas;
}
public void addPropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.removePropertyChangeListener(l);
}
public static class BookmarkState {
boolean showProperties = false;
List visibleProperties = null;
public boolean isShowProperties() {
return showProperties;
}
public List getVisibleProperties() {
return visibleProperties;
}
public void setShowProperties(boolean b) {
showProperties = b;
}
public void setVisibleProperties(List list) {
visibleProperties = list;
}
}
public Object getBookmarkState(int levelOfDetail) {
BookmarkState x = new BookmarkState();
x.setShowProperties(isShowProperties());
if (visiblePropertyMetas != null) {
ArrayList metas = new ArrayList();
metas.addAll(visiblePropertyMetas);
x.setVisibleProperties(metas);
}
return x;
}
public void setBookmarkState(Object state) {
if (!(state instanceof BookmarkState))
return;
BookmarkState x = (BookmarkState) state;
setVisiblePropertyMetas(x.getVisibleProperties());
setShowProperties(x.isShowProperties());
}
/**
* updates the visibleProperties in the extension
*/
protected void setVisiblePropertiesExtension() {
if (extension == null)
return;
if (!showProperties || visiblePropertyMetas == null) {
extension.setVisibleProperties(new MemberPropertyMeta[0]);
return;
}
MemberPropertyMeta[] mps = new MemberPropertyMeta[visiblePropertyMetas.size()];
mps = (MemberPropertyMeta[]) visiblePropertyMetas.toArray(mps);
extension.setVisibleProperties(mps);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -