/tdboid/src/org/openjena/atlas/lib/ColumnMap.java

http://androjena.googlecode.com/ · Java · 267 lines · 158 code · 42 blank · 67 comment · 15 complexity · b2dbb92c4cb2489bcd3dc63fa0629394 MD5 · raw file

  1. /*
  2. * (c) Copyright 2008, 2009 Hewlett-Packard Development Company, LP
  3. * All rights reserved.
  4. * [See end of file]
  5. */
  6. package org.openjena.atlas.lib;
  7. import static java.lang.String.format;
  8. import java.util.Arrays;
  9. import java.util.List;
  10. /** General descriptor of a reordering (mapping) of columns in tuples to columns in indexes,
  11. * for example, from triples to triple index order.
  12. *
  13. * Naming: map is convert to the reordered form, fetch is get back.
  14. */
  15. public class ColumnMap
  16. {
  17. // Map from tuple order to index order
  18. // So SPO->POS is (0->2, 1->0, 2->1)
  19. // i.e. the location of the element after mapping.
  20. private int[] insertOrder ;
  21. // The mapping from index to tuple order
  22. // For POS->SPO, is (0->1, 1->2, 2->0)
  23. // i.e. the location to fetch the mapped element from.
  24. private int[] fetchOrder ;
  25. private String label ;
  26. /** Construct a column mapping that maps the input (one col, one char) to the output */
  27. public ColumnMap(String input, String output)
  28. {
  29. this(input+"->"+output, compileMapping(input, output)) ;
  30. }
  31. public <T> ColumnMap(String label, List<T> input, List<T> output)
  32. {
  33. this(label, compileMapping(input, output)) ;
  34. }
  35. public <T> ColumnMap(String label, T[] input, T[] output)
  36. {
  37. this(label, compileMapping(input, output)) ;
  38. }
  39. /** Construct a column map - the elements are the
  40. * mappings of a tuple originally in the order 0,1,2,...
  41. * so SPO->POS is 2,0,1 (SPO->POS so S->2, P->0, O->1)
  42. * and not 1,2,0 (which is the extraction mapping).
  43. * The label is just a lable and is not interpretted.
  44. */
  45. public ColumnMap(String label, int...elements)
  46. {
  47. this.label = label ;
  48. this.insertOrder = new int[elements.length] ;
  49. System.arraycopy(elements, 0, elements, 0, elements.length) ;
  50. Arrays.fill(insertOrder, -1) ;
  51. this.fetchOrder = new int[elements.length] ;
  52. Arrays.fill(fetchOrder, -1) ;
  53. for ( int i = 0 ; i < elements.length ; i++ )
  54. {
  55. int x = elements[i] ;
  56. if ( x < 0 || x >= elements.length)
  57. throw new IllegalArgumentException("Out of range: "+x) ;
  58. // Checking
  59. if ( insertOrder[i] != -1 || fetchOrder[x] != -1 )
  60. throw new IllegalArgumentException("Inconsistent: "+ListUtils.str(elements)) ;
  61. insertOrder[i] = x ;
  62. fetchOrder[x] = i ;
  63. }
  64. }
  65. /** Length of mapping */
  66. public int length() { return fetchOrder.length ; }
  67. /** Apply to an <em>unmapped</em> tuple to get the i'th slot after mapping : SPO->POS : 0'th slot is P from SPO */
  68. public <T> T fetchSlot(int idx, Tuple<T> tuple)
  69. {
  70. idx = fetchOrder[idx] ; // Apply the reverse mapping as we are doing zero is P, so it's an unmap.
  71. return tuple.get(idx) ;
  72. }
  73. /** Apply to an <em>unmapped</em> tuple to get the i'th slot after mapping : SPO->POS : 0'th slot is P from SPO */
  74. public <T> T fetchSlot(int idx, T[] tuple)
  75. {
  76. idx = fetchOrder[idx] ; // Apply the reverse mapping as we are doing zero is P, so it's an unmap.
  77. return tuple[idx] ;
  78. }
  79. /** Apply to a <em>mapped</em> tuple to get the i'th slot as it appears after mapping : SPO->POS : 0'th slot is S from POS */
  80. public <T> T mapSlot(int idx, Tuple<T> tuple)
  81. {
  82. idx = insertOrder[idx] ;
  83. return tuple.get(idx) ;
  84. }
  85. /** Apply to a <em>mapped</em> tuple to get the i'th slot as it appears after mapping : SPO->POS : 0'th slot is S from POS */
  86. public <T> T mapSlot(int idx, T[] tuple)
  87. {
  88. idx = insertOrder[idx] ; // Yes - it's the insert location we want to access
  89. return tuple[idx] ;
  90. }
  91. /** Get the index of the i'th slot as it appears after mapping : SPO->POS : 0'th slot is S from POS so 2->0 */
  92. public int mapSlotIdx(int idx)
  93. {
  94. return insertOrder[idx] ; // Yes - it's the insert location we want to access
  95. }
  96. /** Get the index of the i'th slot as it appears from a mapping : for SPO->POS : 0'th slot is P so 1->0 */
  97. public int fetchSlotIdx(int idx)
  98. {
  99. return fetchOrder[idx] ; // Yes - it's the insert location we want to access
  100. }
  101. /** Apply to an <em>unmapped</em> tuple to get a tuple with the column mapping applied */
  102. public <T> Tuple<T> map(Tuple<T> src)
  103. {
  104. return map(src, insertOrder) ;
  105. }
  106. /** Apply to a <em>mapped</em> tuple to get a tuple with the column mapping reverse-applied */
  107. public <T> Tuple<T> unmap(Tuple<T> src)
  108. {
  109. return map(src, fetchOrder) ;
  110. }
  111. private <T> Tuple<T> map(Tuple<T> src, int[] map)
  112. {
  113. @SuppressWarnings("unchecked")
  114. T[] elts = (T[])new Object[src.size()] ;
  115. for ( int i = 0 ; i < src.size() ; i++ )
  116. {
  117. int j = map[i] ;
  118. elts[j] = src.get(i) ;
  119. }
  120. return Tuple.create(elts) ;
  121. }
  122. /** Compile a mapping encoded as single charcaters e.g. "SPO", "POS" */
  123. static int[] compileMapping(String domain, String range)
  124. {
  125. List<Character> input = StrUtils.toCharList(domain) ;
  126. List<Character> output = StrUtils.toCharList(range) ;
  127. return compileMapping(input, output) ;
  128. }
  129. /** Compile a mapping, encoded two list, the domain and range of the mapping function */
  130. static <T> int[] compileMapping(T[] domain, T[] range)
  131. {
  132. return compileMapping(Arrays.asList(domain), Arrays.asList(range)) ;
  133. }
  134. /** Compile a mapping */
  135. static <T> int[] compileMapping(List<T> domain, List<T>range)
  136. {
  137. if ( domain.size() != range.size() )
  138. throw new AtlasException("Bad mapping: lengths not the same: "+domain+" -> "+range) ;
  139. int[] cols = new int[domain.size()] ;
  140. boolean[] mapped = new boolean[domain.size()] ;
  141. //Arrays.fill(mapped, false) ;
  142. for ( int i = 0 ; i < domain.size() ; i++ )
  143. {
  144. T input = domain.get(i) ;
  145. int j = range.indexOf(input) ;
  146. if ( j < 0 )
  147. throw new AtlasException("Bad mapping: missing mapping: "+domain+" -> "+range) ;
  148. if ( mapped[j] )
  149. throw new AtlasException("Bad mapping: duplicate: "+domain+" -> "+range) ;
  150. cols[i] = j ;
  151. mapped[j] = true ;
  152. }
  153. return cols ;
  154. }
  155. @Override
  156. public String toString()
  157. {
  158. //return label ;
  159. return format("%s:%s%s", label, mapStr(insertOrder), mapStr(fetchOrder)) ;
  160. }
  161. private Object mapStr(int[] map)
  162. {
  163. StringBuilder buff = new StringBuilder() ;
  164. String sep = "{" ;
  165. for ( int i = 0 ; i < map.length ; i++ )
  166. {
  167. buff.append(sep) ;
  168. sep = ", " ;
  169. buff.append(format("%d->%d", i, map[i])) ;
  170. }
  171. buff.append("}") ;
  172. return buff.toString() ;
  173. }
  174. public String getLabel()
  175. {
  176. return label ;
  177. }
  178. /** Reorder the letters of a string by the same rules as this column map (forward, map direction)*/
  179. public String mapName(String word)
  180. {
  181. return mapString(word, insertOrder) ;
  182. }
  183. /** Reorder the letters of a string by the same rules as this column map (backward, fetch direction) */
  184. public String unmapName(String word)
  185. {
  186. return mapString(word, fetchOrder) ;
  187. }
  188. // Map is get from i and put to j
  189. private String mapString(String src, int[] map)
  190. {
  191. char[] chars = new char[src.length()] ;
  192. for ( int i = 0 ; i < src.length() ; i++ )
  193. {
  194. int j = map[i] ;
  195. chars[j] = src.charAt(i) ;
  196. }
  197. return new String(chars) ;
  198. }
  199. }
  200. /*
  201. * (c) Copyright 2008, 2009 Hewlett-Packard Development Company, LP
  202. * All rights reserved.
  203. *
  204. * Redistribution and use in source and binary forms, with or without
  205. * modification, are permitted provided that the following conditions
  206. * are met:
  207. * 1. Redistributions of source code must retain the above copyright
  208. * notice, this list of conditions and the following disclaimer.
  209. * 2. Redistributions in binary form must reproduce the above copyright
  210. * notice, this list of conditions and the following disclaimer in the
  211. * documentation and/or other materials provided with the distribution.
  212. * 3. The name of the author may not be used to endorse or promote products
  213. * derived from this software without specific prior written permission.
  214. *
  215. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  216. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  217. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  218. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  219. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  220. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  221. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  222. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  223. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  224. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  225. */