1 13 package mondrian.olap.fun; 14 15 import mondrian.calc.*; 16 import mondrian.calc.impl.AbstractListCalc; 17 import mondrian.calc.impl.AbstractIterCalc; 18 import mondrian.calc.impl.AbstractVoidCalc; 19 import mondrian.calc.ExpCompiler.ResultStyle; 20 import mondrian.olap.*; 21 import mondrian.olap.type.*; 22 import mondrian.resource.MondrianResource; 23 import mondrian.mdx.ResolvedFunCall; 24 25 import java.io.PrintWriter ; 26 import java.util.ArrayList ; 27 import java.util.Iterator ; 28 import java.util.List ; 29 30 38 public class SetFunDef extends FunDefBase { 39 static final ResolverImpl Resolver = new ResolverImpl(); 40 41 SetFunDef(Resolver resolver, int[] argTypes) { 42 super(resolver, Category.Set, argTypes); 43 } 44 45 public void unparse(Exp[] args, PrintWriter pw) { 46 ExpBase.unparseList(pw, args, "{", ", ", "}"); 47 } 48 49 public Type getResultType(Validator validator, Exp[] args) { 50 Type type0 = null; 54 if (args.length == 0) { 55 type0 = MemberType.Unknown; 57 } else { 58 for (int i = 0; i < args.length; i++) { 59 Exp arg = args[i]; 60 Type type = arg.getType(); 61 type = TypeUtil.toMemberOrTupleType(type); 62 if (i == 0) { 63 type0 = type; 64 } else { 65 if (!TypeUtil.isUnionCompatible(type0, type)) { 66 throw MondrianResource.instance().ArgsMustHaveSameHierarchy.ex(getName()); 67 } 68 } 69 } 70 } 71 return new SetType(type0); 72 } 73 74 public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) { 75 final Exp[] args = call.getArgs(); 76 return new ListSetCalc(call, args, compiler, 77 ExpCompiler.LIST_MUTABLE_LIST_RESULT_STYLE_ARRAY); 78 } 79 80 92 public static class ListSetCalc extends AbstractListCalc { 93 private List result = new ArrayList (); 94 private final VoidCalc[] voidCalcs; 95 96 public ListSetCalc(Exp exp, Exp[] args, ExpCompiler compiler, 97 ResultStyle[] resultStyles) { 98 super(exp, null); 99 voidCalcs = compileSelf(args, compiler, resultStyles); 100 } 101 102 public Calc[] getCalcs() { 103 return voidCalcs; 104 } 105 106 private VoidCalc[] compileSelf(Exp[] args, 107 ExpCompiler compiler, 108 ResultStyle[] resultStyles) { 109 VoidCalc[] voidCalcs = new VoidCalc[args.length]; 110 for (int i = 0; i < args.length; i++) { 111 voidCalcs[i] = createCalc(args[i], compiler, resultStyles); 112 } 113 return voidCalcs; 114 } 115 116 private VoidCalc createCalc(Exp arg, 117 ExpCompiler compiler, 118 ResultStyle[] resultStyles) { 119 final Type type = arg.getType(); 120 if (type instanceof SetType) { 121 final ListCalc listCalc = compiler.compileList(arg); 123 final Type elementType = ((SetType) type).getElementType(); 124 if (elementType instanceof MemberType) { 125 return new AbstractVoidCalc(arg, new Calc[] {listCalc}) { 126 public void evaluateVoid(Evaluator evaluator) { 127 List list = listCalc.evaluateList(evaluator); 128 for (int i = 0; i < list.size(); i++) { 130 Member member = (Member) list.get(i); 131 if (member == null || member.isNull()) { 132 continue; 133 } 134 result.add(member); 135 } 136 } 137 138 protected String getName() { 139 return "Sublist"; 140 } 141 }; 142 } else { 143 return new AbstractVoidCalc(arg, new Calc[] {listCalc}) { 144 public void evaluateVoid(Evaluator evaluator) { 145 List list = listCalc.evaluateList(evaluator); 146 list: 149 for (int i = 0; i < list.size(); i++) { 150 Member[] members = (Member[]) list.get(i); 151 for (int j = 0; j < members.length; j++) { 152 Member member = members[j]; 153 if (member == null || member.isNull()) { 154 continue list; 155 } 156 } 157 result.add(members); 158 } 159 } 160 161 protected String getName() { 162 return "Sublist"; 163 } 164 }; 165 } 166 } else if (TypeUtil.couldBeMember(type)) { 167 final MemberCalc listCalc = compiler.compileMember(arg); 168 return new AbstractVoidCalc(arg, new Calc[] {listCalc}) { 169 public void evaluateVoid(Evaluator evaluator) { 170 Member member = listCalc.evaluateMember(evaluator); 171 if (member == null || member.isNull()) { 172 return; 173 } 174 result.add(member); 175 } 176 177 protected String getName() { 178 return "Sublist"; 179 } 180 }; 181 } else { 182 final TupleCalc tupleCalc = compiler.compileTuple(arg); 183 return new AbstractVoidCalc(arg, new Calc[] {tupleCalc}) { 184 public void evaluateVoid(Evaluator evaluator) { 185 Member[] members = tupleCalc.evaluateTuple(evaluator); 187 if (members == null) { 188 return; 189 } 190 assert !tupleContainsNullMember(members); 191 192 result.add(members); 193 } 194 }; 195 } 196 } 197 198 public List evaluateList(Evaluator evaluator) { 199 result.clear(); 200 for (int i = 0; i < voidCalcs.length; i++) { 201 voidCalcs[i].evaluateVoid(evaluator); 202 } 203 return new ArrayList (result); 204 } 205 } 206 public static class IterSetCalc extends AbstractIterCalc { 207 private final IterCalc[] iterCalcs; 208 209 public IterSetCalc(Exp exp, Exp[] args, ExpCompiler compiler, 210 ResultStyle[] resultStyles) { 211 super(exp, null); 212 iterCalcs = compileSelf(args, compiler, resultStyles); 213 } 214 215 public Calc[] getCalcs() { 216 return iterCalcs; 217 } 218 219 private IterCalc[] compileSelf(Exp[] args, 220 ExpCompiler compiler, 221 ResultStyle[] resultStyles) { 222 IterCalc[] iterCalcs = new IterCalc[args.length]; 223 for (int i = 0; i < args.length; i++) { 224 iterCalcs[i] = createCalc(args[i], compiler, resultStyles); 225 } 226 return iterCalcs; 227 } 228 229 private IterCalc createCalc(Exp arg, 230 ExpCompiler compiler, 231 ResultStyle[] resultStyles) { 232 233 final Type type = arg.getType(); 234 if (type instanceof SetType) { 235 final Calc calc = compiler.compile(arg, resultStyles); 236 final Type elementType = ((SetType) type).getElementType(); 237 if (elementType instanceof MemberType) { 238 switch (calc.getResultStyle()) { 239 case ITERABLE : 240 return new AbstractIterCalc(arg, new Calc[] {calc}) { 241 private final IterCalc iterCalc = (IterCalc) calc; 242 public Iterable evaluateIterable(Evaluator evaluator) { 243 Iterable iterable = 244 iterCalc.evaluateIterable(evaluator); 245 return iterable; 246 } 247 protected String getName() { 248 return "Sublist"; 249 } 250 }; 251 case LIST : 252 case MUTABLE_LIST : 253 return new AbstractIterCalc(arg, new Calc[] {calc}) { 254 private final ListCalc listCalc = (ListCalc) calc; 255 public Iterable evaluateIterable(Evaluator evaluator) { 256 List result = new ArrayList (); 257 List list = listCalc.evaluateList(evaluator); 258 for (int i = 0; i < list.size(); i++) { 260 Member member = (Member) list.get(i); 261 if (member == null || member.isNull()) { 262 continue; 263 } 264 result.add(member); 265 } 266 return result; 267 } 268 protected String getName() { 269 return "Sublist"; 270 } 271 }; 272 } 273 throw ResultStyleException.generateBadType( 274 new ResultStyle[] { 275 ResultStyle.ITERABLE, 276 ResultStyle.LIST, 277 ResultStyle.MUTABLE_LIST 278 }, calc.getResultStyle()); 279 } else { 280 switch (calc.getResultStyle()) { 281 case ITERABLE : 282 return new AbstractIterCalc(arg, new Calc[] {calc}) { 283 private final IterCalc iterCalc = (IterCalc) calc; 284 public Iterable evaluateIterable(Evaluator evaluator) { 285 Iterable iterable = 286 iterCalc.evaluateIterable(evaluator); 287 return iterable; 288 } 289 protected String getName() { 290 return "Sublist"; 291 } 292 }; 293 case LIST : 294 case MUTABLE_LIST : 295 return new AbstractIterCalc(arg, new Calc[] {calc}) { 296 private final ListCalc listCalc = (ListCalc) calc; 297 public Iterable evaluateIterable(Evaluator evaluator) { 298 List result = new ArrayList (); 299 List list = listCalc.evaluateList(evaluator); 300 list: 303 for (int i = 0; i < list.size(); i++) { 304 Member[] members = (Member[]) list.get(i); 305 for (int j = 0; j < members.length; j++) { 306 Member member = members[j]; 307 if (member == null || member.isNull()) { 308 continue list; 309 } 310 } 311 result.add(members); 312 } 313 return result; 314 } 315 316 protected String getName() { 317 return "Sublist"; 318 } 319 }; 320 } 321 throw ResultStyleException.generateBadType( 322 new ResultStyle[] { 323 ResultStyle.ITERABLE, 324 ResultStyle.LIST, 325 ResultStyle.MUTABLE_LIST 326 }, 327 calc.getResultStyle()); 328 329 } 330 } else if (TypeUtil.couldBeMember(type)) { 331 final MemberCalc memberCalc = compiler.compileMember(arg); 332 return new AbstractIterCalc(arg, new Calc[] {memberCalc}) { 333 public Iterable evaluateIterable(Evaluator evaluator) { 334 final Member member = 335 memberCalc.evaluateMember(evaluator); 336 Iterable <Member> iterable = new Iterable <Member>() { 337 public Iterator <Member> iterator() { 338 return new Iterator <Member>() { 339 private Member m = member; 340 public boolean hasNext() { 341 return (m != null); 342 } 343 public Member next() { 344 try { 345 return m; 346 } finally { 347 m = null; 348 } 349 } 350 public void remove() { 351 throw new UnsupportedOperationException ("remove"); 352 } 353 }; 354 } 355 }; 356 return iterable; 357 } 358 protected String getName() { 359 return "Sublist"; 360 } 361 }; 362 } else { 363 final TupleCalc tupleCalc = compiler.compileTuple(arg); 364 365 return new AbstractIterCalc(arg, new Calc[] {tupleCalc}) { 366 public Iterable evaluateIterable(Evaluator evaluator) { 367 final Member[] members = tupleCalc.evaluateTuple(evaluator); 368 Iterable <Member[]> iterable = new Iterable <Member[]>() { 369 public Iterator <Member[]> iterator() { 370 return new Iterator <Member[]>() { 371 private Member[] m = members; 372 public boolean hasNext() { 373 return (m != null); 374 } 375 public Member[] next() { 376 try { 377 return m; 378 } finally { 379 m = null; 380 } 381 } 382 public void remove() { 383 throw new UnsupportedOperationException ("remove"); 384 } 385 }; 386 } 387 }; 388 return iterable; 389 } 390 protected String getName() { 391 return "Sublist"; 392 } 393 }; 394 } 395 } 396 397 public Iterable evaluateIterable(final Evaluator evaluator) { 398 Iterable result = new Iterable <Member>() { 399 public Iterator <Member> iterator() { 400 return new Iterator <Member>() { 401 int index = 0; 402 Iterator <Member> currentIterator = null; 403 Member member = null; 404 public boolean hasNext() { 405 if (member != null) { 406 return true; 407 } 408 if (currentIterator == null) { 409 if (index >= iterCalcs.length) { 410 return false; 411 } 412 IterCalc iterCalc = iterCalcs[index++]; 413 Iterable iter = 414 iterCalc.evaluateIterable(evaluator); 415 currentIterator = iter.iterator(); 416 } 417 while(true) { 418 boolean b = currentIterator.hasNext(); 419 while (! b) { 420 if (index >= iterCalcs.length) { 421 return false; 422 } 423 IterCalc iterCalc = iterCalcs[index++]; 424 Iterable iter = 425 iterCalc.evaluateIterable(evaluator); 426 currentIterator = iter.iterator(); 427 b = currentIterator.hasNext(); 428 } 429 member = currentIterator.next(); 430 if (member != null) { 431 break; 432 } 433 } 434 return true; 435 } 436 public Member next() { 437 try { 438 return member; 439 } finally { 440 member = null; 441 } 442 } 443 public void remove() { 444 throw new UnsupportedOperationException ("remove"); 445 } 446 }; 447 } 448 }; 449 return result; 450 } 451 } 452 453 private static class ResolverImpl extends ResolverBase { 454 public ResolverImpl() { 455 super( 456 "{}", 457 "{<Member> [, <Member>...]}", 458 "Brace operator constructs a set.", 459 Syntax.Braces); 460 } 461 462 public FunDef resolve( 463 Exp[] args, Validator validator, int[] conversionCount) { 464 int[] parameterTypes = new int[args.length]; 465 for (int i = 0; i < args.length; i++) { 466 if (validator.canConvert( 467 args[i], Category.Member, conversionCount)) { 468 parameterTypes[i] = Category.Member; 469 continue; 470 } 471 if (validator.canConvert( 472 args[i], Category.Set, conversionCount)) { 473 parameterTypes[i] = Category.Set; 474 continue; 475 } 476 if (validator.canConvert( 477 args[i], Category.Tuple, conversionCount)) { 478 parameterTypes[i] = Category.Tuple; 479 continue; 480 } 481 return null; 482 } 483 return new SetFunDef(this, parameterTypes); 484 } 485 } 486 } 487 488 | Popular Tags |