0001: /*
0002: * Copyright 2004-2007 Gary Bentley
0003: *
0004: * Licensed under the Apache License, Version 2.0 (the "License"); you may
0005: * not use this file except in compliance with the License.
0006: * You may obtain a copy of the License at
0007: * http://www.apache.org/licenses/LICENSE-2.0
0008: *
0009: * Unless required by applicable law or agreed to in writing, software
0010: * distributed under the License is distributed on an "AS IS" BASIS,
0011: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012: * See the License for the specific language governing permissions and
0013: * limitations under the License.
0014: */
0015: package org.josql.functions;
0016:
0017: import java.util.List;
0018: import java.util.Map;
0019: import java.util.HashMap;
0020: import java.util.Iterator;
0021:
0022: import com.gentlyweb.utils.Getter;
0023:
0024: import org.josql.QueryExecutionException;
0025:
0026: import org.josql.internal.Utilities;
0027:
0028: import org.josql.expressions.Expression;
0029:
0030: import org.josql.Query;
0031:
0032: public class GroupingFunctions extends AbstractFunctionHandler {
0033:
0034: public static final String VALUE = "value";
0035:
0036: public static final String HANDLER_ID = "_internal_grouping";
0037:
0038: public Object least(List allobjs, Expression exp,
0039: String saveValueName) throws QueryExecutionException {
0040:
0041: if (saveValueName != null) {
0042:
0043: Object o = this .q.getSaveValue(saveValueName);
0044:
0045: if (o != null) {
0046:
0047: return o;
0048:
0049: }
0050:
0051: }
0052:
0053: if (allobjs.size() == 0) {
0054:
0055: return null;
0056:
0057: }
0058:
0059: Object currObj = this .q.getCurrentObject();
0060:
0061: Object g = null;
0062:
0063: int s = allobjs.size();
0064:
0065: for (int i = 0; i < s; i++) {
0066:
0067: Object o = allobjs.get(i);
0068:
0069: this .q.setCurrentObject(o);
0070:
0071: Object v = null;
0072:
0073: try {
0074:
0075: v = exp.getValue(o, this .q);
0076:
0077: } catch (Exception e) {
0078:
0079: this .q.setCurrentObject(currObj);
0080:
0081: throw new QueryExecutionException(
0082: "Unable to get value from expression: " + exp
0083: + " for maximum value" + e);
0084:
0085: }
0086:
0087: if (g == null) {
0088:
0089: g = v;
0090:
0091: } else {
0092:
0093: int c = Utilities.compare(v, g);
0094:
0095: if (c < 0) {
0096:
0097: g = v;
0098:
0099: }
0100:
0101: }
0102:
0103: }
0104:
0105: if ((saveValueName != null) && (q != null)) {
0106:
0107: q.setSaveValue(saveValueName, g);
0108:
0109: }
0110:
0111: this .q.setCurrentObject(currObj);
0112:
0113: return g;
0114:
0115: }
0116:
0117: public Object minObject(Expression exp)
0118: throws QueryExecutionException {
0119:
0120: return this .minObject((List) this .q
0121: .getVariable(Query.ALL_OBJS_VAR_NAME), exp);
0122:
0123: }
0124:
0125: public Object minObject(List allobjs, Expression exp)
0126: throws QueryExecutionException {
0127:
0128: return this .leastObject(allobjs, exp);
0129:
0130: }
0131:
0132: public Object leastObject(List allobjs, Expression exp)
0133: throws QueryExecutionException {
0134:
0135: if (allobjs.size() == 0) {
0136:
0137: return null;
0138:
0139: }
0140:
0141: Object currObj = this .q.getCurrentObject();
0142:
0143: Object l = null;
0144: Object lo = null;
0145:
0146: int s = allobjs.size();
0147:
0148: for (int i = 0; i < s; i++) {
0149:
0150: Object o = allobjs.get(i);
0151:
0152: this .q.setCurrentObject(o);
0153:
0154: Object v = null;
0155:
0156: try {
0157:
0158: v = exp.getValue(o, this .q);
0159:
0160: } catch (Exception e) {
0161:
0162: this .q.setCurrentObject(currObj);
0163:
0164: throw new QueryExecutionException(
0165: "Unable to get value from expression: " + exp
0166: + " for maximum value" + e);
0167:
0168: }
0169:
0170: if (l == null) {
0171:
0172: l = v;
0173: lo = o;
0174:
0175: } else {
0176:
0177: int c = Utilities.compare(v, l);
0178:
0179: if (c < 0) {
0180:
0181: l = v;
0182: lo = o;
0183:
0184: }
0185:
0186: }
0187:
0188: }
0189:
0190: this .q.setCurrentObject(currObj);
0191:
0192: return lo;
0193:
0194: }
0195:
0196: public Object maxObject(List allobjs, Expression exp)
0197: throws QueryExecutionException {
0198:
0199: return this .greatestObject(allobjs, exp);
0200:
0201: }
0202:
0203: public Object maxObject(Expression exp)
0204: throws QueryExecutionException {
0205:
0206: return this .maxObject((List) this .q
0207: .getVariable(Query.ALL_OBJS_VAR_NAME), exp);
0208:
0209: }
0210:
0211: public Object greatestObject(List allobjs, Expression exp)
0212: throws QueryExecutionException {
0213:
0214: if (allobjs.size() == 0) {
0215:
0216: return null;
0217:
0218: }
0219:
0220: Object currObj = this .q.getCurrentObject();
0221:
0222: Object g = null;
0223: Object go = null;
0224:
0225: int s = allobjs.size();
0226:
0227: for (int i = 0; i < s; i++) {
0228:
0229: Object o = allobjs.get(i);
0230:
0231: this .q.setCurrentObject(o);
0232:
0233: Object v = null;
0234:
0235: try {
0236:
0237: v = exp.getValue(o, this .q);
0238:
0239: } catch (Exception e) {
0240:
0241: this .q.setCurrentObject(currObj);
0242:
0243: throw new QueryExecutionException(
0244: "Unable to get value from expression: " + exp
0245: + " for maximum value" + e);
0246:
0247: }
0248:
0249: if (g == null) {
0250:
0251: g = v;
0252: go = o;
0253:
0254: } else {
0255:
0256: int c = Utilities.compare(v, g);
0257:
0258: if (c > 0) {
0259:
0260: g = v;
0261: go = o;
0262:
0263: }
0264:
0265: }
0266:
0267: }
0268:
0269: this .q.setCurrentObject(currObj);
0270:
0271: return go;
0272:
0273: }
0274:
0275: public Object least(List allobjs, Expression exp)
0276: throws QueryExecutionException {
0277:
0278: return this .least(allobjs, exp, null);
0279:
0280: }
0281:
0282: public Object min(Expression exp) throws QueryExecutionException {
0283:
0284: return this .min((List) this .q
0285: .getVariable(Query.ALL_OBJS_VAR_NAME), exp);
0286:
0287: }
0288:
0289: public Object min(List allobjs, Expression exp)
0290: throws QueryExecutionException {
0291:
0292: return this .least(allobjs, exp, null);
0293:
0294: }
0295:
0296: public Object min(List allobjs, Expression exp, String saveValueName)
0297: throws QueryExecutionException {
0298:
0299: return this .least(allobjs, exp, saveValueName);
0300:
0301: }
0302:
0303: public Map.Entry maxEntry(Map m, String type) {
0304:
0305: int t = 0;
0306:
0307: if (type.equals(GroupingFunctions.VALUE)) {
0308:
0309: t = 1;
0310:
0311: }
0312:
0313: Map.Entry r = null;
0314: Map.Entry le = null;
0315:
0316: Iterator iter = m.entrySet().iterator();
0317:
0318: while (iter.hasNext()) {
0319:
0320: r = (Map.Entry) iter.next();
0321:
0322: if (le != null) {
0323:
0324: if (t == 0) {
0325:
0326: if (Utilities.isGTEquals(r.getKey(), le.getKey())) {
0327:
0328: le = r;
0329:
0330: }
0331:
0332: } else {
0333:
0334: if (Utilities.isGTEquals(r.getValue(), le
0335: .getValue())) {
0336:
0337: le = r;
0338:
0339: }
0340:
0341: }
0342:
0343: } else {
0344:
0345: le = r;
0346:
0347: }
0348:
0349: }
0350:
0351: return le;
0352:
0353: }
0354:
0355: public Map.Entry minEntry(Object m, String type)
0356: throws QueryExecutionException {
0357:
0358: if (!(m instanceof Map)) {
0359:
0360: throw new QueryExecutionException("Only instances of: "
0361: + Map.class.getName() + " are supported, passed: "
0362: + m.getClass().getName());
0363:
0364: }
0365:
0366: return this .minEntry((Map) m, type);
0367:
0368: }
0369:
0370: public Map.Entry minEntry(Map m, String type) {
0371:
0372: int t = 0;
0373:
0374: if (type.equals(GroupingFunctions.VALUE)) {
0375:
0376: t = 1;
0377:
0378: }
0379:
0380: Map.Entry r = null;
0381: Map.Entry le = null;
0382:
0383: Iterator iter = m.entrySet().iterator();
0384:
0385: while (iter.hasNext()) {
0386:
0387: r = (Map.Entry) iter.next();
0388:
0389: if (le != null) {
0390:
0391: if (t == 0) {
0392:
0393: if (Utilities.isLTEquals(r.getKey(), le.getKey())) {
0394:
0395: le = r;
0396:
0397: }
0398:
0399: } else {
0400:
0401: if (Utilities.isLTEquals(r.getValue(), le
0402: .getValue())) {
0403:
0404: le = r;
0405:
0406: }
0407:
0408: }
0409:
0410: } else {
0411:
0412: le = r;
0413:
0414: }
0415:
0416: }
0417:
0418: return le;
0419:
0420: }
0421:
0422: public Object max(List allobjs, Expression exp, String saveValueName)
0423: throws QueryExecutionException {
0424:
0425: return this .greatest(allobjs, exp, saveValueName);
0426:
0427: }
0428:
0429: public Object greatest(List allobjs, Expression exp,
0430: String saveValueName) throws QueryExecutionException {
0431:
0432: if (saveValueName != null) {
0433:
0434: Object o = this .q.getSaveValue(saveValueName);
0435:
0436: if (o != null) {
0437:
0438: return (Double) o;
0439:
0440: }
0441:
0442: }
0443:
0444: if (allobjs.size() == 0) {
0445:
0446: return null;
0447:
0448: }
0449:
0450: Object currObj = this .q.getCurrentObject();
0451:
0452: Object g = null;
0453:
0454: int s = allobjs.size();
0455:
0456: for (int i = 0; i < s; i++) {
0457:
0458: Object o = allobjs.get(i);
0459:
0460: this .q.setCurrentObject(o);
0461:
0462: Object v = null;
0463:
0464: try {
0465:
0466: v = exp.getValue(o, this .q);
0467:
0468: } catch (Exception e) {
0469:
0470: this .q.setCurrentObject(currObj);
0471:
0472: throw new QueryExecutionException(
0473: "Unable to get value from expression: " + exp
0474: + " for maximum value" + e);
0475:
0476: }
0477:
0478: if (g == null) {
0479:
0480: g = v;
0481:
0482: } else {
0483:
0484: int c = Utilities.compare(v, g);
0485:
0486: if (c > 0) {
0487:
0488: g = v;
0489:
0490: }
0491:
0492: }
0493:
0494: }
0495:
0496: if (saveValueName != null) {
0497:
0498: this .q.setSaveValue(saveValueName, g);
0499:
0500: }
0501:
0502: this .q.setCurrentObject(currObj);
0503:
0504: return g;
0505:
0506: }
0507:
0508: public Object greatest(List allobjs, Expression exp)
0509: throws QueryExecutionException {
0510:
0511: return this .greatest(allobjs, exp, null);
0512:
0513: }
0514:
0515: public Object max(Expression exp) throws QueryExecutionException {
0516:
0517: return this .max((List) this .q
0518: .getVariable(Query.ALL_OBJS_VAR_NAME), exp);
0519:
0520: }
0521:
0522: public Object max(List allobjs, Expression exp)
0523: throws QueryExecutionException {
0524:
0525: return this .greatest(allobjs, exp, null);
0526:
0527: }
0528:
0529: private double getTotal(List allobjs, Expression exp)
0530: throws QueryExecutionException {
0531:
0532: Object currObj = this .q.getCurrentObject();
0533:
0534: double total = 0;
0535:
0536: int size = allobjs.size();
0537:
0538: for (int i = 0; i < size; i++) {
0539:
0540: Object o = allobjs.get(i);
0541:
0542: this .q.setCurrentObject(o);
0543:
0544: Number n = null;
0545:
0546: try {
0547:
0548: n = (Number) exp.getValue(o, this .q);
0549:
0550: } catch (Exception e) {
0551:
0552: this .q.setCurrentObject(currObj);
0553:
0554: throw new QueryExecutionException(
0555: "Unable to get value from expression: " + exp
0556: + " for item: " + i
0557: + " from the list of objects.", e);
0558:
0559: }
0560:
0561: total += n.doubleValue();
0562:
0563: }
0564:
0565: this .q.setCurrentObject(currObj);
0566:
0567: return total;
0568:
0569: }
0570:
0571: public void checkType(Object o, Class expected, Expression exp)
0572: throws QueryExecutionException {
0573:
0574: if (!expected.isInstance(o)) {
0575:
0576: throw new QueryExecutionException("Expression: " + exp
0577: + " returns type: " + o.getClass().getName()
0578: + " however must return instance of: "
0579: + expected.getName());
0580:
0581: }
0582:
0583: }
0584:
0585: public Double sum(List allobjs, Expression exp, String saveValueName)
0586: throws QueryExecutionException {
0587:
0588: if (saveValueName != null) {
0589:
0590: Object o = this .q.getSaveValue(saveValueName);
0591:
0592: if (o != null) {
0593:
0594: return (Double) o;
0595:
0596: }
0597:
0598: }
0599:
0600: if ((allobjs == null) || (allobjs.size() == 0)) {
0601:
0602: return new Double(0);
0603:
0604: }
0605:
0606: double total = this .getTotal(allobjs, exp);
0607:
0608: Double d = new Double(total);
0609:
0610: if ((saveValueName != null) && (q != null)) {
0611:
0612: this .q.setSaveValue(saveValueName, d);
0613:
0614: }
0615:
0616: return d;
0617:
0618: }
0619:
0620: public Double sum(Expression exp) throws QueryExecutionException {
0621:
0622: return this .sum((List) this .q.getAllObjects(), exp);
0623:
0624: }
0625:
0626: public Double sum(List objs, Expression exp)
0627: throws QueryExecutionException {
0628:
0629: Class c = null;
0630:
0631: try {
0632:
0633: c = exp.getExpectedReturnType(this .q);
0634:
0635: } catch (Exception e) {
0636:
0637: throw new QueryExecutionException(
0638: "Unable to determine expected return type for expression: "
0639: + exp, e);
0640:
0641: }
0642:
0643: boolean dyn = false;
0644:
0645: if (!c.getName().equals(Object.class.getName())) {
0646:
0647: // Should return a number...
0648: if (!Utilities.isNumber(c)) {
0649:
0650: throw new QueryExecutionException(
0651: "This function expects the expression: "
0652: + exp
0653: + " to return a number (sub-class of: "
0654: + Number.class.getName()
0655: + ") but evaluation of the expression will return an instance of: "
0656: + c.getName());
0657:
0658: }
0659:
0660: } else {
0661:
0662: dyn = true;
0663:
0664: }
0665:
0666: Object co = this .q.getCurrentObject();
0667: List allobjs = this .q.getAllObjects();
0668:
0669: this .q.setAllObjects(objs);
0670:
0671: int s = objs.size() - 1;
0672:
0673: double d = 0;
0674:
0675: for (int i = s; i > -1; i--) {
0676:
0677: Object o = objs.get(i);
0678:
0679: this .q.setCurrentObject(o);
0680:
0681: Object v = null;
0682:
0683: try {
0684:
0685: v = exp.getValue(o, this .q);
0686:
0687: } catch (Exception e) {
0688:
0689: this .q.setCurrentObject(co);
0690: this .q.setAllObjects(allobjs);
0691:
0692: throw new QueryExecutionException(
0693: "Unable to evaluate expression: " + exp
0694: + " on item: " + i, e);
0695:
0696: }
0697:
0698: if (v == null) {
0699:
0700: // Skip... i.e. assume it's zero.
0701: continue;
0702:
0703: }
0704:
0705: if (dyn) {
0706:
0707: if (!(Utilities.isNumber(v))) {
0708:
0709: this .q.setCurrentObject(co);
0710: this .q.setAllObjects(allobjs);
0711:
0712: throw new QueryExecutionException(
0713: "Expected expression: "
0714: + exp
0715: + " to return a number (sub-class of: "
0716: + Number.class.getName()
0717: + ") but returns instance of: "
0718: + o.getClass().getName()
0719: + " for item: " + i + " (class: "
0720: + v.getClass().getName() + ")");
0721:
0722: }
0723:
0724: }
0725:
0726: d += ((Number) v).doubleValue();
0727:
0728: }
0729:
0730: this .q.setCurrentObject(co);
0731: this .q.setAllObjects(allobjs);
0732:
0733: return new Double(d);
0734:
0735: }
0736:
0737: /**
0738: * This function allows you to specify your own accessor as a string that will
0739: * be used to access the relevant value for each of the objects in the <b>objs</b>
0740: * List.
0741: *
0742: * @param objs The List of objects you wish to sum over.
0743: * @param acc The accessor to create for accessing the value in each of the objects in <b>objs</b>.
0744: * @return The summed value.
0745: * @throws QueryExecutionException If the accessor is not valid for the objects in the list or
0746: * if the accessor throws an exception.
0747: */
0748: public Double sum(List objs, String acc)
0749: throws QueryExecutionException {
0750:
0751: if ((objs == null) || (objs.size() == 0)) {
0752:
0753: return new Double(0);
0754:
0755: }
0756:
0757: // Get the first object.
0758: Object o = objs.get(0);
0759:
0760: Getter get = null;
0761:
0762: try {
0763:
0764: get = new Getter(acc, o.getClass());
0765:
0766: } catch (Exception e) {
0767:
0768: throw new QueryExecutionException(
0769: "Unable to create accessor for: " + acc
0770: + " with class: " + o.getClass().getName(),
0771: e);
0772:
0773: }
0774:
0775: if (!get.getType().getName().equals(Object.class.getName())) {
0776:
0777: // Should return a number...
0778: if (!Utilities.isNumber(get.getType())) {
0779:
0780: throw new QueryExecutionException(
0781: "This function expects the accessor (second parm): "
0782: + acc
0783: + " to return a number (sub-class of: "
0784: + Number.class.getName()
0785: + ") but evaluation of the accessor will return an instance of: "
0786: + get.getType().getName());
0787:
0788: }
0789:
0790: }
0791:
0792: int s = objs.size() - 1;
0793:
0794: Object currobj = this .q.getCurrentObject();
0795: List allobjs = this .q.getAllObjects();
0796:
0797: this .q.setAllObjects(objs);
0798:
0799: double d = 0;
0800:
0801: for (int i = s; i > -1; i--) {
0802:
0803: o = objs.get(i);
0804:
0805: this .q.setCurrentObject(o);
0806:
0807: Object v = null;
0808:
0809: try {
0810:
0811: v = get.getValue(o);
0812:
0813: } catch (Exception e) {
0814:
0815: this .q.setCurrentObject(currobj);
0816: this .q.setAllObjects(allobjs);
0817:
0818: throw new QueryExecutionException(
0819: "Unable to evaluate accessor: " + acc
0820: + " on item: " + i, e);
0821:
0822: }
0823:
0824: if (v == null) {
0825:
0826: // Skip... i.e. assume it's zero.
0827: continue;
0828:
0829: }
0830:
0831: d += ((Number) v).doubleValue();
0832:
0833: }
0834:
0835: this .q.setCurrentObject(currobj);
0836: this .q.setAllObjects(allobjs);
0837:
0838: return new Double(d);
0839:
0840: }
0841:
0842: public String concat(List allobjs, Expression exp, String sep,
0843: String saveValueName) throws QueryExecutionException {
0844:
0845: if (saveValueName != null) {
0846:
0847: Object o = this .q.getSaveValue(saveValueName);
0848:
0849: if (o != null) {
0850:
0851: return (String) o;
0852:
0853: }
0854:
0855: }
0856:
0857: StringBuffer buf = new StringBuffer();
0858:
0859: int size = allobjs.size();
0860: int size1 = size - 1;
0861:
0862: Object currObj = this .q.getCurrentObject();
0863: List currall = this .q.getAllObjects();
0864:
0865: this .q.setAllObjects(allobjs);
0866:
0867: for (int i = 0; i < size; i++) {
0868:
0869: Object o = allobjs.get(i);
0870:
0871: this .q.setCurrentObject(o);
0872:
0873: Object v = null;
0874:
0875: try {
0876:
0877: v = exp.getValue(o, this .q);
0878:
0879: } catch (Exception e) {
0880:
0881: this .q.setCurrentObject(currObj);
0882: this .q.setAllObjects(currall);
0883:
0884: throw new QueryExecutionException(
0885: "Unable to get value from expression: " + exp
0886: + " for item: " + i
0887: + " from the list of objects.", e);
0888:
0889: }
0890:
0891: buf.append(v);
0892:
0893: if ((sep != null) && (i < size1)) {
0894:
0895: buf.append(sep);
0896:
0897: }
0898:
0899: }
0900:
0901: String r = buf.toString();
0902:
0903: if ((saveValueName != null) && (q != null)) {
0904:
0905: q.setSaveValue(saveValueName, r);
0906:
0907: }
0908:
0909: this .q.setCurrentObject(currObj);
0910: this .q.setAllObjects(currall);
0911:
0912: return r;
0913:
0914: }
0915:
0916: public String concat(List allobjs, Expression exp, String sep)
0917: throws QueryExecutionException {
0918:
0919: return this .concat(allobjs, exp, sep, null);
0920:
0921: }
0922:
0923: public String concat(Expression exp) throws QueryExecutionException {
0924:
0925: return this .concat((List) this .q
0926: .getVariable(Query.ALL_OBJS_VAR_NAME), exp);
0927:
0928: }
0929:
0930: public String concat(List allobjs, Expression exp)
0931: throws QueryExecutionException {
0932:
0933: return this .concat(allobjs, exp, null, null);
0934:
0935: }
0936:
0937: public Double avg(List allobjs, Expression exp, String saveValueName)
0938: throws QueryExecutionException {
0939:
0940: if (saveValueName != null) {
0941:
0942: Object o = this .q.getSaveValue(saveValueName);
0943:
0944: if (o != null) {
0945:
0946: return (Double) o;
0947:
0948: }
0949:
0950: }
0951:
0952: if ((allobjs == null) || (allobjs.size() == 0)) {
0953:
0954: return new Double(0);
0955:
0956: }
0957:
0958: double total = this .getTotal(allobjs, exp);
0959:
0960: double avg = total / allobjs.size();
0961:
0962: Double d = new Double(avg);
0963:
0964: if (saveValueName != null) {
0965:
0966: q.setSaveValue(saveValueName, d);
0967:
0968: }
0969:
0970: return d;
0971:
0972: }
0973:
0974: public Double avg(Expression exp) throws QueryExecutionException {
0975:
0976: return this .avg((List) this .q
0977: .getVariable(Query.ALL_OBJS_VAR_NAME), exp);
0978:
0979: }
0980:
0981: public Double avg(List allobjs, Expression exp)
0982: throws QueryExecutionException {
0983:
0984: return this .avg(allobjs, exp, null);
0985:
0986: }
0987:
0988: /**
0989: * A function that will take each item from the passed in List and
0990: * determine a "count" for each item, i.e. how many times each item appears.
0991: *
0992: * @param objs The List of objects to operate on.
0993: * @return A Map of object to a count of the number of times the object appears in the list.
0994: * @throws QueryExecutionException Won't happen in this method.
0995: */
0996: public Map occurrence(List objs) throws QueryExecutionException {
0997:
0998: return this .occurrence(objs, null);
0999:
1000: }
1001:
1002: /*
1003: public Map occurrence (Expression exp)
1004: throws QueryExecutionException
1005: {
1006:
1007: return this.occurrence ((List) this.q.getVariable (Query.ALL_OBJS_VAR_NAME),
1008: exp);
1009:
1010: }
1011: */
1012:
1013: /**
1014: * A function that will take each item from the passed in List and
1015: * determine a "count" for each item, i.e. how many times each item appears.
1016: *
1017: * @param objs The List of objects to operate on.
1018: * @param exp An optional expression that should be performed on each object
1019: * and the value returned used instead.
1020: * @return A Map of object to a count of the number of times the object appears in the list.
1021: * @throws QueryExecutionException If the expression cannot be evaluated.
1022: */
1023: public Map occurrence(List objs, Expression exp)
1024: throws QueryExecutionException {
1025:
1026: Map occs = new HashMap();
1027:
1028: if (objs == null) {
1029:
1030: return occs;
1031:
1032: }
1033:
1034: Object currObj = this .q.getCurrentObject();
1035: List currAll = this .q.getAllObjects();
1036:
1037: this .q.setAllObjects(objs);
1038:
1039: int s = objs.size();
1040:
1041: for (int i = 0; i < s; i++) {
1042:
1043: Object o = objs.get(i);
1044:
1045: this .q.setCurrentObject(o);
1046:
1047: if (exp != null) {
1048:
1049: try {
1050:
1051: o = exp.getValue(o, this .q);
1052:
1053: } catch (Exception e) {
1054:
1055: this .q.setCurrentObject(currObj);
1056: this .q.setAllObjects(currAll);
1057:
1058: throw new QueryExecutionException(
1059: "Unable to get value for expression: "
1060: + exp + " for object: " + i
1061: + " from the list of objects.", e);
1062:
1063: }
1064:
1065: }
1066:
1067: Integer c = (Integer) occs.get(o);
1068:
1069: int co = 1;
1070:
1071: if (c != null) {
1072:
1073: co = c.intValue();
1074:
1075: co++;
1076:
1077: }
1078:
1079: occs.put(o, Integer.valueOf(co));
1080:
1081: }
1082:
1083: this .q.setCurrentObject(currObj);
1084: this .q.setAllObjects(currAll);
1085:
1086: return occs;
1087:
1088: }
1089:
1090: /**
1091: * This is the same as {@link #occurrence(List,Expression)} except that the
1092: * second expression should evaluate to a number that will be used to limit the
1093: * results, the occurrence count must be greater than or equal to the value from
1094: * the expression.
1095: *
1096: * @param objs The List of objects to operate on.
1097: * @param exp An optional expression that should be performed on each object
1098: * and the value returned used instead.
1099: * @param limitExp An expression that when evaluated should return a number, this
1100: * will then be used to limit the results returned to those that have an
1101: * occurrence count >= that number.
1102: * @return A Map of object to a count of the number of times the object appears in the list.
1103: * @throws QueryExecutionException If the expression cannot be evaluated or the <b>limitExp</b>
1104: * arg does not evaulate to a number.
1105: */
1106: public Map occurrence(List objs, Expression exp, Expression limitExp)
1107: throws QueryExecutionException {
1108:
1109: Map rs = this .occurrence(objs, exp);
1110:
1111: // Evaluate the limit expression.
1112: Object o = limitExp.getValue(this .q.getCurrentObject(), this .q);
1113:
1114: if (!(o instanceof Number)) {
1115:
1116: throw new QueryExecutionException("Limit expression: "
1117: + limitExp + " does not evaluate to a number");
1118:
1119: }
1120:
1121: int i = ((Number) o).intValue();
1122:
1123: Map ret = new HashMap();
1124:
1125: Iterator iter = rs.keySet().iterator();
1126:
1127: while (iter.hasNext()) {
1128:
1129: Object k = iter.next();
1130:
1131: Integer c = (Integer) rs.get(k);
1132:
1133: if (c.intValue() >= i) {
1134:
1135: ret.put(k, c);
1136:
1137: }
1138:
1139: }
1140:
1141: return ret;
1142:
1143: }
1144:
1145: }
|