1 12 package mondrian.rolap; 13 14 import java.util.ArrayList ; 15 import java.util.Arrays ; 16 import java.util.Collections ; 17 import java.util.HashMap ; 18 import java.util.List ; 19 import java.util.Map ; 20 21 import javax.sql.DataSource ; 22 23 import mondrian.olap.*; 24 import mondrian.olap.type.StringType; 25 import mondrian.rolap.sql.TupleConstraint; 26 import mondrian.rolap.sql.MemberChildrenConstraint; 27 import mondrian.calc.Calc; 28 import mondrian.calc.ExpCompiler; 29 import mondrian.calc.DummyExp; 30 import mondrian.calc.impl.AbstractCalc; 31 import mondrian.calc.impl.GenericCalc; 32 33 import org.apache.log4j.Logger; 34 import org.eigenbase.util.property.Property; 35 36 44 public abstract class RolapSchemaReader implements SchemaReader { 45 private final Role role; 46 private final Map <Hierarchy, MemberReader> hierarchyReaders = new HashMap <Hierarchy, MemberReader>(); 47 private final RolapSchema schema; 48 private final SqlConstraintFactory sqlConstraintFactory = 49 SqlConstraintFactory.instance(); 50 private static final Logger LOGGER = Logger.getLogger(RolapSchemaReader.class); 51 52 RolapSchemaReader(Role role, RolapSchema schema) { 53 assert role != null : "precondition: role != null"; 54 this.role = role; 55 this.schema = schema; 56 } 57 58 public Role getRole() { 59 return role; 60 } 61 62 public Member[] getHierarchyRootMembers(Hierarchy hierarchy) { 63 final Role.HierarchyAccess hierarchyAccess = role.getAccessDetails(hierarchy); 64 Level firstLevel; 65 if (hierarchyAccess == null) { 66 firstLevel = hierarchy.getLevels()[0]; 67 } else { 68 firstLevel = hierarchyAccess.getTopLevel(); 69 if (firstLevel == null) { 70 firstLevel = hierarchy.getLevels()[0]; 71 } 72 } 73 return getLevelMembers(firstLevel, true); 74 } 75 76 synchronized MemberReader getMemberReader(Hierarchy hierarchy) { 77 MemberReader memberReader = hierarchyReaders.get(hierarchy); 78 if (memberReader == null) { 79 memberReader = ((RolapHierarchy) hierarchy).getMemberReader(role); 80 hierarchyReaders.put(hierarchy, memberReader); 81 } 82 return memberReader; 83 } 84 85 public void getMemberRange(Level level, Member startMember, Member endMember, List <Member> list) { 86 getMemberReader(level.getHierarchy()).getMemberRange( 87 (RolapLevel) level, (RolapMember) startMember, 88 (RolapMember) endMember, (List ) list); 89 } 90 91 public int compareMembersHierarchically(Member m1, Member m2) { 92 RolapMember member1 = (RolapMember) m1; 93 RolapMember member2 = (RolapMember) m2; 94 final RolapHierarchy hierarchy = member1.getHierarchy(); 95 Util.assertPrecondition(hierarchy == m2.getHierarchy()); 96 return getMemberReader(hierarchy).compare(member1, member2, true); 97 } 98 99 public Member getMemberParent(Member member) { 100 Member parentMember = member.getParentMember(); 101 while (parentMember != null && parentMember.isHidden()) { 103 parentMember = parentMember.getParentMember(); 104 } 105 if (parentMember != null) { 107 final Role.HierarchyAccess hierarchyAccess = 108 role.getAccessDetails(member.getHierarchy()); 109 if (hierarchyAccess != null && 110 hierarchyAccess.getAccess(parentMember) == Access.NONE) { 111 return null; 112 } 113 } 114 return parentMember; 115 } 116 117 public int getMemberDepth(Member member) { 118 final Role.HierarchyAccess hierarchyAccess = role.getAccessDetails(member.getHierarchy()); 119 if (hierarchyAccess != null) { 120 int memberDepth = member.getLevel().getDepth(); 121 final Level topLevel = hierarchyAccess.getTopLevel(); 122 if (topLevel != null) { 123 memberDepth -= topLevel.getDepth(); 124 } 125 return memberDepth; 126 } else if (((RolapLevel) member.getLevel()).isParentChild()) { 127 int depth = 0; 130 for (Member m = member.getParentMember(); m != null; m = m.getParentMember()) { 131 depth++; 132 } 133 return depth; 134 } else { 135 return member.getLevel().getDepth(); 136 } 137 } 138 139 140 public Member[] getMemberChildren(Member member) { 141 return getMemberChildren(member, null); 142 } 143 144 public Member[] getMemberChildren(Member member, Evaluator context) { 145 MemberChildrenConstraint constraint = 146 sqlConstraintFactory.getMemberChildrenConstraint(context); 147 List <RolapMember> memberList = 148 internalGetMemberChildren(member, constraint); 149 return memberList.toArray(new Member[memberList.size()]); 150 } 151 152 private List <RolapMember> internalGetMemberChildren( 153 Member member, MemberChildrenConstraint constraint) { 154 List <RolapMember> children = new ArrayList <RolapMember>(); 155 final Hierarchy hierarchy = member.getHierarchy(); 156 final MemberReader memberReader = getMemberReader(hierarchy); 157 memberReader.getMemberChildren( 158 (RolapMember) member, children, constraint); 159 return children; 160 } 161 162 167 public int getChildrenCountFromCache(Member member) { 168 final Hierarchy hierarchy = member.getHierarchy(); 169 final MemberReader memberReader = getMemberReader(hierarchy); 170 if( !(memberReader instanceof MemberCache)) { 171 return -1; 172 } 173 List list = ((MemberCache)memberReader).getChildrenFromCache((RolapMember)member, null); 174 if (list == null) { 175 return -1; 176 } 177 return list.size(); 178 } 179 180 185 private int getLevelCardinalityFromCache(Level level) { 186 final Hierarchy hierarchy = level.getHierarchy(); 187 final MemberReader memberReader = getMemberReader(hierarchy); 188 if( !(memberReader instanceof MemberCache)) { 189 return Integer.MIN_VALUE; 190 } 191 List list = ((MemberCache)memberReader).getLevelMembersFromCache((RolapLevel)level, null); 192 if (list == null) { 193 return Integer.MIN_VALUE; 194 } 195 return list.size(); 196 } 197 198 public int getLevelCardinality( 199 Level level, 200 boolean approximate, 201 boolean materialize) 202 { 203 int rowCount = Integer.MIN_VALUE; 204 if (approximate) { 205 rowCount = level.getApproxRowCount(); 207 } 208 209 if (rowCount == Integer.MIN_VALUE) { 210 rowCount = getLevelCardinalityFromCache(level); 212 } 213 214 if (rowCount == Integer.MIN_VALUE) { 215 if (materialize) { 216 rowCount = getLevelMembers(level, false).length; 219 ((RolapLevel) level).setApproxRowCount(rowCount); 221 } 222 } 223 return rowCount; 224 } 225 226 public Member[] getMemberChildren(Member[] members) { 227 return getMemberChildren(members, null); 228 } 229 230 public Member[] getMemberChildren(Member[] members, Evaluator context) { 231 if (members.length == 0) { 232 return RolapUtil.emptyMemberArray; 233 } else { 234 MemberChildrenConstraint constraint = 235 sqlConstraintFactory.getMemberChildrenConstraint(context); 236 final Hierarchy hierarchy = members[0].getHierarchy(); 237 final MemberReader memberReader = getMemberReader(hierarchy); 238 List <RolapMember> children = new ArrayList <RolapMember>(); 239 memberReader.getMemberChildren( 240 (List <RolapMember>) (List ) Arrays.asList(members), 241 children, 242 constraint); 243 return RolapUtil.toArray(children); 244 } 245 } 246 247 public abstract Cube getCube(); 248 249 public OlapElement getElementChild(OlapElement parent, String name) { 250 return getElementChild(parent, name, MatchType.EXACT); 251 } 252 253 public OlapElement getElementChild( 254 OlapElement parent, String name, MatchType matchType) 255 { 256 return parent.lookupChild(this, name, matchType); 257 } 258 259 public Member getMemberByUniqueName( 260 String [] uniqueNameParts, boolean failIfNotFound) { 261 return getMemberByUniqueName( 262 uniqueNameParts, failIfNotFound, MatchType.EXACT); 263 } 264 265 public Member getMemberByUniqueName( 266 String [] uniqueNameParts, boolean failIfNotFound, 267 MatchType matchType) { 268 return null; 271 } 272 273 public OlapElement lookupCompound( 274 OlapElement parent, 275 String [] names, 276 boolean failIfNotFound, 277 int category) 278 { 279 return lookupCompound( 280 parent, names, failIfNotFound, category, MatchType.EXACT); 281 } 282 283 public OlapElement lookupCompound( 284 OlapElement parent, 285 String [] names, 286 boolean failIfNotFound, 287 int category, 288 MatchType matchType) 289 { 290 return Util.lookupCompound( 291 this, parent, names, failIfNotFound, category, matchType); 292 } 293 294 public Member lookupMemberChildByName(Member parent, String childName) 295 { 296 return lookupMemberChildByName(parent, childName, MatchType.EXACT); 297 } 298 299 public Member lookupMemberChildByName( 300 Member parent, String childName, MatchType matchType) 301 { 302 LOGGER.debug("looking for child \"" + childName + "\" of " + parent); 303 try { 304 MemberChildrenConstraint constraint = 305 (matchType == MatchType.EXACT) ? 306 sqlConstraintFactory.getChildByNameConstraint( 307 (RolapMember)parent, childName) : 308 sqlConstraintFactory.getMemberChildrenConstraint(null); 309 List <RolapMember> children = internalGetMemberChildren(parent, constraint); 310 if (children.size() > 0) { 311 return 312 RolapUtil.findBestMemberMatch( 313 children, 314 (RolapMember) parent, 315 children.get(0).getLevel(), 316 childName, 317 matchType, 318 true); 319 } 320 } catch (NumberFormatException e) { 321 LOGGER.debug("NumberFormatException in lookupMemberChildByName for parent = \"" + parent + "\", childName=\"" + childName + "\", exception: " + e.getMessage()); 330 } 331 return null; 332 } 333 334 public Member getCalculatedMember(String [] nameParts) { 335 return null; 337 } 338 339 public NamedSet getNamedSet(String [] nameParts) { 340 if (nameParts.length != 1) { 341 return null; 342 } 343 final String name = nameParts[0]; 344 return schema.getNamedSet(name); 345 } 346 347 public Member getLeadMember(Member member, int n) { 348 final MemberReader memberReader = getMemberReader(member.getHierarchy()); 349 return memberReader.getLeadMember((RolapMember) member, n); 350 } 351 352 public Member[] getLevelMembers(Level level, boolean includeCalculated) { 353 return getLevelMembers(level, null); 354 } 355 356 public Member[] getLevelMembers(Level level, Evaluator context) { 357 TupleConstraint constraint = 358 sqlConstraintFactory.getLevelMembersConstraint( 359 context, 360 new Level [] { level }); 361 final MemberReader memberReader = getMemberReader(level.getHierarchy()); 362 final List <RolapMember> membersInLevel = 363 memberReader.getMembersInLevel( 364 (RolapLevel) level, 0, Integer.MAX_VALUE, constraint); 365 return RolapUtil.toArray(membersInLevel); 366 } 367 368 public Level[] getHierarchyLevels(Hierarchy hierarchy) { 369 assert hierarchy != null; 370 final Role.HierarchyAccess hierarchyAccess = role.getAccessDetails(hierarchy); 371 final Level[] levels = hierarchy.getLevels(); 372 if (hierarchyAccess == null) { 373 return levels; 374 } 375 Level topLevel = hierarchyAccess.getTopLevel(); 376 Level bottomLevel = hierarchyAccess.getBottomLevel(); 377 if ((topLevel == null) && (bottomLevel == null)) { 378 return levels; 379 } 380 if (topLevel == null) { 381 topLevel = levels[0]; 382 } 383 if (bottomLevel == null) { 384 bottomLevel = levels[levels.length - 1]; 385 } 386 final int levelCount = bottomLevel.getDepth() - topLevel.getDepth() + 1; 387 Level[] restrictedLevels = new Level[levelCount]; 388 System.arraycopy(levels, topLevel.getDepth(), restrictedLevels, 0, levelCount); 389 Util.assertPostcondition(restrictedLevels.length >= 1, "return.length >= 1"); 390 return restrictedLevels; 391 } 392 393 public Member getHierarchyDefaultMember(Hierarchy hierarchy) { 394 assert hierarchy != null; 395 Member defaultMember = hierarchy.getDefaultMember(); 396 if (role.getAccess(hierarchy) != Access.NONE) { 399 if (defaultMember == null || (!role.canAccess(defaultMember))) { 402 Member[] rootMembers = this.getHierarchyRootMembers(hierarchy); 403 defaultMember = (rootMembers.length > 0) ? rootMembers[0] : null; 404 } 405 } 406 return defaultMember; 407 } 408 409 public boolean isDrillable(Member member) { 410 final RolapLevel level = (RolapLevel) member.getLevel(); 411 if (level.getParentExp() != null) { 412 return getMemberChildren(member).length > 0; 417 } else { 418 final Level childLevel = level.getChildLevel(); 421 return (childLevel != null) && 422 (role.getAccess(childLevel) != Access.NONE); 423 } 424 } 425 426 public boolean isVisible(Member member) { 427 return !member.isHidden() && role.canAccess(member); 428 } 429 430 public Cube[] getCubes() { 431 List <RolapCube> cubes = schema.getCubeList(); 432 List <Cube> visibleCubes = new ArrayList <Cube>(cubes.size()); 433 434 for (Cube cube : cubes) { 435 if (role.canAccess(cube)) { 436 visibleCubes.add(cube); 437 } 438 } 439 440 return visibleCubes.toArray(new Cube[visibleCubes.size()]); 441 } 442 443 public List <Member> getCalculatedMembers(Hierarchy hierarchy) { 444 return Collections.emptyList(); 445 } 446 447 public List <Member> getCalculatedMembers(Level level) { 448 return Collections.emptyList(); 449 } 450 451 public List <Member> getCalculatedMembers() { 452 return Collections.emptyList(); 453 } 454 455 public NativeEvaluator getNativeSetEvaluator( 456 FunDef fun, Exp[] args, Evaluator evaluator, Calc calc) { 457 RolapEvaluator revaluator = (RolapEvaluator) 458 AbstractCalc.simplifyEvaluator(calc, evaluator); 459 return schema.getNativeRegistry().createEvaluator(revaluator, fun, args); 460 } 461 462 public Parameter getParameter(String name) { 463 for (RolapSchemaParameter parameter : schema.parameterList) { 465 if (Util.equalName(parameter.getName(), name)) { 466 return parameter; 467 } 468 } 469 470 List <Property> propertyList = MondrianProperties.instance().getPropertyList(); 472 for (Property property : propertyList) { 473 if (property.getPath().equals(name)) { 474 return new SystemPropertyParameter(name, false); 475 } 476 } 477 if (System.getProperty(name) != null) { 478 return new SystemPropertyParameter(name, true); 479 } 480 481 return null; 482 } 483 484 public DataSource getDataSource() { 485 return schema.getInternalConnection().getDataSource(); 486 } 487 488 RolapSchema getSchema() { 489 return schema; 490 } 491 492 501 private static class SystemPropertyParameter 502 extends ParameterImpl 503 { 504 508 private final boolean system; 509 512 private final Property propertyDefinition; 513 514 public SystemPropertyParameter(String name, boolean system) { 515 super(name, 516 Literal.nullValue, 517 "System property '" + name + "'", 518 new StringType()); 519 this.system = system; 520 this.propertyDefinition = 521 system ? null : 522 MondrianProperties.instance().getPropertyDefinition(name); 523 } 524 525 public Scope getScope() { 526 return Scope.System; 527 } 528 529 public boolean isModifiable() { 530 return false; 531 } 532 533 public Calc compile(ExpCompiler compiler) { 534 return new GenericCalc(new DummyExp(getType())) { 535 public Calc[] getCalcs() { 536 return new Calc[0]; 537 } 538 539 public Object evaluate(Evaluator evaluator) { 540 if (system) { 541 final String name = SystemPropertyParameter.this.getName(); 542 return System.getProperty(name); 543 } else { 544 return propertyDefinition.stringValue(); 545 } 546 } 547 }; 548 } 549 } 550 } 551 552 | Popular Tags |