1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.millscript.millscript.functions;
23
24 import org.millscript.commons.alert.Alert;
25 import org.millscript.commons.util.EMap;
26 import org.millscript.commons.util.IList;
27 import org.millscript.commons.util.IMap;
28 import org.millscript.commons.util.ListIterator;
29 import org.millscript.commons.util.map.EHashMap;
30 import org.millscript.millscript.datatypes.MapAwareTools;
31 import org.millscript.millscript.vm.Machine;
32
33 /**
34 * This class implements the MillScript <code>indexByPrimaryKey</code> function.
35 */
36 public class IndexByPrimaryKeyFunction extends Function {
37
38 /**
39 * @see org.millscript.millscript.functions.Function#apply(org.millscript.millscript.vm.Machine, int)
40 */
41 @Override
42 public void apply( final Machine mc, final int nargs ) {
43 checkNargs( mc, 2, nargs );
44 Object by = mc.popObject();
45 IList list = mc.popIList();
46 mc.pushObject( indexByPrimaryKey( list, by ) );
47 }
48
49 /**
50 * Returns the supplied data indexed by the specified field. The supplied
51 * data is sorted into a Map, whose keys are all the values for the
52 * specified field and whose value is the data with that key value.
53 *
54 * @param list the data to index, a list of maps
55 * @param by the field to index by
56 * @return a map of the indexed data
57 */
58 static IMap indexByPrimaryKey( final IList list, final Object by ) {
59 EMap< Object, Object > h = new EHashMap< Object, Object >();
60 ListIterator< ? > it = list.iterator( true );
61 while ( it.hasNext() ) {
62 Object x = it.nextValue();
63 Object val = MapAwareTools.get( x, by );
64 if ( h.containsKey( val ) ) {
65 throw new Alert(
66 "Multiple records sharing this key",
67 "Primary keys uniquely determine records"
68 ).culprit(
69 "record",
70 x
71 ).culprit(
72 "key",
73 by
74 ).culprit(
75 "value",
76 val
77 ).mishap();
78 } else {
79 h.insert( val, x );
80 }
81 }
82 return h;
83 }
84
85 }