1 13 package mondrian.olap.fun; 14 15 import mondrian.olap.*; 16 import mondrian.olap.type.MemberType; 17 import mondrian.olap.type.Type; 18 import mondrian.resource.MondrianResource; 19 import mondrian.calc.*; 20 import mondrian.calc.impl.AbstractMemberCalc; 21 import mondrian.calc.impl.DimensionCurrentMemberCalc; 22 import mondrian.mdx.ResolvedFunCall; 23 24 32 class OpeningClosingPeriodFunDef extends FunDefBase { 33 private final boolean opening; 34 35 static final Resolver OpeningPeriodResolver = new MultiResolver( 36 "OpeningPeriod", 37 "OpeningPeriod([<Level>[, <Member>]])", 38 "Returns the first descendant of a member at a level.", 39 new String [] {"fm", "fml", "fmlm"}) { 40 protected FunDef createFunDef( 41 Exp[] args, FunDef dummyFunDef) { 42 return new OpeningClosingPeriodFunDef( 43 dummyFunDef, true); 44 } 45 }; 46 47 static final Resolver ClosingPeriodResolver = new MultiResolver( 48 "ClosingPeriod", 49 "ClosingPeriod([<Level>[, <Member>]])", 50 "Returns the last descendant of a member at a level.", 51 new String [] {"fm", "fml", "fmlm", "fmm"}) { 52 protected FunDef createFunDef( 53 Exp[] args, FunDef dummyFunDef) { 54 return new OpeningClosingPeriodFunDef( 55 dummyFunDef, false); 56 } 57 }; 58 59 public OpeningClosingPeriodFunDef( 60 FunDef dummyFunDef, 61 boolean opening) { 62 super(dummyFunDef); 63 this.opening = opening; 64 } 65 66 public Type getResultType(Validator validator, Exp[] args) { 67 if (args.length == 0) { 68 Hierarchy hierarchy = validator.getQuery() 72 .getCube().getTimeDimension() 73 .getHierarchy(); 74 return MemberType.forHierarchy(hierarchy); 75 } 76 return super.getResultType(validator, args); 77 } 78 79 public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) { 80 final Exp[] args = call.getArgs(); 81 final LevelCalc levelCalc; 82 final MemberCalc memberCalc; 83 switch (args.length) { 84 case 0: 85 memberCalc = new DimensionCurrentMemberCalc( 86 compiler.getEvaluator().getCube().getTimeDimension()); 87 levelCalc = null; 88 break; 89 case 1: 90 levelCalc = compiler.compileLevel(call.getArg(0)); 91 memberCalc = new DimensionCurrentMemberCalc( 92 compiler.getEvaluator().getCube().getTimeDimension()); 93 break; 94 default: 95 levelCalc = compiler.compileLevel(call.getArg(0)); 96 memberCalc = compiler.compileMember(call.getArg(1)); 97 break; 98 } 99 100 final Dimension memberDimension = memberCalc.getType().getDimension(); 103 final Dimension levelDimension; 104 if (levelCalc == null) { 105 levelDimension = memberDimension; 106 } else { 107 levelDimension = levelCalc.getType().getDimension(); 108 if (!memberDimension.equals(levelDimension)) { 109 throw MondrianResource.instance(). 110 FunctionMbrAndLevelHierarchyMismatch.ex( 111 opening ? "OpeningPeriod" : "ClosingPeriod", 112 levelDimension.getUniqueName(), 113 memberDimension.getUniqueName()); 114 } 115 } 116 return new AbstractMemberCalc(call, new Calc[] {levelCalc, memberCalc}) { 117 public Member evaluateMember(Evaluator evaluator) { 118 Member member = memberCalc.evaluateMember(evaluator); 119 120 Level level; 123 if (levelCalc == null) { 124 int targetDepth = member.getLevel().getDepth() + 1; 125 Level[] levels = member.getHierarchy().getLevels(); 126 127 if (levels.length <= targetDepth) { 128 return member.getHierarchy().getNullMember(); 129 } 130 level = levels[targetDepth]; 131 } else { 132 level = levelCalc.evaluateLevel(evaluator); 133 } 134 135 if (level.getDepth() < member.getLevel().getDepth()) { 137 return member.getHierarchy().getNullMember(); 138 } 139 140 if (level == member.getLevel()) { 142 return member; 143 } 144 145 return getDescendant(evaluator.getSchemaReader(), member, 146 level, opening); 147 } 148 }; 149 } 150 151 162 static Member getDescendant( 163 SchemaReader schemaReader, 164 Member member, 165 Level targetLevel, 166 boolean returnFirstDescendant) { 167 Member[] children; 168 169 final int targetLevelDepth = targetLevel.getDepth(); 170 assertPrecondition(member.getLevel().getDepth() < targetLevelDepth, 171 "member.getLevel().getDepth() < targetLevel.getDepth()"); 172 173 for (;;) { 174 children = schemaReader.getMemberChildren(member); 175 176 if (children.length == 0) { 177 return targetLevel.getHierarchy().getNullMember(); 178 } 179 180 member = children[returnFirstDescendant ? 0 : (children.length - 1)]; 181 182 if (member.getLevel().getDepth() == targetLevelDepth) { 183 if (member.isHidden()) { 184 return member.getHierarchy().getNullMember(); 185 } else { 186 return member; 187 } 188 } 189 } 190 } 191 192 } 193 194 | Popular Tags |