KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > olap > fun > ParallelPeriodFunDef


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/olap/fun/ParallelPeriodFunDef.java#1 $
3 // This software is subject to the terms of the Common Public License
4 // Agreement, available at the following URL:
5 // http://www.opensource.org/licenses/cpl.html.
6 // Copyright (C) 2006-2006 Julian Hyde
7 // All Rights Reserved.
8 // You must accept the terms of that agreement to use this software.
9 */

10 package mondrian.olap.fun;
11
12 import mondrian.olap.*;
13 import mondrian.olap.type.Type;
14 import mondrian.olap.type.MemberType;
15 import mondrian.calc.*;
16 import mondrian.calc.impl.DimensionCurrentMemberCalc;
17 import mondrian.calc.impl.ConstantCalc;
18 import mondrian.calc.impl.AbstractMemberCalc;
19 import mondrian.mdx.ResolvedFunCall;
20 import mondrian.resource.MondrianResource;
21
22 /**
23  * Definition of the <code>ParallelPeriod</code> MDX function.
24  *
25  * @author jhyde
26  * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/ParallelPeriodFunDef.java#1 $
27  * @since Mar 23, 2006
28  */

29 class ParallelPeriodFunDef extends FunDefBase {
30     static final ReflectiveMultiResolver Resolver = new ReflectiveMultiResolver(
31             "ParallelPeriod",
32             "ParallelPeriod([<Level>[, <Numeric Expression>[, <Member>]]])",
33             "Returns a member from a prior period in the same relative position as a specified member.",
34             new String JavaDoc[] {"fm", "fml", "fmln", "fmlnm"},
35             ParallelPeriodFunDef.class);
36
37     public ParallelPeriodFunDef(FunDef dummyFunDef) {
38         super(dummyFunDef);
39     }
40
41     public Type getResultType(Validator validator, Exp[] args) {
42         if (args.length == 0) {
43             // With no args, the default implementation cannot
44
// guess the hierarchy, so we supply the Time
45
// dimension.
46
Hierarchy hierarchy = validator.getQuery()
47                     .getCube().getTimeDimension()
48                     .getHierarchy();
49             return MemberType.forHierarchy(hierarchy);
50         }
51         return super.getResultType(validator, args);
52     }
53
54     public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
55         // Member defaults to [Time].currentmember
56
Exp[] args = call.getArgs();
57         final MemberCalc memberCalc;
58         switch (args.length) {
59         case 3:
60             memberCalc = compiler.compileMember(args[2]);
61             break;
62         case 1:
63             final Dimension dimension =
64                     args[0].getType().getHierarchy().getDimension();
65             memberCalc = new DimensionCurrentMemberCalc(dimension);
66             break;
67         default:
68             final Dimension timeDimension =
69                     compiler.getEvaluator().getCube()
70                     .getTimeDimension();
71             memberCalc = new DimensionCurrentMemberCalc(
72                     timeDimension);
73             break;
74         }
75
76         // Numeric Expression defaults to 1.
77
final IntegerCalc lagValueCalc = (args.length >= 2) ?
78                 compiler.compileInteger(args[1]) :
79                 ConstantCalc.constantInteger(1);
80
81         // If level is not specified, we compute it from
82
// member at runtime.
83
final LevelCalc ancestorLevelCalc =
84                 args.length >= 1 ?
85                 compiler.compileLevel(args[0]) :
86                 null;
87
88         return new AbstractMemberCalc(call, new Calc[] {memberCalc, lagValueCalc, ancestorLevelCalc}) {
89             public Member evaluateMember(Evaluator evaluator) {
90                 Member member = memberCalc.evaluateMember(
91                         evaluator);
92                 int lagValue = lagValueCalc.evaluateInteger(
93                         evaluator);
94                 Level ancestorLevel;
95                 if (ancestorLevelCalc != null) {
96                     ancestorLevel = ancestorLevelCalc
97                             .evaluateLevel(evaluator);
98                 } else {
99                     Member parent = member.getParentMember();
100                     if (parent == null) {
101                         // This is a root member,
102
// so there is no parallelperiod.
103
return member.getHierarchy()
104                                 .getNullMember();
105                     }
106                     ancestorLevel = parent.getLevel();
107                 }
108                 return parallelPeriod(member, ancestorLevel,
109                         evaluator, lagValue);
110             }
111         };
112     }
113
114     Member parallelPeriod(
115             Member member,
116             Level ancestorLevel,
117             Evaluator evaluator,
118             int lagValue) {
119         // Now do some error checking.
120
// The ancestorLevel and the member must be from the
121
// same hierarchy.
122
if (member.getHierarchy() != ancestorLevel.getHierarchy()) {
123             MondrianResource.instance().FunctionMbrAndLevelHierarchyMismatch.ex(
124                     "ParallelPeriod", ancestorLevel.getHierarchy().getUniqueName(),
125                     member.getHierarchy().getUniqueName()
126             );
127         }
128
129         int distance = member.getLevel().getDepth() -
130                 ancestorLevel.getDepth();
131         Member ancestor = FunUtil.ancestor(
132                 evaluator, member, distance, ancestorLevel);
133         Member inLaw = evaluator.getSchemaReader()
134                 .getLeadMember(ancestor, -lagValue);
135         return FunUtil.cousin(
136                 evaluator.getSchemaReader(), member, inLaw);
137     }
138 }
139
140 // End ParallelPeriodFunDef.java
141
Popular Tags