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.util.EList;
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.list.ELinkedList;
30 import org.millscript.commons.util.map.EHashMap;
31 import org.millscript.millscript.alert.Alerts;
32 import org.millscript.millscript.vm.Machine;
33
34 /**
35 * This class implements the MillScript <code>joinByPrimaryKey</code> function.
36 */
37 public class JoinByPrimaryKeyFunction extends Function {
38
39 /**
40 * @see org.millscript.millscript.functions.Function#apply(org.millscript.millscript.vm.Machine, int)
41 */
42 @Override
43 public void apply( final Machine mc, final int nargs ) {
44 checkNargs( mc, 3, nargs );
45 Object by = mc.popObject();
46 IList y = mc.popIList();
47 IList x = mc.popIList();
48 IMap ibpk = IndexByPrimaryKeyFunction.indexByPrimaryKey( y, by );
49 mc.pushObject( jbpk( x, ibpk, by ) );
50 }
51
52 /**
53 * Returns the supplied data joined by the specified field. The data is
54 * supplied as a list of one set of data and a map containing the indexed
55 * other set of data.
56 *
57 * @param x the list of maps for one set of data
58 * @param map the indexed other set of data
59 * @param by the field to join by
60 * @return a list of maps containing the two sets of data joined together
61 * @see IndexByPrimaryKeyFunction
62 */
63 @SuppressWarnings( "unchecked" )
64 static IList jbpk( final IList x, final IMap map, final Object by ) {
65 EList< IMap > result = new ELinkedList< IMap >();
66 ListIterator< ? > it = x.iterator( true );
67 while ( it.hasNext() ) {
68
69 IMap recordX = (IMap)it.nextValue();
70
71 IMap recordY = (IMap)map.get( recordX.get( by ) );
72 if ( recordY == null ) {
73 throw(
74 Alerts.eval(
75 "Missing record",
76 "When joining by primary key, there must be a record for each key"
77 ).
78 culprit( "key", by ).
79 culprit( "record", recordX ).
80 mishap()
81 );
82 }
83 EMap< Object, Object > m = new EHashMap< Object, Object >( recordY );
84 m.insertAll( recordX );
85 result.addLast( m );
86 }
87 return result;
88 }
89
90 }