001 /* 002 // $Id: //open/mondrian/src/main/mondrian/olap4j/MondrianOlap4jCube.java#1 $ 003 // This software is subject to the terms of the Common Public License 004 // Agreement, available at the following URL: 005 // http://www.opensource.org/licenses/cpl.html. 006 // Copyright (C) 2007-2007 Julian Hyde 007 // All Rights Reserved. 008 // You must accept the terms of that agreement to use this software. 009 */ 010 package mondrian.olap4j; 011 012 import org.olap4j.metadata.*; 013 import org.olap4j.OlapException; 014 import org.olap4j.impl.*; 015 016 import java.util.*; 017 018 /** 019 * Implementation of {@link Cube} 020 * for the Mondrian OLAP engine. 021 * 022 * @author jhyde 023 * @version $Id: //open/mondrian/src/main/mondrian/olap4j/MondrianOlap4jCube.java#1 $ 024 * @since May 24, 2007 025 */ 026 class MondrianOlap4jCube implements Cube, Named { 027 private final mondrian.olap.Cube cube; 028 final MondrianOlap4jSchema olap4jSchema; 029 030 MondrianOlap4jCube( 031 mondrian.olap.Cube cube, 032 MondrianOlap4jSchema olap4jSchema) 033 { 034 this.cube = cube; 035 this.olap4jSchema = olap4jSchema; 036 } 037 038 public Schema getSchema() { 039 return olap4jSchema; 040 } 041 042 public int hashCode() { 043 return olap4jSchema.hashCode() 044 ^ cube.hashCode(); 045 } 046 047 public boolean equals(Object obj) { 048 if (obj instanceof MondrianOlap4jCube) { 049 MondrianOlap4jCube that = (MondrianOlap4jCube) obj; 050 return this.olap4jSchema == that.olap4jSchema 051 && this.cube.equals(that.cube); 052 } 053 return false; 054 } 055 056 public NamedList<Dimension> getDimensions() { 057 NamedList<MondrianOlap4jDimension> list = 058 new NamedListImpl<MondrianOlap4jDimension>(); 059 for (mondrian.olap.Dimension dimension : cube.getDimensions()) { 060 list.add( 061 new MondrianOlap4jDimension( 062 olap4jSchema, dimension)); 063 } 064 return Olap4jUtil.cast(list); 065 } 066 067 public NamedList<Hierarchy> getHierarchies() { 068 NamedList<MondrianOlap4jHierarchy> list = 069 new NamedListImpl<MondrianOlap4jHierarchy>(); 070 for (mondrian.olap.Dimension dimension : cube.getDimensions()) { 071 for (mondrian.olap.Hierarchy hierarchy : dimension.getHierarchies()) { 072 list.add( 073 new MondrianOlap4jHierarchy( 074 olap4jSchema, hierarchy)); 075 } 076 } 077 return Olap4jUtil.cast(list); 078 } 079 080 public List<Measure> getMeasures() { 081 final MondrianOlap4jLevel measuresLevel = 082 (MondrianOlap4jLevel) 083 getDimensions().get("Measures").getDefaultHierarchy() 084 .getLevels().get(0); 085 return Olap4jUtil.cast(measuresLevel.getMembers()); 086 } 087 088 public NamedList<NamedSet> getSets() { 089 final NamedListImpl<MondrianOlap4jNamedSet> list = 090 new NamedListImpl<MondrianOlap4jNamedSet>(); 091 final MondrianOlap4jConnection olap4jConnection = 092 olap4jSchema.olap4jCatalog.olap4jDatabaseMetaData.olap4jConnection; 093 for (mondrian.olap.NamedSet namedSet : cube.getNamedSets()) { 094 list.add(olap4jConnection.toOlap4j(cube, namedSet)); 095 } 096 return Olap4jUtil.cast(list); 097 } 098 099 public Collection<Locale> getSupportedLocales() { 100 throw new UnsupportedOperationException(); 101 } 102 103 public String getName() { 104 return cube.getName(); 105 } 106 107 public String getUniqueName() { 108 return cube.getUniqueName(); 109 } 110 111 public String getCaption(Locale locale) { 112 // todo: i81n 113 return cube.getCaption(); 114 } 115 116 public String getDescription(Locale locale) { 117 // todo: i81n 118 return cube.getDescription(); 119 } 120 121 public MondrianOlap4jMember lookupMember(String... nameParts) { 122 final MondrianOlap4jConnection olap4jConnection = 123 olap4jSchema.olap4jCatalog.olap4jDatabaseMetaData.olap4jConnection; 124 final mondrian.olap.SchemaReader schemaReader = 125 cube.getSchemaReader(olap4jConnection.connection.getRole()); 126 127 final List<mondrian.olap.Id.Segment> segmentList = 128 new ArrayList<mondrian.olap.Id.Segment>(); 129 for (String namePart : nameParts) { 130 segmentList.add( 131 new mondrian.olap.Id.Segment( 132 namePart, mondrian.olap.Id.Quoting.QUOTED)); 133 } 134 final mondrian.olap.Member member = 135 schemaReader.getMemberByUniqueName(segmentList, false); 136 if (member == null) { 137 return null; 138 } 139 return olap4jConnection.toOlap4j(member); 140 } 141 142 public List<Member> lookupMembers( 143 Set<Member.TreeOp> treeOps, 144 String... nameParts) throws OlapException 145 { 146 final MondrianOlap4jMember member = lookupMember(nameParts); 147 if (member == null) { 148 return Collections.emptyList(); 149 } 150 151 // Add ancestors and/or the parent. Ancestors are prepended, to ensure 152 // hierarchical order. 153 final List<MondrianOlap4jMember> list = 154 new ArrayList<MondrianOlap4jMember>(); 155 if (treeOps.contains(Member.TreeOp.ANCESTORS)) { 156 for (MondrianOlap4jMember m = member.getParentMember(); 157 m != null; 158 m = m.getParentMember()) { 159 list.add(0, m); 160 } 161 } else if (treeOps.contains(Member.TreeOp.PARENT)) { 162 final MondrianOlap4jMember parentMember = member.getParentMember(); 163 if (parentMember != null) { 164 list.add(parentMember); 165 } 166 } 167 168 // Add siblings. Siblings which occur after the member are deferred, 169 // because they occur after children and descendants in the 170 // hierarchical ordering. 171 List<MondrianOlap4jMember> remainingSiblingsList = null; 172 if (treeOps.contains(Member.TreeOp.SIBLINGS)) { 173 final MondrianOlap4jMember parentMember = member.getParentMember(); 174 NamedList<MondrianOlap4jMember> siblingMembers; 175 if (parentMember != null) { 176 siblingMembers = parentMember.getChildMembers(); 177 } else { 178 siblingMembers = 179 Olap4jUtil.cast(member.getHierarchy().getRootMembers()); 180 } 181 List<MondrianOlap4jMember> targetList = list; 182 for (MondrianOlap4jMember siblingMember : siblingMembers) { 183 if (siblingMember.equals(member)) { 184 targetList = 185 remainingSiblingsList = 186 new ArrayList<MondrianOlap4jMember>(); 187 } else { 188 targetList.add(siblingMember); 189 } 190 } 191 } 192 193 // Add the member itself. 194 if (treeOps.contains(Member.TreeOp.SELF)) { 195 list.add(member); 196 } 197 198 // Add descendants and/or children. 199 if (treeOps.contains(Member.TreeOp.DESCENDANTS)) { 200 for (MondrianOlap4jMember childMember : member.getChildMembers()) { 201 list.add(childMember); 202 addDescendants(list, childMember); 203 } 204 } else if (treeOps.contains(Member.TreeOp.CHILDREN)) { 205 for (MondrianOlap4jMember childMember : member.getChildMembers()) { 206 list.add(childMember); 207 } 208 } 209 // Lastly, add siblings which occur after the member itself. They 210 // occur after all of the descendants in the hierarchical ordering. 211 if (remainingSiblingsList != null) { 212 list.addAll(remainingSiblingsList); 213 } 214 return Olap4jUtil.cast(list); 215 } 216 217 private static void addDescendants( 218 List<MondrianOlap4jMember> list, 219 MondrianOlap4jMember member) 220 { 221 for (MondrianOlap4jMember childMember : member.getChildMembers()) { 222 list.add(childMember); 223 addDescendants(list, childMember); 224 } 225 } 226 } 227 228 // End MondrianOlap4jCube.java