View Javadoc

1   ////////////////////////////////////////////////////////////////////////////////
2   // MillScript: an Open Spice interpreter and batch website creation tool
3   // Copyright (C) 2001-2004 Open World Ltd
4   // Copyright (C) 2005 Kevin Rogers
5   //
6   // This file is part of MillScript.
7   //
8   // MillScript is free software; you can redistribute it and/or modify it under
9   // the terms of the GNU General Public License as published by the Free
10  // Software Foundation; either version 2 of the License, or (at your option)
11  // any later version.
12  //
13  // MillScript is distributed in the hope that it will be useful, but WITHOUT
14  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  // more details.
17  //
18  // You should have received a copy of the GNU General Public License along with
19  // MillScript; if not, write to the Free Software Foundation, Inc., 59 Temple
20  // Place, Suite 330, Boston, MA  02111-1307  USA
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  }