() {
+
+ private int p = 0;
+
+ /**
+ * @see java.util.Iterator#hasNext()
+ */
+ @Override
+ public boolean hasNext() {
+ return p < s.length();
+ }
+
+ /**
+ * @see java.util.Iterator#next()
+ */
+ @Override
+ public Character next() {
+ return s.charAt(p++);
+ }
+
+ /**
+ * @see java.util.Iterator#remove()
+ */
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ };
+ }
+
+ }) {
+ State newState = getState(c);
+ if (oldState != newState) {
+ if (oldState == State.NUMBER && (newState == State.IGNORED || newState == State.UNIT)) {
+ num = Integer.parseInt(s.subSequence(start, end).toString());
+ } else if (oldState == State.UNIT && (newState == State.IGNORED || newState == State.NUMBER)) {
+ out.nTimes(s.subSequence(start, end).toString(), num);
+ num = 0;
+ }
+ start = end;
+ }
+ ++end;
+ oldState = newState;
+ }
+ if (oldState == State.UNIT) {
+ out.nTimes(s.subSequence(start, end).toString(), num);
+ }
+
+ return out;
+ }
+
+ /**
+ * Parses and formats the given char sequence, preserving all data.
+ *
+ * Equivalent to eval(in).getExactly()
+ *
+ * @param in
+ * the char sequence, may not be null
+ * @return a formatted String, never null
+ */
+ public static String exactly(CharSequence in) {
+ return eval(in).getExactly();
+ }
+
+ /**
+ * Formats the given time delta, preserving all data.
+ *
+ * Equivalent to new HumanTime(in).getExactly()
+ *
+ * @param l
+ * the time delta
+ * @return a formatted String, never null
+ */
+ public static String exactly(long l) {
+ return new HumanTime(l).getExactly();
+ }
+
+ /**
+ * Parses and formats the given char sequence, potentially removing some data to make the output easier to
+ * understand.
+ *
+ * Equivalent to eval(in).getApproximately()
+ *
+ * @param in
+ * the char sequence, may not be null
+ * @return a formatted String, never null
+ */
+ public static String approximately(CharSequence in) {
+ return eval(in).getApproximately();
+ }
+
+ /**
+ * Formats the given time delta, preserving all data.
+ *
+ * Equivalent to new HumanTime(l).getApproximately()
+ *
+ * @param l
+ * the time delta
+ * @return a formatted String, never null
+ */
+ public static String approximately(long l) {
+ return new HumanTime(l).getApproximately();
+ }
+
+ /**
+ * The time delta.
+ */
+ private long delta;
+
+ /**
+ * No-argument Constructor for HumanTime.
+ *
+ * Equivalent to calling new HumanTime(0L)
.
+ */
+ public HumanTime() {
+ this(0L);
+ }
+
+ /**
+ * Constructor for HumanTime.
+ *
+ * @param delta
+ * the initial time delta, interpreted as a positive number
+ */
+ public HumanTime(long delta) {
+ super();
+ this.delta = Math.abs(delta);
+ }
+
+ private void nTimes(String unit, int n) {
+ if ("ms".equalsIgnoreCase(unit)) {
+ ms(n);
+ } else if ("s".equalsIgnoreCase(unit)) {
+ s(n);
+ } else if ("m".equalsIgnoreCase(unit)) {
+ m(n);
+ } else if ("h".equalsIgnoreCase(unit)) {
+ h(n);
+ } else if ("d".equalsIgnoreCase(unit)) {
+ d(n);
+ } else if ("y".equalsIgnoreCase(unit)) {
+ y(n);
+ }
+ }
+
+ private long upperCeiling(long x) {
+ return (x / 100) * (100 - CEILING_PERCENTAGE);
+ }
+
+ private long lowerCeiling(long x) {
+ return (x / 100) * CEILING_PERCENTAGE;
+ }
+
+ private String ceil(long d, long n) {
+ return Integer.toString((int) Math.ceil((double) d / n));
+ }
+
+ private String floor(long d, long n) {
+ return Integer.toString((int) Math.floor((double) d / n));
+ }
+
+ /**
+ * Adds one year to the time delta.
+ *
+ * @return this HumanTime object
+ */
+ public HumanTime y() {
+ return y(1);
+ }
+
+ /**
+ * Adds n years to the time delta.
+ *
+ * @param n
+ * n
+ * @return this HumanTime object
+ */
+ public HumanTime y(int n) {
+ delta += YEAR * Math.abs(n);
+ return this;
+ }
+
+ /**
+ * Adds one day to the time delta.
+ *
+ * @return this HumanTime object
+ */
+ public HumanTime d() {
+ return d(1);
+ }
+
+ /**
+ * Adds n days to the time delta.
+ *
+ * @param n
+ * n
+ * @return this HumanTime object
+ */
+ public HumanTime d(int n) {
+ delta += DAY * Math.abs(n);
+ return this;
+ }
+
+ /**
+ * Adds one hour to the time delta.
+ *
+ * @return this HumanTime object
+ */
+ public HumanTime h() {
+ return h(1);
+ }
+
+ /**
+ * Adds n hours to the time delta.
+ *
+ * @param n
+ * n
+ * @return this HumanTime object
+ */
+ public HumanTime h(int n) {
+ delta += HOUR * Math.abs(n);
+ return this;
+ }
+
+ /**
+ * Adds one month to the time delta.
+ *
+ * @return this HumanTime object
+ */
+ public HumanTime m() {
+ return m(1);
+ }
+
+ /**
+ * Adds n months to the time delta.
+ *
+ * @param n
+ * n
+ * @return this HumanTime object
+ */
+ public HumanTime m(int n) {
+ delta += MINUTE * Math.abs(n);
+ return this;
+ }
+
+ /**
+ * Adds one second to the time delta.
+ *
+ * @return this HumanTime object
+ */
+ public HumanTime s() {
+ return s(1);
+ }
+
+ /**
+ * Adds n seconds to the time delta.
+ *
+ * @param n
+ * seconds
+ * @return this HumanTime object
+ */
+ public HumanTime s(int n) {
+ delta += SECOND * Math.abs(n);
+ return this;
+ }
+
+ /**
+ * Adds one millisecond to the time delta.
+ *
+ * @return this HumanTime object
+ */
+ public HumanTime ms() {
+ return ms(1);
+ }
+
+ /**
+ * Adds n milliseconds to the time delta.
+ *
+ * @param n
+ * n
+ * @return this HumanTime object
+ */
+ public HumanTime ms(int n) {
+ delta += Math.abs(n);
+ return this;
+ }
+
+ /**
+ * Returns a human-formatted representation of the time delta.
+ *
+ * @return a formatted representation of the time delta, never null
+ */
+ public String getExactly() {
+ return getExactly(new StringBuilder()).toString();
+ }
+
+ /**
+ * Appends a human-formatted representation of the time delta to the given {@link Appendable} object.
+ *
+ * @param
+ * the return type
+ * @param a
+ * the Appendable object, may not be null
+ * @return the given Appendable object, never null
+ */
+ public T getExactly(T a) {
+ try {
+ boolean prependBlank = false;
+ long d = delta;
+ if (d >= YEAR) {
+ a.append(floor(d, YEAR));
+ a.append(' ');
+ a.append('y');
+ prependBlank = true;
+ }
+ d %= YEAR;
+ if (d >= DAY) {
+ if (prependBlank) {
+ a.append(' ');
+ }
+ a.append(floor(d, DAY));
+ a.append(' ');
+ a.append('d');
+ prependBlank = true;
+ }
+ d %= DAY;
+ if (d >= HOUR) {
+ if (prependBlank) {
+ a.append(' ');
+ }
+ a.append(floor(d, HOUR));
+ a.append(' ');
+ a.append('h');
+ prependBlank = true;
+ }
+ d %= HOUR;
+ if (d >= MINUTE) {
+ if (prependBlank) {
+ a.append(' ');
+ }
+ a.append(floor(d, MINUTE));
+ a.append(' ');
+ a.append('m');
+ prependBlank = true;
+ }
+ d %= MINUTE;
+ if (d >= SECOND) {
+ if (prependBlank) {
+ a.append(' ');
+ }
+ a.append(floor(d, SECOND));
+ a.append(' ');
+ a.append('s');
+ prependBlank = true;
+ }
+ d %= SECOND;
+ if (d > 0) {
+ if (prependBlank) {
+ a.append(' ');
+ }
+ a.append(Integer.toString((int) d));
+ a.append(' ');
+ a.append('m');
+ a.append('s');
+ }
+ } catch (IOException ex) {
+ // What were they thinking...
+ }
+ return a;
+ }
+
+ /**
+ * Returns an approximate, human-formatted representation of the time delta.
+ *
+ * @return a formatted representation of the time delta, never null
+ */
+ public String getApproximately() {
+ return getApproximately(new StringBuilder()).toString();
+ }
+
+ /**
+ * Appends an approximate, human-formatted representation of the time delta to the given {@link Appendable} object.
+ *
+ * @param
+ * the return type
+ * @param a
+ * the Appendable object, may not be null
+ * @return the given Appendable object, never null
+ */
+ public T getApproximately(T a) {
+
+ try {
+ int parts = 0;
+ boolean rounded = false;
+ boolean prependBlank = false;
+ long d = delta;
+ long mod = d % YEAR;
+
+ if (mod >= upperCeiling(YEAR)) {
+ a.append(ceil(d, YEAR));
+ a.append(' ');
+ a.append('y');
+ ++parts;
+ rounded = true;
+ prependBlank = true;
+ } else if (d >= YEAR) {
+ a.append(floor(d, YEAR));
+ a.append(' ');
+ a.append('y');
+ ++parts;
+ rounded = mod <= lowerCeiling(YEAR);
+ prependBlank = true;
+ }
+
+ if (!rounded) {
+ d %= YEAR;
+ mod = d % DAY;
+
+ if (mod >= upperCeiling(DAY)) {
+ if (prependBlank) {
+ a.append(' ');
+ }
+ a.append(ceil(d, DAY));
+ a.append(' ');
+ a.append('d');
+ ++parts;
+ rounded = true;
+ prependBlank = true;
+ } else if (d >= DAY) {
+ if (prependBlank) {
+ a.append(' ');
+ }
+ a.append(floor(d, DAY));
+ a.append(' ');
+ a.append('d');
+ ++parts;
+ rounded = mod <= lowerCeiling(DAY);
+ prependBlank = true;
+ }
+
+ if (parts < 2) {
+ d %= DAY;
+ mod = d % HOUR;
+
+ if (mod >= upperCeiling(HOUR)) {
+ if (prependBlank) {
+ a.append(' ');
+ }
+ a.append(ceil(d, HOUR));
+ a.append(' ');
+ a.append('h');
+ ++parts;
+ rounded = true;
+ prependBlank = true;
+ } else if (d >= HOUR && !rounded) {
+ if (prependBlank) {
+ a.append(' ');
+ }
+ a.append(floor(d, HOUR));
+ a.append(' ');
+ a.append('h');
+ ++parts;
+ rounded = mod <= lowerCeiling(HOUR);
+ prependBlank = true;
+ }
+
+ if (parts < 2) {
+ d %= HOUR;
+ mod = d % MINUTE;
+
+ if (mod >= upperCeiling(MINUTE)) {
+ if (prependBlank) {
+ a.append(' ');
+ }
+ a.append(ceil(d, MINUTE));
+ a.append(' ');
+ a.append('m');
+ ++parts;
+ rounded = true;
+ prependBlank = true;
+ } else if (d >= MINUTE && !rounded) {
+ if (prependBlank) {
+ a.append(' ');
+ }
+ a.append(floor(d, MINUTE));
+ a.append(' ');
+ a.append('m');
+ ++parts;
+ rounded = mod <= lowerCeiling(MINUTE);
+ prependBlank = true;
+ }
+
+ if (parts < 2) {
+ d %= MINUTE;
+ mod = d % SECOND;
+
+ if (mod >= upperCeiling(SECOND)) {
+ if (prependBlank) {
+ a.append(' ');
+ }
+ a.append(ceil(d, SECOND));
+ a.append(' ');
+ a.append('s');
+ ++parts;
+ rounded = true;
+ prependBlank = true;
+ } else if (d >= SECOND && !rounded) {
+ if (prependBlank) {
+ a.append(' ');
+ }
+ a.append(floor(d, SECOND));
+ a.append(' ');
+ a.append('s');
+ ++parts;
+ rounded = mod <= lowerCeiling(SECOND);
+ prependBlank = true;
+ }
+
+ if (parts < 2) {
+ d %= SECOND;
+
+ if (d > 0 && !rounded) {
+ if (prependBlank) {
+ a.append(' ');
+ }
+ a.append(Integer.toString((int) d));
+ a.append(' ');
+ a.append('m');
+ a.append('s');
+ }
+ }
+
+ }
+
+ }
+
+ }
+ }
+ } catch (IOException ex) {
+ // What were they thinking...
+ }
+
+ return a;
+ }
+
+ /**
+ * Returns the time delta.
+ *
+ * @return the time delta
+ */
+ public long getDelta() {
+ return delta;
+ }
+
+ /**
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof HumanTime)) {
+ return false;
+ }
+ return delta == ((HumanTime) obj).delta;
+ }
+
+ /**
+ * Returns a 32-bit representation of the time delta.
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return (int) (delta ^ (delta >> 32));
+ }
+
+ /**
+ * Returns a String representation of this.
+ *
+ * The output is identical to {@link #getExactly()}.
+ *
+ * @see java.lang.Object#toString()
+ * @see #getExactly()
+ * @return a String, never null
+ */
+ @Override
+ public String toString() {
+ return getExactly();
+ }
+
+ /**
+ * Compares this HumanTime to another HumanTime.
+ *
+ * @param t
+ * the other instance, may not be null
+ * @return which one is greater
+ */
+ @Override
+ public int compareTo(HumanTime t) {
+ return delta == t.delta ? 0 : (delta < t.delta ? -1 : 1);
+ }
+
+ /**
+ * Deep-clones this object.
+ *
+ * @see java.lang.Object#clone()
+ * @throws CloneNotSupportedException
+ */
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+ /**
+ * @see java.io.Externalizable#readExternal(java.io.ObjectInput)
+ */
+ @Override
+ public void readExternal(ObjectInput in) throws IOException {
+ delta = in.readLong();
+ }
+
+ /**
+ * @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
+ */
+ @Override
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeLong(delta);
+ }
+
+}
Index: modules/cnr-misc-utils/tags/cnr-misc-utils-1.0.5/src/main/java/eu/dnetlib/miscutils/functional/xml/ApplyXslt.java
===================================================================
--- modules/cnr-misc-utils/tags/cnr-misc-utils-1.0.5/src/main/java/eu/dnetlib/miscutils/functional/xml/ApplyXslt.java (nonexistent)
+++ modules/cnr-misc-utils/tags/cnr-misc-utils-1.0.5/src/main/java/eu/dnetlib/miscutils/functional/xml/ApplyXslt.java (revision 50644)
@@ -0,0 +1,60 @@
+package eu.dnetlib.miscutils.functional.xml;
+
+import java.io.StringReader;
+import java.util.Map;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+
+import org.springframework.core.io.Resource;
+
+/**
+ * Applies a stylesheet to a XML string and returns an XML string.
+ *
+ * @author marko
+ *
+ */
+public class ApplyXslt extends AbstractApplyXslt {
+
+ public ApplyXslt(Resource xslt) {
+ super(xslt);
+ }
+
+ public ApplyXslt(Source xslt, String name) {
+ super(xslt, name);
+ }
+
+ public ApplyXslt(Source xslt) {
+ super(xslt);
+ }
+
+ public ApplyXslt(String xslt, String name) {
+ super(xslt, name);
+ }
+
+ public ApplyXslt(String xslt) {
+ super(xslt);
+ }
+
+ public ApplyXslt(Resource xslt, Map parameters) {
+ super(xslt, parameters);
+ }
+
+ public ApplyXslt(Source xslt, String name, Map parameters) {
+ super(xslt, name, parameters);
+ }
+
+ public ApplyXslt(String xslt, String name, Map parameters) {
+ super(xslt, name, parameters);
+ }
+
+ @Override
+ public Source toStream(String input) {
+ return new StreamSource(new StringReader(input));
+ }
+
+ @Override
+ public String toString(String input) {
+ return input;
+ }
+}
Index: modules/cnr-misc-utils/tags/cnr-misc-utils-1.0.5/src/main/java/eu/dnetlib/miscutils/functional/xml/ApplyXsltDom.java
===================================================================
--- modules/cnr-misc-utils/tags/cnr-misc-utils-1.0.5/src/main/java/eu/dnetlib/miscutils/functional/xml/ApplyXsltDom.java (nonexistent)
+++ modules/cnr-misc-utils/tags/cnr-misc-utils-1.0.5/src/main/java/eu/dnetlib/miscutils/functional/xml/ApplyXsltDom.java (revision 50644)
@@ -0,0 +1,80 @@
+package eu.dnetlib.miscutils.functional.xml;
+
+import java.io.StringWriter;
+import java.util.Map;
+
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.springframework.core.io.Resource;
+import org.w3c.dom.Node;
+
+/**
+ * Applies a stylesheet to a XML DOM and returns an XML string.
+ *
+ * @author marko
+ *
+ */
+public class ApplyXsltDom extends AbstractApplyXslt {
+
+ public ApplyXsltDom(Resource xslt) {
+ super(xslt);
+ }
+
+ public ApplyXsltDom(Source xslt, String name) {
+ super(xslt, name);
+ }
+
+ public ApplyXsltDom(Source xslt) {
+ super(xslt);
+ }
+
+ public ApplyXsltDom(String xslt, String name) {
+ super(xslt, name);
+ }
+
+ public ApplyXsltDom(String xslt) {
+ super(xslt);
+ }
+
+ public ApplyXsltDom(Resource xslt, Map parameters) {
+ super(xslt, parameters);
+ }
+
+ public ApplyXsltDom(Source xslt, String name, Map parameters) {
+ super(xslt, name, parameters);
+ }
+
+ public ApplyXsltDom(String xslt, String name, Map parameters) {
+ super(xslt, name, parameters);
+ }
+
+ @Override
+ public Source toStream(Node input) {
+ return new DOMSource(input);
+ }
+
+ @Override
+ public String toString(Node input) {
+ return nodeToString(input);
+ }
+
+ private String nodeToString(Node node) {
+ StringWriter sw = new StringWriter();
+ try {
+ Transformer t = TransformerFactory.newInstance().newTransformer();
+ t.setOutputProperty(OutputKeys.INDENT, "yes");
+ t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+ t.transform(new DOMSource(node), new StreamResult(sw));
+ } catch (TransformerException te) {
+ System.out.println("nodeToString Transformer Exception");
+ }
+ return sw.toString();
+ }
+
+}
Index: modules/cnr-misc-utils/tags/cnr-misc-utils-1.0.5/src/main/java/eu/dnetlib/miscutils/collections/PositionalStringMapGenerator.java
===================================================================
--- modules/cnr-misc-utils/tags/cnr-misc-utils-1.0.5/src/main/java/eu/dnetlib/miscutils/collections/PositionalStringMapGenerator.java (nonexistent)
+++ modules/cnr-misc-utils/tags/cnr-misc-utils-1.0.5/src/main/java/eu/dnetlib/miscutils/collections/PositionalStringMapGenerator.java (revision 50644)
@@ -0,0 +1,78 @@
+package eu.dnetlib.miscutils.collections;
+
+import java.util.Map;
+
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * A special case of a PositionalMapGenerator, bound for String values. It provides automatic split which returns an
+ * iterable of maps.
+ *
+ * @author marko
+ *
+ * @param
+ * key
+ */
+public class PositionalStringMapGenerator extends PositionalMapGenerator {
+
+ /**
+ * Creates a new positional string map generator
+ *
+ * @param keys
+ */
+ public PositionalStringMapGenerator(final K... keys) {
+ super(keys);
+ }
+
+ /**
+ * Pass a list of strings and return a list of maps where each key has a value according to the position in the
+ * splitted array relative to the position of the key in the constructor.
+ *
+ * @param elements
+ * list of strings which will be splitted
+ * @param separator
+ * separator
+ * @return iterable of maps contained splitted values
+ */
+ public Iterable