@Override public String resolve(String fieldName, int[] arrayPos) throws FieldDoesNotHaveDimensionException, FieldIndexOutOfBoundsException, InvalidElementException, IOException { String result = null; try { result = wrapped.resolve(fieldName, arrayPos); } catch (FieldIndexOutOfBoundsException ex) { if (ex.getDimension() > dimension) { fieldResolvedUsingFullArrayPos = true; } throw ex; } fieldResolvedUsingFullArrayPos = true; return result; }
@Override public void resolve( DefaultParser parser, String parametersString, Reader oin, Writer out, DataFieldResolver dataFieldResolver, int[] arrayPositioner) throws IOException { if (out != null) { out.flush(); } String[] endMarkers = {"/loop"}; if (!(oin instanceof MultiMarkLineNumberReader)) { throw new RuntimeException("MultiMarkLineNumberReader required"); } MultiMarkLineNumberReader in = (MultiMarkLineNumberReader) oin; in.mark(64000); // this is the maximum codelength in a loop int[] newArrayPositioner = new int[arrayPositioner.length + 1]; // add a loop recursion for (int i = 0; i < arrayPositioner.length; i++) { newArrayPositioner[i] = arrayPositioner[i]; // copy existing values } newArrayPositioner[newArrayPositioner.length - 1] = 0; String[] parameters = parametersString.trim().split(" "); boolean sortValues; SortedMap<Object, String> sortedMap = null; boolean invertSortOrder = false; String sortKeyField = null; if (parameters[0].equals("sort")) { sortValues = true; if (parameters[1].equals("desc")) { invertSortOrder = true; } else { if (!parameters[1].equals("asc")) { throw new RuntimeException("the keyword sort must be followed by either asc or desc"); } } sortedMap = new TreeMap<Object, String>(); sortKeyField = parameters[2]; } else { sortValues = false; } while (true) { final WrappedDataFieldResolver wrappedDataFieldResolver = new WrappedDataFieldResolver(dataFieldResolver, arrayPositioner.length); final StringWriter outBuffer = new StringWriter(); if (out != null) { // parse loop content parser.perform(outBuffer, endMarkers, newArrayPositioner, wrappedDataFieldResolver); } else { // skip to the end tag parser.perform(null, endMarkers, newArrayPositioner, wrappedDataFieldResolver); } if (out == null) { break; } if (!wrappedDataFieldResolver.isFieldResolvedUsingFullArrayPos()) { // none of the fields evaluating to a value used the full length // of the array positioner (so incrementing the loop variable // wouldn't yield to a different result) break; } else { if (out != null) { if (sortValues) { Object value = null; try { value = dataFieldResolver.resolveAsObject(sortKeyField, newArrayPositioner); } catch (FieldDoesNotHaveDimensionException ex) { log.warn( "the sort-key" + sortKeyField + "doesn't have as many dimensions as loops are nested"); } catch (FieldIndexOutOfBoundsException ex) { log.debug("the sort-key" + sortKeyField + "end before an other field in the loop"); } catch (InvalidElementException ex) { log.warn("the sort-key" + sortKeyField + "is an invalid elemend"); } SortKeyValue sortKeyValue = new SortKeyValue( newArrayPositioner[newArrayPositioner.length - 1], value, invertSortOrder); sortedMap.put(sortKeyValue, outBuffer.toString()); } else { out.write(outBuffer.toString()); } } in.reset(); // reset back to the beginning of the loop } newArrayPositioner[newArrayPositioner.length - 1]++; // increment loop variable } in.removeMark(); // recursion ended, remove corresponding mark if (sortValues) { for (String string : sortedMap.values()) { out.write(string); } } return; }