/*
// This software is subject to the terms of the Eclipse Public License v1.0
// Agreement, available at the following URL:
// http://www.eclipse.org/legal/epl-v10.html.
// Copyright (C) 2007-2010 Julian Hyde
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
*/
package org.olap4j.driver.olap4ld;
import org.olap4j.driver.olap4ld.Olap4ldConnection;
import org.olap4j.driver.olap4ld.Olap4ldMemberBase;
import org.olap4j.driver.olap4ld.Olap4ldPositionMember;
import org.olap4j.impl.ArrayMap;
import org.olap4j.metadata.*;
import org.olap4j.mdx.ParseTreeNode;
import org.olap4j.OlapException;
import java.util.*;
/**
* Implementation of {@link org.olap4j.metadata.Member}
* for positions on an axis in a cell set
* from an XML/A provider.
*
* <p>This class is necessary because a member can have different properties
* when it is retrieved as part of a cell set than if it is retrieved by
* querying schema metadata (e.g. using
* {@link Cube#lookupMember(java.util.List)}.
* XmlaOlap4jPositionMember wraps the schema member (which might potentially
* be cached between queries - even though today it is not) and adds extra
* properties. All other methods are delegated to the underlying member.</p>
*
* @author jhyde
* @version $Id: XmlaOlap4jPositionMember.java 374 2010-12-03 02:29:37Z jhyde $
* @since Dec 7, 2007
*/
class Olap4ldPositionMember
implements Olap4ldMemberBase
{
private final Olap4ldMemberBase member;
private final Map<Property, Object> propertyValues;
/**
* Creates a XmlaOlap4jPositionMember.
*
* @param member Underlying member
* @param propertyValues Property values
*/
Olap4ldPositionMember(
Olap4ldMemberBase member,
Map<Property, Object> propertyValues)
{
assert member != null;
assert propertyValues != null;
this.member = member;
this.propertyValues = new ArrayMap<Property, Object>(propertyValues);
}
public boolean equals(Object obj) {
if (obj instanceof Olap4ldPositionMember) {
Olap4ldPositionMember that =
(Olap4ldPositionMember) obj;
return this.member.equals(that.member);
} else if (obj instanceof Olap4ldMember) {
Olap4ldMember that = (Olap4ldMember) obj;
return this.member.equals(that);
} else {
return super.equals(obj);
}
}
public int hashCode() {
return member.hashCode();
}
public Olap4ldCube getCube() {
return member.getCube();
}
public Olap4ldConnection getConnection() {
return member.getConnection();
}
public Olap4ldCatalog getCatalog() {
return member.getCatalog();
}
public Map<Property, Object> getPropertyValueMap() {
return new ChainedMap<Property, Object>(
propertyValues,
member.getPropertyValueMap());
}
public NamedList<? extends Member> getChildMembers() throws OlapException {
return member.getChildMembers();
}
public int getChildMemberCount() throws OlapException {
return member.getChildMemberCount();
}
public Member getParentMember() {
return member.getParentMember();
}
public Level getLevel() {
return member.getLevel();
}
public Hierarchy getHierarchy() {
return member.getHierarchy();
}
public Dimension getDimension() {
return member.getDimension();
}
public Type getMemberType() {
return member.getMemberType();
}
public boolean isAll() {
return member.isAll();
}
public boolean isChildOrEqualTo(Member member) {
return this.member.isChildOrEqualTo(member);
}
public boolean isCalculated() {
return member.isCalculated();
}
public int getSolveOrder() {
return member.getSolveOrder();
}
public ParseTreeNode getExpression() {
return member.getExpression();
}
public List<Member> getAncestorMembers() {
return member.getAncestorMembers();
}
public boolean isCalculatedInQuery() {
return member.isCalculatedInQuery();
}
public Object getPropertyValue(Property property) throws OlapException {
if (propertyValues.containsKey(property)) {
return propertyValues.get(property);
}
return member.getPropertyValue(property);
}
public String getPropertyFormattedValue(Property property)
throws OlapException
{
// REVIEW: Formatted value is not available for properties which
// come back as part of axis tuple. Unformatted property is best we
// can do.
if (propertyValues.containsKey(property)) {
return String.valueOf(propertyValues.get(property));
}
return member.getPropertyFormattedValue(property);
}
public void setProperty(
Property property,
Object value)
throws OlapException
{
throw new UnsupportedOperationException();
}
public NamedList<Property> getProperties() {
return member.getProperties();
}
public int getOrdinal() {
return member.getOrdinal();
}
public boolean isHidden() {
return member.isHidden();
}
public int getDepth() {
try {
final Object value =
Olap4ldMember.getPropertyValue(
Property.StandardMemberProperty.DEPTH,
member,
getPropertyValueMap());
return Olap4ldMember.toInteger(value);
} catch (OlapException e) {
// should not happen; only CHILDREN_CARDINALITY can potentially
// give an error
throw new RuntimeException(e);
}
}
public Member getDataMember() {
return member.getDataMember();
}
public String getName() {
return member.getName();
}
public String getUniqueName() {
return member.getUniqueName();
}
public String getCaption() {
return member.getCaption();
}
public String getDescription() {
return member.getDescription();
}
public boolean isVisible() {
return member.isVisible();
}
/**
* Read-only map that contains the union of two maps.
*/
private static class ChainedMap<K, V> implements Map<K, V> {
private final Map<? extends K, ? extends V> map;
private final Map<? extends K, ? extends V> next;
/**
* Creates a ChainedMap.
*
* @param map First map in the chain
* @param next Next map in the chain
*/
ChainedMap(
Map<? extends K, ? extends V> map,
Map<? extends K, ? extends V> next)
{
this.map = map;
this.next = next;
}
public int size() {
int n = next.size();
for (K k : map.keySet()) {
//noinspection SuspiciousMethodCalls
if (!next.containsKey(k)) {
++n;
}
}
return n;
}
public boolean isEmpty() {
return map.isEmpty()
&& next.isEmpty();
}
public boolean containsKey(Object key) {
return map.containsKey(key)
|| next.containsKey(key);
}
public boolean containsValue(Object value) {
return map.containsValue(value)
|| next.containsValue(value);
}
public V get(Object key) {
//noinspection SuspiciousMethodCalls
if (map.containsKey(key)) {
return map.get(key);
} else {
return next.get(key);
}
}
public V put(K key, V value) {
throw new UnsupportedOperationException("read only");
}
public V remove(Object key) {
throw new UnsupportedOperationException("read only");
}
public void putAll(Map<? extends K, ? extends V> t) {
throw new UnsupportedOperationException("read only");
}
public void clear() {
throw new UnsupportedOperationException("read only");
}
public Set<K> keySet() {
throw new UnsupportedOperationException("need to implement");
}
public Collection<V> values() {
throw new UnsupportedOperationException("need to implement");
}
public Set<Entry<K, V>> entrySet() {
throw new UnsupportedOperationException("need to implement");
}
}
}
// End XmlaOlap4jPositionMember.java