diff --git a/dnet-core-components/pom.xml b/dnet-core-components/pom.xml new file mode 100644 index 0000000..c147c77 --- /dev/null +++ b/dnet-core-components/pom.xml @@ -0,0 +1,75 @@ + + + 4.0.0 + + eu.dnetlib + dnet-core + 1.0.0-SNAPSHOT + + dnet-core-components + eu.dnetlib + jar + 1.0.0-SNAPSHOT + + + + org.apache.commons + commons-lang3 + + + commons-codec + commons-codec + + + dom4j + dom4j + + + jaxen + jaxen + + + saxonica + saxon + + + saxonica + saxon-dom + + + jgrapht + jgrapht + + + net.sf.ehcache + ehcache + + + com.google.guava + guava + + + + + org.mockito + mockito-core + test + + + junit + junit + test + + + org.springframework + spring-test + false + + + commons-io + commons-io + test + + + + diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/cache/Cache.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/cache/Cache.java new file mode 100644 index 0000000..5648a3f --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/cache/Cache.java @@ -0,0 +1,39 @@ +package eu.dnetlib.miscutils.cache; + +import java.util.Map; +import java.util.Set; + +/** + * Generic strongly typed cache. + * + * @author marko + * + * @param + * key type + * @param + * value type + */ +@Deprecated +public interface Cache extends Map { + V put(K key, CacheElement element); + + CacheElement getElement(K key); + + /** + * Short verision of put(K key, CacheElement element) using default values for expiry time and other caching + * options. + * + * @param key + * key + * @param value + * value + */ + @Override + V put(K key, V value); + + @Override + V get(Object key); + + @Override + Set keySet(); +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/cache/CacheElement.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/cache/CacheElement.java new file mode 100644 index 0000000..86b75db --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/cache/CacheElement.java @@ -0,0 +1,73 @@ +package eu.dnetlib.miscutils.cache; + +/** + * A cache element encapsulates a value and a number of cache specific parameters like the expiration time. + * + * @author marko + * + * @param + * type of payload + */ +@Deprecated +public class CacheElement { + private T value; + private int timeToLive; + private int timeToIdle; + private long creationTime; + + /** + * reference to the underlying implementation specific element instance, for all other properties not exposed here. + */ + Object specificElement; + + CacheElement(final T value) { + this.value = value; + } + + CacheElement(final T value, final int timeToLive, final int timeToIdle) { + this.value = value; + this.timeToLive = timeToLive; + this.timeToIdle = timeToIdle; + } + + public T getValue() { + return value; + } + + public void setValue(final T value) { + this.value = value; + } + + public Integer getTimeToLive() { + return timeToLive; + } + + public void setTimeToLive(final Integer timeToLive) { + this.timeToLive = timeToLive; + } + + public Integer getTimeToIdle() { + return timeToIdle; + } + + public void setTimeToIdle(final Integer timeToIdle) { + this.timeToIdle = timeToIdle; + } + + public Object getSpecificElement() { + return specificElement; + } + + public void setSpecificElement(final Object specificElement) { + this.specificElement = specificElement; + } + + public long getCreationTime() { + return creationTime; + } + + public void setCreationTime(long creationTime) { + this.creationTime = creationTime; + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/cache/EhCache.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/cache/EhCache.java new file mode 100644 index 0000000..dadf271 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/cache/EhCache.java @@ -0,0 +1,178 @@ +package eu.dnetlib.miscutils.cache; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import net.sf.ehcache.Element; + +/** + * This is a wrapper to a EhCache instance exposed as a miscutils Cache object offering statically typed java Map-like + * behavior. + * + * @author marko + * + * @param + * @param + */ +@Deprecated +public class EhCache implements Cache { // NOPMD + public class MapEntry implements java.util.Map.Entry { + + transient K key; + + MapEntry(final K key) { + this.key = key; + } + + @Override + public K getKey() { + return key; + } + + @Override + public V getValue() { + return get(key); + } + + @Override + public V setValue(final V value) { + return put(key, value); + } + + } + + /** + * underlying cache implementation. + */ + private net.sf.ehcache.Cache cache; + + public EhCache() { + // no operation + } + + public EhCache(final net.sf.ehcache.Cache ehCache) { + basicSetCache(ehCache); + } + + /** + * {@inheritDoc} + * + * @see eu.dnetlib.miscutils.cache.Cache#get(java.lang.Object) Java is really strange. Map defines V + * get(Object), so we have to implement this method using Object otherwise the compiler signals a name clash. + */ + @Override + @SuppressWarnings("unchecked") + public V get(final Object key) { + final CacheElement element = getElement((K) key); + if (element == null) + return null; + return element.getValue(); + } + + @Override + @SuppressWarnings("unchecked") + public CacheElement getElement(final K key) { + final Element element = cache.get(key); + if (element == null) + return null; + + final CacheElement res = new CacheElement((V) element.getObjectValue()); + res.setTimeToLive(element.getTimeToLive()); + res.setTimeToLive(element.getTimeToIdle()); + res.setCreationTime(element.getCreationTime()); + res.setSpecificElement(element); + return res; + } + + @Override + public V put(final K key, final CacheElement element) { + final boolean eternal = element.getTimeToLive() == 0; + if (eternal) + cache.put(new Element(key, element.getValue(),eternal)); + else + cache.put(new Element(key, element.getValue(), element.getTimeToLive(), element.getTimeToIdle())); + return element.getValue(); + } + + @Override + public V put(final K key, final V value) { + return put(key, new CacheElement(value)); + } + + @Override + public void clear() { + cache.removeAll(); + } + + @Override + public boolean containsKey(final Object arg0) { + return cache.isKeyInCache(arg0); + } + + @Override + public boolean containsValue(final Object arg0) { + return cache.isValueInCache(arg0); + } + + @Override + public Set> entrySet() { + final Set> res = new HashSet>(); + for (K key : keySet()) + res.add(new MapEntry(key)); // NOPMD + return res; + } + + @Override + public boolean isEmpty() { + return size() == 0; + } + + @Override + @SuppressWarnings("unchecked") + public Set keySet() { + return new HashSet(cache.getKeys()); + } + + @Override + public void putAll(final Map arg0) { + for (java.util.Map.Entry entry : arg0.entrySet()) + put(entry.getKey(), entry.getValue()); + } + + @Override + public V remove(final Object arg0) { + final V val = get(arg0); + cache.remove(arg0); + return val; + } + + @Override + public int size() { + return cache.getSize(); + } + + @Override + public Collection values() { + final List res = new ArrayList(); + for (K key : keySet()) + res.add(get(key)); + return res; + } + + public net.sf.ehcache.Cache getCache() { + return cache; + } + + public void setCache(final net.sf.ehcache.Cache cache) { + basicSetCache(cache); + } + + private void basicSetCache(final net.sf.ehcache.Cache cache) { + this.cache = cache; + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/AffixCollection.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/AffixCollection.java new file mode 100644 index 0000000..09529be --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/AffixCollection.java @@ -0,0 +1,58 @@ +package eu.dnetlib.miscutils.collections; + +import java.util.Collection; + +import eu.dnetlib.miscutils.functional.UnaryFunction; + +/** + * This is a utility class which helps you append suffixes or prefixes to a collection of strings. + * + * @author marko + * + */ +public class AffixCollection extends MappedCollection { + + /** + * Position of the affix. + * + * @author marko + * + */ + enum Position { + /** + * prefix. + */ + PREFIX, + /** + * suffix. + */ + SUFFIX + } + + /** + * append a given suffix to every element of the input collection. + * + * @param coll + * @param suffix + */ + public AffixCollection(final Collection coll, final String suffix) { + this(coll, suffix, Position.SUFFIX); + } + + /** + * add a given affix to every element of the input collection, either as prefix or suffix. + * + * @param coll + * @param affix + * @param position + */ + public AffixCollection(final Collection coll, final String affix, final Position position) { + super(coll, new UnaryFunction() { + @Override + public String evaluate(String arg) { + return arg + affix; + } + }); + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/BloomFilter.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/BloomFilter.java new file mode 100644 index 0000000..538582f --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/BloomFilter.java @@ -0,0 +1,443 @@ +/** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package eu.dnetlib.miscutils.collections; + +import java.io.Serializable; +import java.nio.charset.Charset; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.BitSet; +import java.util.Collection; + +/** + * Implementation of a Bloom-filter, as described here: + * http://en.wikipedia.org/wiki/Bloom_filter + * + * For updates and bugfixes, see http://github.com/magnuss/java-bloomfilter + * + * Inspired by the SimpleBloomFilter-class written by Ian Clarke. This + * implementation provides a more evenly distributed Hash-function by + * using a proper digest instead of the Java RNG. Many of the changes + * were proposed in comments in his blog: + * http://blog.locut.us/2008/01/12/a-decent-stand-alone-java-bloom-filter-implementation/ + * + * @param Object type that is to be inserted into the Bloom filter, e.g. String or Integer. + * @author Magnus Skjegstad + */ +public class BloomFilter implements Serializable { + private static final long serialVersionUID = 1L; + private BitSet bitset; + private int bitSetSize; + private double bitsPerElement; + private int expectedNumberOfFilterElements; // expected (maximum) number of elements to be added + private int numberOfAddedElements; // number of elements actually added to the Bloom filter + private int k; // number of hash functions + + static final Charset charset = Charset.forName("UTF-8"); // encoding used for storing hash values as strings + + static final String hashName = "MD5"; // MD5 gives good enough accuracy in most circumstances. Change to SHA1 if it's needed + static final MessageDigest digestFunction; + static { // The digest method is reused between instances + MessageDigest tmp; + try { + tmp = java.security.MessageDigest.getInstance(hashName); + } catch (NoSuchAlgorithmException e) { + tmp = null; + } + digestFunction = tmp; + } + + /** + * Constructs an empty Bloom filter. The total length of the Bloom filter will be + * c*n. + * + * @param c is the number of bits used per element. + * @param n is the expected number of elements the filter will contain. + * @param k is the number of hash functions used. + */ + public BloomFilter(double c, int n, int k) { + this.expectedNumberOfFilterElements = n; + this.k = k; + this.bitsPerElement = c; + this.bitSetSize = (int) Math.ceil(c * n); + numberOfAddedElements = 0; + this.bitset = new BitSet(bitSetSize); + } + + /** + * Constructs an empty Bloom filter. The optimal number of hash functions (k) is estimated from the total size of the Bloom + * and the number of expected elements. + * + * @param bitSetSize defines how many bits should be used in total for the filter. + * @param expectedNumberOElements defines the maximum number of elements the filter is expected to contain. + */ + public BloomFilter(int bitSetSize, int expectedNumberOElements) { + this(bitSetSize / (double)expectedNumberOElements, + expectedNumberOElements, + (int) Math.round((bitSetSize / (double)expectedNumberOElements) * Math.log(2.0))); + } + + /** + * Constructs an empty Bloom filter with a given false positive probability. The number of bits per + * element and the number of hash functions is estimated + * to match the false positive probability. + * + * @param falsePositiveProbability is the desired false positive probability. + * @param expectedNumberOfElements is the expected number of elements in the Bloom filter. + */ + public BloomFilter(double falsePositiveProbability, int expectedNumberOfElements) { + this(Math.ceil(-(Math.log(falsePositiveProbability) / Math.log(2))) / Math.log(2), // c = k / ln(2) + expectedNumberOfElements, + (int)Math.ceil(-(Math.log(falsePositiveProbability) / Math.log(2)))); // k = ceil(-log_2(false prob.)) + } + + /** + * Construct a new Bloom filter based on existing Bloom filter data. + * + * @param bitSetSize defines how many bits should be used for the filter. + * @param expectedNumberOfFilterElements defines the maximum number of elements the filter is expected to contain. + * @param actualNumberOfFilterElements specifies how many elements have been inserted into the filterData BitSet. + * @param filterData a BitSet representing an existing Bloom filter. + */ + public BloomFilter(int bitSetSize, int expectedNumberOfFilterElements, int actualNumberOfFilterElements, BitSet filterData) { + this(bitSetSize, expectedNumberOfFilterElements); + this.bitset = filterData; + this.numberOfAddedElements = actualNumberOfFilterElements; + } + + /** + * Generates a digest based on the contents of a String. + * + * @param val specifies the input data. + * @param charset specifies the encoding of the input data. + * @return digest as long. + */ + public static int createHash(String val, Charset charset) { + return createHash(val.getBytes(charset)); + } + + /** + * Generates a digest based on the contents of a String. + * + * @param val specifies the input data. The encoding is expected to be UTF-8. + * @return digest as long. + */ + public static int createHash(String val) { + return createHash(val, charset); + } + + /** + * Generates a digest based on the contents of an array of bytes. + * + * @param data specifies input data. + * @return digest as long. + */ + public static int createHash(byte[] data) { + return createHashes(data, 1)[0]; + } + + /** + * Generates digests based on the contents of an array of bytes and splits the result into 4-byte int's and store them in an array. The + * digest function is called until the required number of int's are produced. For each call to digest a salt + * is prepended to the data. The salt is increased by 1 for each call. + * + * @param data specifies input data. + * @param hashes number of hashes/int's to produce. + * @return array of int-sized hashes + */ + public static int[] createHashes(byte[] data, int hashes) { + int[] result = new int[hashes]; + + int k = 0; + byte salt = 0; + while (k < hashes) { + byte[] digest; + synchronized (digestFunction) { + digestFunction.update(salt); + salt++; + digest = digestFunction.digest(data); + } + + for (int i = 0; i < digest.length/4 && k < hashes; i++) { + int h = 0; + for (int j = (i*4); j < (i*4)+4; j++) { + h <<= 8; + h |= ((int) digest[j]) & 0xFF; + } + result[k] = h; + k++; + } + } + return result; + } + + /** + * Compares the contents of two instances to see if they are equal. + * + * @param obj is the object to compare to. + * @return True if the contents of the objects are equal. + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + @SuppressWarnings("unchecked") + final BloomFilter other = (BloomFilter) obj; + if (this.expectedNumberOfFilterElements != other.expectedNumberOfFilterElements) { + return false; + } + if (this.k != other.k) { + return false; + } + if (this.bitSetSize != other.bitSetSize) { + return false; + } + if (this.bitset != other.bitset && (this.bitset == null || !this.bitset.equals(other.bitset))) { + return false; + } + return true; + } + + /** + * Calculates a hash code for this class. + * @return hash code representing the contents of an instance of this class. + */ + @Override + public int hashCode() { + int hash = 7; + hash = 61 * hash + (this.bitset != null ? this.bitset.hashCode() : 0); + hash = 61 * hash + this.expectedNumberOfFilterElements; + hash = 61 * hash + this.bitSetSize; + hash = 61 * hash + this.k; + return hash; + } + + + /** + * Calculates the expected probability of false positives based on + * the number of expected filter elements and the size of the Bloom filter. + *

+ * The value returned by this method is the expected rate of false + * positives, assuming the number of inserted elements equals the number of + * expected elements. If the number of elements in the Bloom filter is less + * than the expected value, the true probability of false positives will be lower. + * + * @return expected probability of false positives. + */ + public double expectedFalsePositiveProbability() { + return getFalsePositiveProbability(expectedNumberOfFilterElements); + } + + /** + * Calculate the probability of a false positive given the specified + * number of inserted elements. + * + * @param numberOfElements number of inserted elements. + * @return probability of a false positive. + */ + public double getFalsePositiveProbability(double numberOfElements) { + // (1 - e^(-k * n / m)) ^ k + return Math.pow((1 - Math.exp(-k * (double) numberOfElements + / (double) bitSetSize)), k); + + } + + /** + * Get the current probability of a false positive. The probability is calculated from + * the size of the Bloom filter and the current number of elements added to it. + * + * @return probability of false positives. + */ + public double getFalsePositiveProbability() { + return getFalsePositiveProbability(numberOfAddedElements); + } + + + /** + * Returns the value chosen for K.
+ *
+ * K is the optimal number of hash functions based on the size + * of the Bloom filter and the expected number of inserted elements. + * + * @return optimal k. + */ + public int getK() { + return k; + } + + /** + * Sets all bits to false in the Bloom filter. + */ + public void clear() { + bitset.clear(); + numberOfAddedElements = 0; + } + + /** + * Adds an object to the Bloom filter. The output from the object's + * toString() method is used as input to the hash functions. + * + * @param element is an element to register in the Bloom filter. + */ + public void add(E element) { + add(element.toString().getBytes(charset)); + } + + /** + * Adds an array of bytes to the Bloom filter. + * + * @param bytes array of bytes to add to the Bloom filter. + */ + public void add(byte[] bytes) { + int[] hashes = createHashes(bytes, k); + for (int hash : hashes) + bitset.set(Math.abs(hash % bitSetSize), true); + numberOfAddedElements ++; + } + + /** + * Adds all elements from a Collection to the Bloom filter. + * @param c Collection of elements. + */ + public void addAll(Collection c) { + for (E element : c) + add(element); + } + + /** + * Returns true if the element could have been inserted into the Bloom filter. + * Use getFalsePositiveProbability() to calculate the probability of this + * being correct. + * + * @param element element to check. + * @return true if the element could have been inserted into the Bloom filter. + */ + public boolean contains(E element) { + return contains(element.toString().getBytes(charset)); + } + + /** + * Returns true if the array of bytes could have been inserted into the Bloom filter. + * Use getFalsePositiveProbability() to calculate the probability of this + * being correct. + * + * @param bytes array of bytes to check. + * @return true if the array could have been inserted into the Bloom filter. + */ + public boolean contains(byte[] bytes) { + int[] hashes = createHashes(bytes, k); + for (int hash : hashes) { + if (!bitset.get(Math.abs(hash % bitSetSize))) { + return false; + } + } + return true; + } + + /** + * Returns true if all the elements of a Collection could have been inserted + * into the Bloom filter. Use getFalsePositiveProbability() to calculate the + * probability of this being correct. + * @param c elements to check. + * @return true if all the elements in c could have been inserted into the Bloom filter. + */ + public boolean containsAll(Collection c) { + for (E element : c) + if (!contains(element)) + return false; + return true; + } + + /** + * Read a single bit from the Bloom filter. + * @param bit the bit to read. + * @return true if the bit is set, false if it is not. + */ + public boolean getBit(int bit) { + return bitset.get(bit); + } + + /** + * Set a single bit in the Bloom filter. + * @param bit is the bit to set. + * @param value If true, the bit is set. If false, the bit is cleared. + */ + public void setBit(int bit, boolean value) { + bitset.set(bit, value); + } + + /** + * Return the bit set used to store the Bloom filter. + * @return bit set representing the Bloom filter. + */ + public BitSet getBitSet() { + return bitset; + } + + /** + * Returns the number of bits in the Bloom filter. Use count() to retrieve + * the number of inserted elements. + * + * @return the size of the bitset used by the Bloom filter. + */ + public int size() { + return this.bitSetSize; + } + + /** + * Returns the number of elements added to the Bloom filter after it + * was constructed or after clear() was called. + * + * @return number of elements added to the Bloom filter. + */ + public int count() { + return this.numberOfAddedElements; + } + + /** + * Returns the expected number of elements to be inserted into the filter. + * This value is the same value as the one passed to the constructor. + * + * @return expected number of elements. + */ + public int getExpectedNumberOfElements() { + return expectedNumberOfFilterElements; + } + + /** + * Get expected number of bits per element when the Bloom filter is full. This value is set by the constructor + * when the Bloom filter is created. See also getBitsPerElement(). + * + * @return expected number of bits per element. + */ + public double getExpectedBitsPerElement() { + return this.bitsPerElement; + } + + /** + * Get actual number of bits per element based on the number of elements that have currently been inserted and the length + * of the Bloom filter. See also getExpectedBitsPerElement(). + * + * @return number of bits per element. + */ + public double getBitsPerElement() { + return this.bitSetSize / (double)numberOfAddedElements; + } +} \ No newline at end of file diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/EnsureCollection.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/EnsureCollection.java new file mode 100644 index 0000000..748a0da --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/EnsureCollection.java @@ -0,0 +1,48 @@ +package eu.dnetlib.miscutils.collections; + +import java.util.List; + +import com.google.common.collect.Lists; + +/** + * Utility class which checks ensures that a given collection is not null. + * + *

+ * CXF for example cannot distinguish from nulls. This helper allows you write: + *

+ * + *
+ * for(String bla : EnsureCollection.list(somecode())) {....}
+ * 
+ * + * @author marko + * + */ +public class EnsureCollection { + + /** + * returns the argument or a new list if the argument is null. + * + * @param a type + * @param aList a list + * @return passthrough or empty list + */ + public static List list(final List aList) { + if (aList == null) + return Lists.newArrayList(); + return aList; + } + + + /** + * Alias for static imports. + * + * @param a type + * @param aList a list + * @return passthrough or empty list + */ + public static List notNullList(final List aList) { + return list(aList); + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/Filter.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/Filter.java new file mode 100644 index 0000000..f0e6cf9 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/Filter.java @@ -0,0 +1,6 @@ +package eu.dnetlib.miscutils.collections; + +import eu.dnetlib.miscutils.functional.UnaryFunction; + +public interface Filter extends UnaryFunction { +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/FilteredCollection.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/FilteredCollection.java new file mode 100644 index 0000000..967aa98 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/FilteredCollection.java @@ -0,0 +1,119 @@ +package eu.dnetlib.miscutils.collections; + +import java.util.*; + +import com.google.common.collect.Lists; + +import eu.dnetlib.miscutils.functional.UnaryFunction; + +public class FilteredCollection implements Iterable { + final transient private Iterable coll; + transient UnaryFunction filter; + + class FilterIterator implements Iterator { + final transient private Iterator iter; + + transient T nextElement; + + public FilterIterator() { + this.iter = coll.iterator(); + scanNext(); + } + + private void scanNext() { + while (iter.hasNext()) { + final T element = iter.next(); + if (filter.evaluate(element)) { + nextElement = element; + return; + } + } + nextElement = null; // NOPMD + } + + @Override + public boolean hasNext() { + return nextElement != null; + } + + @Override + public T next() { + final T res = nextElement; + scanNext(); + return res; + } + + @Override + public void remove() { + // no operation + } + } + + /** + * Static helper function, makes usage shorter. + * + * @param + * @param coll + * @param filter + * @return + */ + public static Iterable filter(final Iterable coll, final UnaryFunction filter) { + return new FilteredCollection(coll, filter); + } + + public static Iterable filter(final X[] coll, final UnaryFunction filter) { + return new FilteredCollection(coll, filter); + } + + /** + * Static helper function, makes common usage shorter. + * + * @param + * @param + * @param coll + * @param mapper + * @return + */ + public static List listFilter(final Iterable coll, final UnaryFunction filter) { + return Lists.newArrayList(filter(coll, filter)); + } + + public static List listFilter(final X[] coll, final UnaryFunction filter) { + return Lists.newArrayList(filter(coll, filter)); + } + + public FilteredCollection(final Collection coll, final UnaryFunction filter) { + this.coll = coll; + this.filter = filter; + } + + public FilteredCollection(final Iterable coll, final UnaryFunction filter) { + this.coll = coll; + this.filter = filter; + } + + public FilteredCollection(final T[] coll, final UnaryFunction filter) { + this.coll = Lists.newArrayList(coll); + this.filter = filter; + } + + + @Override + public Iterator iterator() { + return new FilterIterator(); + } + + public static void main(final String[] args) { + final List list = new ArrayList(); + list.add("ciao"); + list.add(2); + list.add("bubu"); + + final TypeFilteredCollection filtered = new TypeFilteredCollection(list, String.class); + + for (final String el : filtered) + System.out.println("element: " + el); // NOPMD + + System.out.println("ok"); // NOPMD + } +} \ No newline at end of file diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/MappedCollection.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/MappedCollection.java new file mode 100644 index 0000000..6049bb9 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/MappedCollection.java @@ -0,0 +1,109 @@ +/** + * + */ +package eu.dnetlib.miscutils.collections; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import com.google.common.collect.Lists; + +import eu.dnetlib.miscutils.functional.UnaryFunction; + +/** + * @author marko + * + */ +public class MappedCollection implements Iterable { + private transient final Iterable coll; + private transient final UnaryFunction mapper; + + /** + * Static helper function, makes usage shorter. + * + * @param + * @param coll + * @param filter + * @return + */ + public static Iterable map(final Iterable coll, final UnaryFunction mapper) { + return new MappedCollection(coll, mapper); + } + + public static Iterable map(final Y[] coll, final UnaryFunction mapper) { + return new MappedCollection(coll, mapper); + } + + /** + * Static helper function, makes common usage shorter. + * + * @param + * @param + * @param coll + * @param mapper + * @return + */ + public static List listMap(final Iterable coll, final UnaryFunction mapper) { + return Lists.newArrayList(map(coll, mapper)); + } + + public static List listMap(final Y[] coll, final UnaryFunction mapper) { + return Lists.newArrayList(map(coll, mapper)); + } + + /** + * Compatibility with pre 0.0.3 cnr-misc-utils. + * + * @param coll + * @param mapper + */ + public MappedCollection(final Collection coll, final UnaryFunction mapper) { + this.coll = coll; + this.mapper = mapper; + } + + public MappedCollection(final Iterable coll, final UnaryFunction mapper) { + this.coll = coll; + this.mapper = mapper; + } + + public MappedCollection(final K[] coll, final UnaryFunction mapper) { + this.coll = Lists.newArrayList(coll); + this.mapper = mapper; + } + + class MappedIterator implements Iterator { + private transient final Iterator iter; + + public MappedIterator() { + this.iter = coll.iterator(); + } + + @Override + public T next() { + return mapper.evaluate(iter.next()); + } + + @Override + public boolean hasNext() { + return iter.hasNext(); + } + + @Override + public void remove() { + iter.remove(); + } + } + + /* + * (non-Javadoc) + * + * @see java.lang.Iterable#iterator() + */ + @Override + public Iterator iterator() { + return new MappedIterator(); + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/Pair.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/Pair.java new file mode 100644 index 0000000..03c98b6 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/Pair.java @@ -0,0 +1,30 @@ +package eu.dnetlib.miscutils.collections; + +public class Pair { + + private K k; + + private V v; + + public Pair(K k, V v) { + this.k = k; + this.v = v; + } + + public K getKey() { + return k; + } + + public V getValue() { + return v; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Pair) { + Pair tmp = (Pair) obj; + return k.equals(tmp.getKey()) && v.equals(tmp.getValue()); + } else return false; + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/PositionalMapGenerator.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/PositionalMapGenerator.java new file mode 100644 index 0000000..2537eb2 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/PositionalMapGenerator.java @@ -0,0 +1,73 @@ +package eu.dnetlib.miscutils.collections; + +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + + + +/** + * Helper for creating a named key/value pairs out of a String.split output. + * + * @author luca.santocono + * + * @param + * key type + * @param + * value type + */ +public class PositionalMapGenerator { + + /** + * keys in positional order. + */ + private final K[] keys; + + /** + * positional keys declaration + * + * @param keys + * keys + */ + public PositionalMapGenerator( final K... keys) { + this.keys = keys; + } + + /** + * Positionally map the input array with the configured keys. + * + * @param values + * value array + * @return map containing value array mapped with keys + */ + public Map asMap(final V[] values) { + final Map stringMap = new HashMap(); + for (int i = 0; i < values.length; i++) + stringMap.put(keys[i], values[i]); + return stringMap; + } + + @SuppressWarnings("unchecked") + public X construct(final Class clazz, final Class clavv, final V[] values) { + Class[] params = new Class[values.length]; + Arrays.fill(params, clavv); + + try { + return clazz.getDeclaredConstructor(params).newInstance(values); + } catch (IllegalArgumentException e) { + throw new IllegalStateException(e); + } catch (InstantiationException e) { + throw new IllegalStateException(e); + } catch (IllegalAccessException e) { + throw new IllegalStateException(e); + } catch (InvocationTargetException e) { + throw new IllegalStateException(e); + } catch (SecurityException e) { + throw new IllegalStateException(e); + } catch (NoSuchMethodException e) { + throw new IllegalStateException(e); + } + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/PositionalStringMapGenerator.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/PositionalStringMapGenerator.java new file mode 100644 index 0000000..71bb729 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/PositionalStringMapGenerator.java @@ -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> split(Iterable elements, final String separator) { + + return new MappedCollection, String>(elements, new UnaryFunction, String>() { + + @Override + public Map evaluate(String value) { + return asMap(value.split(separator)); + } + }); + + } + + /** + * Pass a list of strings and return a list of objects constructed by passing the splitted string values to the + * constructor of the new object. + * + *

+ * This method doesn't need to setup a list of key names in the constructor + *

+ * + * @param + * some class + * @param clazz + * some class + * @param elements + * list of strings to split + * @param separator + * separator + * @return iterable of instances of some class constructed with splitted values + */ + public Iterable split(final Class clazz, Iterable elements, final String separator) { + + return new MappedCollection(elements, new UnaryFunction() { + + @Override + public X evaluate(String value) { + return construct(clazz, String.class, value.split(separator)); + } + }); + + } +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/TypeFilter.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/TypeFilter.java new file mode 100644 index 0000000..984e926 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/TypeFilter.java @@ -0,0 +1,14 @@ +package eu.dnetlib.miscutils.collections; + +public class TypeFilter implements Filter { + transient final Class cls; + + public TypeFilter(final Class cls) { + this.cls = cls; + } + + @Override + public Boolean evaluate(final T element) { + return (cls.isInstance(element)); + } +} \ No newline at end of file diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/TypeFilteredCollection.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/TypeFilteredCollection.java new file mode 100644 index 0000000..b35f122 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/collections/TypeFilteredCollection.java @@ -0,0 +1,21 @@ +package eu.dnetlib.miscutils.collections; + +import java.util.Collection; +import java.util.Iterator; + +public class TypeFilteredCollection implements Iterable { + private transient final Collection coll; + private transient final Class cls; + + public TypeFilteredCollection(final Collection coll, final Class cls) { + this.coll = coll; + this.cls = cls; + } + + @Override + @SuppressWarnings("unchecked") + public Iterator iterator() { + final Filter filter = new TypeFilter(cls); + return (Iterator) (new FilteredCollection(coll, filter)).iterator(); + } +} \ No newline at end of file diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/coupling/ExternalCondition.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/coupling/ExternalCondition.java new file mode 100644 index 0000000..0e41f48 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/coupling/ExternalCondition.java @@ -0,0 +1,18 @@ +package eu.dnetlib.miscutils.coupling; + +/** + * In many occasions one component wants to disable some other component or some functionalty of another component + * but it's not advisable to couple these components too tightly. This class offers an abstraction to the concept of "Condition", + * where a component can parameterize it's behavior according to some external condition, which can be driven by another component. + * + * @author marko + * + */ +public interface ExternalCondition { + /** + * true if true. + * + * @return true if true + */ + boolean isTrue(); +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/coupling/StaticCondition.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/coupling/StaticCondition.java new file mode 100644 index 0000000..ad669a5 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/coupling/StaticCondition.java @@ -0,0 +1,33 @@ +package eu.dnetlib.miscutils.coupling; + +/** + * Simple implementation of an ExternalCondition object, where a condition provider has directly control to the global condition. + * + * @author marko + * + */ +public class StaticCondition implements ExternalCondition { + + /** + * condition provider can set this field. + */ + boolean condition; + + /** + * {@inheritDoc} + * @see eu.dnetlib.miscutils.coupling.ExternalCondition#isTrue() + */ + @Override + public synchronized boolean isTrue() { + return isCondition(); + } + + public synchronized boolean isCondition() { + return condition; + } + + public synchronized void setCondition(boolean condition) { + this.condition = condition; + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/datetime/DateUtils.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/datetime/DateUtils.java new file mode 100644 index 0000000..25f502a --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/datetime/DateUtils.java @@ -0,0 +1,109 @@ +package eu.dnetlib.miscutils.datetime; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +/** + * various date utilities. + * + * @author michele + * + */ +public class DateUtils { + + private static final SimpleDateFormat ISO8601FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US); + + private transient final Date date; + + public DateUtils() { + this.date = new Date(); + } + + public DateUtils(final Date date) { + this.date = (Date) date.clone(); + } + + public String getDateAsISO8601String() { + String result; + synchronized (ISO8601FORMAT) { + result = ISO8601FORMAT.format(this.date); + } + + //convert YYYYMMDDTHH:mm:ss+HH00 into YYYYMMDDTHH:mm:ss+HH:00 + //- note the added colon for the Timezone + return result.substring(0, result.length() - 2) + ":" + result.substring(result.length() - 2); + } + + public Long getPrecisionTime() { + return this.date.getTime(); + } + + public static long now() { + return new Date().getTime(); + } + + public static String now_ISO8601() { // NOPMD + String result; + synchronized (ISO8601FORMAT) { + result = ISO8601FORMAT.format(new Date()); + } + //convert YYYYMMDDTHH:mm:ss+HH00 into YYYYMMDDTHH:mm:ss+HH:00 + //- note the added colon for the Timezone + return result.substring(0, result.length() - 2) + ":" + result.substring(result.length() - 2); + } + + /** + * parses a iso8601 date into a date. + * + * @param date + * string iso8601 date + * @return date object + */ + public Date parse(final String dateArg) { + String date = dateArg; + + if ("".equals(date)) + return null; + + try { + if (date.endsWith("Z")) { + date = date.replace("Z", "+0000"); + } else if (date.length() < 20) { + date += "+0000"; // NOPMD + } else { + final String end = date.substring(date.length() - 3); + date = date.substring(0, date.length() - 3) + end.replace(":", ""); + } + + synchronized (ISO8601FORMAT) { + return ISO8601FORMAT.parse(date); + } + } catch (ParseException e) { + throw new IllegalStateException("invalid iso8601 date '" + dateArg + "' (even after normalizing it to '" + date + "')"); + } + } + + public static String calculate_ISO8601(long l) { + String result = ISO8601FORMAT.format(new Date(l)); + // convert YYYYMMDDTHH:mm:ss+HH00 into YYYYMMDDTHH:mm:ss+HH:00 + //- note the added colon for the Timezone + result = result.substring(0, result.length() - 2) + ":" + result.substring(result.length() - 2); + return result; + } + + /** + * Extracts the duration part of a ISO8601 formatted date. Duration part is the part after the 'T'. + * + * @param dateArg + * @return + */ + public String getDuration(final String dateArg) { + String[] splitted = dateArg.split("T"); + if (splitted.length == 1) + return "0"; + else + return splitted[1]; + } +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/datetime/HumanTime.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/datetime/HumanTime.java new file mode 100644 index 0000000..70a11dc --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/datetime/HumanTime.java @@ -0,0 +1,804 @@ +package eu.dnetlib.miscutils.datetime; + +/* + * HumanTime.java + * + * Created on 06.10.2008 + * + * Copyright (c) 2008 Johann Burkard () + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Iterator; + +/** + * HumanTime parses and formats time deltas for easier reading by humans. It can format time information without losing + * information but its main purpose is to generate more easily understood approximations.

Using HumanTime

+ *

+ * Use HumanTime by creating an instance that contains the time delta ({@link HumanTime#HumanTime(long)}), create an + * empty instance through ({@link HumanTime#HumanTime()}) and set the delta using the {@link #y()}, {@link #d()}, + * {@link #h()}, {@link #s()} and {@link #ms()} methods or parse a {@link CharSequence} representation ( + * {@link #eval(CharSequence)}). Parsing ignores whitespace and is case insensitive. + *

+ *

HumanTime format

+ *

+ * HumanTime will format time deltas in years ("y"), days ("d"), hours ("h"), minutes ("m"), seconds ("s") and + * milliseconds ("ms"), separated by a blank character. For approximate representations, the time delta will be round up + * or down if necessary. + *

+ *

HumanTime examples

+ *
    + *
  • HumanTime.eval("1 d 1d 2m 3m").getExactly() = "2 d 5 m"
  • + *
  • HumanTime.eval("2m8d2h4m").getExactly() = "8 d 2 h 6 m"
  • + *
  • HumanTime.approximately("2 d 8 h 20 m 50 s") = "2 d 8 h"
  • + *
  • HumanTime.approximately("55m") = "1 h"
  • + *
+ *

Implementation details

+ *
    + *
  • The time delta can only be increased.
  • + *
  • Instances of this class are thread safe.
  • + *
  • Getters using the Java Beans naming conventions are provided for use in environments like JSP or with expression + * languages like OGNL. See {@link #getApproximately()} and {@link #getExactly()}.
  • + *
  • To keep things simple, a year consists of 365 days.
  • + *
+ * + * @author Johann Burkard + * @version $Id: HumanTime.java 323 2008-10-08 19:06:22Z Johann $ + * @see #eval(CharSequence) + * @see #approximately(CharSequence) + * @see Date + * Formatting and Parsing for Humans in Java with HumanTime + */ +public class HumanTime implements Externalizable, Comparable, Cloneable { + + /** + * The serial version UID. + */ + private static final long serialVersionUID = 5179328390732826722L; + + /** + * One second. + */ + private static final long SECOND = 1000; + + /** + * One minute. + */ + private static final long MINUTE = SECOND * 60; + + /** + * One hour. + */ + private static final long HOUR = MINUTE * 60; + + /** + * One day. + */ + private static final long DAY = HOUR * 24; + + /** + * One year. + */ + private static final long YEAR = DAY * 365; + + /** + * Percentage of what is round up or down. + */ + private static final int CEILING_PERCENTAGE = 15; + + /** + * Parsing state. + */ + static enum State { + + NUMBER, IGNORED, UNIT + + } + + static State getState(char c) { + State out; + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + out = State.NUMBER; + break; + case 's': + case 'm': + case 'h': + case 'd': + case 'y': + case 'S': + case 'M': + case 'H': + case 'D': + case 'Y': + out = State.UNIT; + break; + default: + out = State.IGNORED; + } + return out; + } + + /** + * Parses a {@link CharSequence} argument and returns a {@link HumanTime} instance. + * + * @param s + * the char sequence, may not be null + * @return an instance, never null + */ + public static HumanTime eval(final CharSequence s) { + HumanTime out = new HumanTime(0L); + + int num = 0; + + int start = 0; + int end = 0; + + State oldState = State.IGNORED; + + for (char c : new Iterable() { + + /** + * @see java.lang.Iterable#iterator() + */ + @Override + public Iterator iterator() { + return new Iterator() { + + 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); + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/dom4j/XPathHelper.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/dom4j/XPathHelper.java new file mode 100644 index 0000000..107f166 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/dom4j/XPathHelper.java @@ -0,0 +1,50 @@ +package eu.dnetlib.miscutils.dom4j; // NOPMD + +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; + +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.Node; +import org.dom4j.io.SAXReader; + +import eu.dnetlib.miscutils.collections.TypeFilteredCollection; + +/** + * This class allows to avoid casts and unnecessary suppress warnings statements which would be necessary when using the dom4j API. + * + * @author marko + * + */ +public class XPathHelper { + public static Iterable selectElements(final Node base, final String xpath) { + @SuppressWarnings("unchecked") + final List children = base.selectNodes(xpath); + return new TypeFilteredCollection(children, Element.class); + } + + public static Iterable selectElements(final String base, final String xpath) { + Document document; + try { + document = new SAXReader().read(new StringReader(base)); + return selectElements(document, xpath); + } catch (DocumentException e) { + return new ArrayList(); + } + } + + public static Element selectElement(final Node base, final String xpath) { + for (Element el : selectElements(base, xpath)) + return el; + return null; + } + + public static Element selectElement(final String base, final String xpath) { + for (Element el : selectElements(base, xpath)) + return el; + return null; + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/factory/Factory.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/factory/Factory.java new file mode 100644 index 0000000..f2be086 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/factory/Factory.java @@ -0,0 +1,17 @@ +package eu.dnetlib.miscutils.factory; + +/** + * Provides a common interface for factory objects. + * + * @author marko + * + * @param + */ +public interface Factory { + /** + * returns a new instance. + * + * @return + */ + T newInstance(); +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/CompositeUnaryFunction.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/CompositeUnaryFunction.java new file mode 100644 index 0000000..45461cb --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/CompositeUnaryFunction.java @@ -0,0 +1,38 @@ +package eu.dnetlib.miscutils.functional; + +public class CompositeUnaryFunction implements UnaryFunction { + + protected transient UnaryFunction function; + + public CompositeUnaryFunction(final UnaryFunction function) { + this.function = function; + } + + class UnaryHelper extends CompositeUnaryFunction { + + private transient final UnaryFunction comp; + private transient final UnaryFunction base; + + public UnaryHelper(final UnaryFunction base, final UnaryFunction comp) { + super(null); + + this.comp = comp; + this.base = base; + } + + @Override + public T evaluate(final X arg) { + return base.evaluate(comp.evaluate(arg)); + } + } + + public CompositeUnaryFunction of(UnaryFunction comp) { // NOPMD + return new UnaryHelper(this, comp); + } + + @Override + public T evaluate(final K arg) { + return function.evaluate(arg); + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/Functional.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/Functional.java new file mode 100644 index 0000000..f09d574 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/Functional.java @@ -0,0 +1,34 @@ +package eu.dnetlib.miscutils.functional; + +import java.lang.reflect.Constructor; + +/** + * Functional helpers. + * + * @author marko + * + */ +public class Functional { + /** + * Given a class and a constructor type, return a unary function which invokes the constructor of that class. + * + * @param + * @param + * @param clazz + * @param argumentType + * @return + */ + static public UnaryFunction construct(final Class clazz, final Class argumentType) { + return new UnaryFunction() { + @Override + public A evaluate(final B arg) { + try { + final Constructor constructor = clazz.getConstructor(new Class[] { argumentType }); + return constructor.newInstance(arg); + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + } + }; + } +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/IdentityFunction.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/IdentityFunction.java new file mode 100644 index 0000000..350393b --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/IdentityFunction.java @@ -0,0 +1,22 @@ +package eu.dnetlib.miscutils.functional; + +/** + * Identity function + * + * @author marko + * + * @param + */ +public class IdentityFunction implements UnaryFunction { + + /** + * {@inheritDoc} + * + * @see eu.dnetlib.miscutils.functional.UnaryFunction#evaluate(java.lang.Object) + */ + @Override + public T evaluate(final T arg) { + return arg; + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/ThreadSafeUnaryFunction.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/ThreadSafeUnaryFunction.java new file mode 100644 index 0000000..073eab2 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/ThreadSafeUnaryFunction.java @@ -0,0 +1,52 @@ +package eu.dnetlib.miscutils.functional; + +import eu.dnetlib.miscutils.factory.Factory; + + +/** + * ThreadSafeUnaryFunction maintains a ThreadLocal of a UnaryFunction and + * delegates the application to the thread local function. + * + * @author claudio + * + * @param + * @param + */ +public class ThreadSafeUnaryFunction implements UnaryFunction { + + /** + * ThreadLocal UnaryFunction + */ + private ThreadLocal> localFunction; + + /** + * Builds a new ThreadSafeUnaryFunction. + * @param localFunction + */ + public ThreadSafeUnaryFunction(ThreadLocal> localFunction) { + super(); + this.localFunction = localFunction; + } + + /** + * Builds a new ThreadSafeUnaryFunction. + * @param localFunction + */ + public ThreadSafeUnaryFunction(final Factory> functionFactory) { + super(); + this.localFunction = new ThreadLocal>() { + @Override + protected synchronized UnaryFunction initialValue() { + return functionFactory.newInstance(); + } + }; + } + + /** + * method applies the evaluation by invoking the ThreadLocal function. + */ + @Override + public T evaluate(K arg) { + return localFunction.get().evaluate(arg); + } +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/UnaryFunction.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/UnaryFunction.java new file mode 100644 index 0000000..63587f3 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/UnaryFunction.java @@ -0,0 +1,12 @@ +/** + * + */ +package eu.dnetlib.miscutils.functional; + +/** + * @author marko + * + */ +public interface UnaryFunction { + T evaluate(K arg); +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/hash/Hashing.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/hash/Hashing.java new file mode 100644 index 0000000..2ac2b1a --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/hash/Hashing.java @@ -0,0 +1,20 @@ +package eu.dnetlib.miscutils.functional.hash; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.digest.DigestUtils; + +public class Hashing { + + public static String md5(String s) { + return DigestUtils.md5Hex(s); + } + + public static String decodeBase64(String s) { + return new String(Base64.decodeBase64(s.getBytes())); + } + + public static String encodeBase64(String s) { + return new String(Base64.encodeBase64(s.getBytes())); + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/string/EscapeHtml.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/string/EscapeHtml.java new file mode 100644 index 0000000..3c9ca1a --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/string/EscapeHtml.java @@ -0,0 +1,12 @@ +package eu.dnetlib.miscutils.functional.string; + + +import eu.dnetlib.miscutils.functional.UnaryFunction; +import org.apache.commons.lang3.StringEscapeUtils; + +public class EscapeHtml implements UnaryFunction { + @Override + public String evaluate(String arg) { + return StringEscapeUtils.escapeHtml4(arg); + } +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/string/EscapeXml.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/string/EscapeXml.java new file mode 100644 index 0000000..d509cbc --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/string/EscapeXml.java @@ -0,0 +1,10 @@ +package eu.dnetlib.miscutils.functional.string; +import eu.dnetlib.miscutils.functional.UnaryFunction; +import org.apache.commons.lang3.StringEscapeUtils; + +public class EscapeXml implements UnaryFunction { + @Override + public String evaluate(String arg) { + return StringEscapeUtils.escapeXml11(arg); + } +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/string/FastEscapeXml.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/string/FastEscapeXml.java new file mode 100644 index 0000000..9319cb8 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/string/FastEscapeXml.java @@ -0,0 +1,12 @@ +package eu.dnetlib.miscutils.functional.string; + +import eu.dnetlib.miscutils.functional.UnaryFunction; + +public class FastEscapeXml implements UnaryFunction { + + @Override + public String evaluate(String arg) { + return "", "]]]]>") + "]]>"; + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/string/Sanitizer.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/string/Sanitizer.java new file mode 100644 index 0000000..4fa03f2 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/string/Sanitizer.java @@ -0,0 +1,23 @@ +package eu.dnetlib.miscutils.functional.string; + +import eu.dnetlib.miscutils.functional.UnaryFunction; + +/** + * Removes control characters from a string + * + * @author claudio + * + */ +public class Sanitizer implements UnaryFunction { + + @Override + public String evaluate(String s) { + return sanitize(s); + } + + + public static String sanitize(String s) { + return s.replaceAll("\\p{Cntrl}", ""); + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/string/UnescapeHtml.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/string/UnescapeHtml.java new file mode 100644 index 0000000..07d9be4 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/string/UnescapeHtml.java @@ -0,0 +1,12 @@ +package eu.dnetlib.miscutils.functional.string; + +import eu.dnetlib.miscutils.functional.UnaryFunction; +import org.apache.commons.lang3.StringEscapeUtils; + +public class UnescapeHtml implements UnaryFunction { + + @Override + public String evaluate(final String arg) { + return StringEscapeUtils.unescapeHtml4(arg); + } +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/AbstractApplyXslt.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/AbstractApplyXslt.java new file mode 100644 index 0000000..6243d4b --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/AbstractApplyXslt.java @@ -0,0 +1,197 @@ +package eu.dnetlib.miscutils.functional.xml; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.Map; + +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.URIResolver; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +import eu.dnetlib.miscutils.functional.UnaryFunction; + +/** + * This function applies a stylesheet to something which can be transformed to a javax.xml.Source. + * + *

Subclasses are specialized and know how to transform K into a Source

+ * + * @author marko + * + * @param + */ +public abstract class AbstractApplyXslt implements UnaryFunction { + private static final String UNKNOWN_XSLT_NAME = "unknown xslt name"; + + private static final Log log = LogFactory.getLog(AbstractApplyXslt.class); // NOPMD by marko on 11/24/08 5:02 PM + + private Transformer transformer; + + /** + * optional, useful to keep track of xslt name for debugging purposes. + */ + private String xsltName; + + public AbstractApplyXslt(final Resource xslt) { + this(xslt, null); + } + + public AbstractApplyXslt(final Resource xslt, Map parameters) { + this(new StreamSource(getInputStream(xslt)), getFileName((ClassPathResource) xslt), parameters); + } + + public AbstractApplyXslt(final String xslt) { + this(xslt, UNKNOWN_XSLT_NAME); + } + + public AbstractApplyXslt(final String xslt, String name) { + this(xslt, name, null); + } + + public AbstractApplyXslt(final String xslt, String name, Map parameters) { + this(new StreamSource(new StringReader(xslt)), name, parameters); + } + + public AbstractApplyXslt(final Source xslt) { + this(xslt, UNKNOWN_XSLT_NAME); + } + + public AbstractApplyXslt(final Source xslt, String name) { + this(xslt, name, null); + } + + /** + * Base method for all the others. + * @param xslt + * @param name + * @param parameters + */ + public AbstractApplyXslt(final Source xslt, String name, Map parameters) { + try { + this.xsltName = name; + TransformerFactory factory = TransformerFactory.newInstance(); + if (! UNKNOWN_XSLT_NAME.equals(name)) + factory.setURIResolver(new ExternalResourceURIResolver(name.replaceFirst("[^/]+$", ""))); + transformer = factory.newTransformer(xslt); + if(parameters != null) + for(Map.Entry parameter : parameters.entrySet()) + transformer.setParameter(parameter.getKey(), parameter.getValue()); + + } catch (final Throwable e) { + log.error("Problems with transformer!\n" + xslt + "--" + name, e); + log.error(xsltDump(xslt)); + throw new IllegalStateException(e); + } + } + + /** + * This class contains the login enabling imports of peer external resources for the current xslt () + * The method resolve() first looks for the resource within the file system; if this fails, it looks in the classpath. + * @author Andrea Mannocci + * + */ + private class ExternalResourceURIResolver implements URIResolver { + private final String xsltBasePath; + + public ExternalResourceURIResolver(String xsltBasePath) { + this.xsltBasePath = xsltBasePath; + } + @Override + public Source resolve(String href, String base) throws TransformerException { + String externalResource = this.xsltBasePath + href; + try{ + log.debug("trying to load external resource from file system: " + externalResource); + return new StreamSource(new File(externalResource)); + } catch (final Throwable e) { + log.debug("trying to load external resource from file system: " + externalResource); + return new StreamSource(getInputStream(new ClassPathResource(externalResource))); + } + } + } + + private String xsltDump(Source xslt) { + Transformer transformer; + try { + transformer = TransformerFactory.newInstance().newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + StringWriter outWriter = new StringWriter(); + Result result = new StreamResult(outWriter); + transformer.transform(xslt, result); + StringBuffer sb = outWriter.getBuffer(); + return sb.toString(); + } catch (TransformerConfigurationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (TransformerException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return "error dumping the xslt"; + } + + @Override + public String evaluate(final K input) { + try { + final StringWriter output = new StringWriter(); + transformer.transform(toStream(input), new StreamResult(output)); + return output.toString(); + } catch (final TransformerException e) { + log.error("cannot transform record", e); + log.debug(input.toString()); + return ""; + } + } + + public abstract Source toStream(K input); + + public abstract String toString(K input); + + /** + * Used only to convert checked to unchecked exception. + * + * @param xslt + * @return + */ + private static InputStream getInputStream(final Resource xslt) { + try { + return xslt.getInputStream(); + } catch (final IOException e) { + throw new IllegalArgumentException(e); + } + } + + private static String getFileName(ClassPathResource xslt) { + return xslt.getPath(); + } + + public Transformer getTransformer() { + return transformer; + } + + public void setTransformer(final Transformer transformer) { + this.transformer = transformer; + } + + public String getXsltName() { + return xsltName; + } + + public void setXsltName(String xsltName) { + this.xsltName = xsltName; + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/ApplyXslt.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/ApplyXslt.java new file mode 100644 index 0000000..6325eb6 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/ApplyXslt.java @@ -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; + } +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/ApplyXsltDom.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/ApplyXsltDom.java new file mode 100644 index 0000000..91fd8b5 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/ApplyXsltDom.java @@ -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(); + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/ApplyXsltDom4j.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/ApplyXsltDom4j.java new file mode 100644 index 0000000..fdbb050 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/ApplyXsltDom4j.java @@ -0,0 +1,61 @@ +package eu.dnetlib.miscutils.functional.xml; + +import java.util.Map; + +import javax.xml.transform.Source; + +import org.dom4j.Document; +import org.dom4j.io.DocumentSource; +import org.springframework.core.io.Resource; + +/** + * Applies a stylesheet to a XML DOM4j and returns an XML string. + * + * @author marko + * + */ +public class ApplyXsltDom4j extends AbstractApplyXslt { + + public ApplyXsltDom4j(Resource xslt) { + super(xslt); + } + + public ApplyXsltDom4j(Source xslt, String name) { + super(xslt, name); + } + + public ApplyXsltDom4j(Source xslt) { + super(xslt); + } + + public ApplyXsltDom4j(String xslt, String name) { + super(xslt, name); + } + + public ApplyXsltDom4j(String xslt) { + super(xslt); + } + + public ApplyXsltDom4j(Resource xslt, Map parameters) { + super(xslt, parameters); + } + + public ApplyXsltDom4j(Source xslt, String name, Map parameters) { + super(xslt, name, parameters); + } + + public ApplyXsltDom4j(String xslt, String name, Map parameters) { + super(xslt, name, parameters); + } + + @Override + public Source toStream(Document input) { + return new DocumentSource(input); + } + + @Override + public String toString(Document input) { + return input.asXML(); + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/DnetXsltFunctions.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/DnetXsltFunctions.java new file mode 100644 index 0000000..0e99f10 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/DnetXsltFunctions.java @@ -0,0 +1,123 @@ +package eu.dnetlib.miscutils.functional.xml; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Random; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.google.common.base.Joiner; +import eu.dnetlib.miscutils.functional.hash.Hashing; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * This class provides some XSLT functions. + * + * ... + * + * @author michele + * + */ +public class DnetXsltFunctions { + + private static final Log log = LogFactory.getLog(DnetXsltFunctions.class); // NOPMD by marko on 11/24/08 5:02 PM + + private static volatile long seedUniquifier = 8682522807148012L; + + private static String[] dateFormats = { "yyyy-MM-dd", "yyyy/MM/dd" }; + + private static final String[] normalizeDateFormats = { "yyyy-MM-dd'T'hh:mm:ss", "yyyy-MM-dd", "yyyy/MM/dd", "yyyy" }; + + private static final String normalizeOutFormat = new String("yyyy-MM-dd'T'hh:mm:ss'Z'"); + + public static String extractYear(String s) throws ParseException { + Calendar c = new GregorianCalendar(); + for (String format : dateFormats) { + try { + c.setTime(new SimpleDateFormat(format).parse(s)); + String year = String.valueOf(c.get(Calendar.YEAR)); + return year; + } catch (ParseException e) {} + } + return ""; + } + + public static String normalizeDate(final String s, final boolean strict) { + + final String date = s != null ? s.trim() : ""; + + for (String format : normalizeDateFormats) { + try { + Date parse = new SimpleDateFormat(format).parse(date); + String res = new SimpleDateFormat(normalizeOutFormat).format(parse); + return res; + } catch (ParseException e) {} + } + if (strict) { + throw new IllegalArgumentException("unable to normalize date: " + date); + } else { + //log.warn("unable to normalize date: " + s); + return ""; + } + } + + public static String randomInt(int max) { + return String.valueOf(new Random(++seedUniquifier + System.nanoTime()).nextInt(max)); + } + + public static String md5(String s) { + return Hashing.md5(s); + } + + public static String decodeBase64(String s) { + return Hashing.decodeBase64(s); + } + + public static String encodeBase64(String s) { + return Hashing.encodeBase64(s); + } + + public static String lc(String s) { + return s.toLowerCase(); + } + + public static String uc(String s) { + return s.toUpperCase(); + } + + public static String decade(String s) { + String res = _decade(s.trim()); + log.debug(s + "--> " + res); + return res; + } + + private static String _decade(String s) { + Matcher m1 = Pattern.compile("(\\d\\d\\d)\\d").matcher(s); + if (m1.find()) { + String part = m1.group(1); + return part + "0-" + part + "9"; + } + Matcher m2 = Pattern.compile("(\\d)\\d").matcher(s); + if (m2.find()) { + String part = m2.group(1); + return "19" + part + "0-19" + part + "9"; + } + return "n/a"; + } + + public static String join(final String s1, final String separator, final String s2) { + if(StringUtils.isBlank(s1) || StringUtils.isBlank(s2)){ + return ""; + } + return Joiner.on(separator).join(s1, s2); + } + + public static String pickFirst(final String s1, final String s2) { + return StringUtils.isNotBlank(s1) ? s1 : StringUtils.isNotBlank(s2) ? s2 : ""; + } +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/IndentXmlString.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/IndentXmlString.java new file mode 100644 index 0000000..df62c36 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/IndentXmlString.java @@ -0,0 +1,133 @@ +package eu.dnetlib.miscutils.functional.xml; + +import java.io.*; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import com.sun.org.apache.xml.internal.serialize.OutputFormat; +import com.sun.org.apache.xml.internal.serialize.XMLSerializer; +import eu.dnetlib.miscutils.functional.UnaryFunction; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * The Class IndentXmlString. + */ +public class IndentXmlString implements UnaryFunction { + + /* + * (non-Javadoc) + * + * @see eu.dnetlib.miscutils.functional.UnaryFunction#evaluate(java.lang.Object) + */ + @Override + public String evaluate(final String unformattedXml) { + try { + return doIndent(unformattedXml); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Do indent. + * + * @param unformattedXml + * the unformatted xml + * @return the string + * @throws IOException + * Signals that an I/O exception has occurred. + */ + protected String doIndent(final String unformattedXml) throws IOException { + final Document document = parseXmlString(unformattedXml); + + OutputFormat format = new OutputFormat(document); + format.setIndenting(true); + format.setIndent(2); + Writer out = new StringWriter(); + XMLSerializer serializer = new XMLSerializer(out, format); + serializer.serialize(document); + + return out.toString(); + } + + /** + * Parses the xml string. + * + * @param in + * the in + * @return the document + */ + protected Document parseXmlString(final String in) { + try { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + db.setErrorHandler(null); + InputSource is = new InputSource(new StringReader(in)); + return db.parse(is); + } catch (ParserConfigurationException e) { + throw new RuntimeException(e); + } catch (SAXException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private String doIndent(final Document document) throws TransformerException, UnsupportedEncodingException { + + final Transformer transformer = getTransformer(); + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + transformer.transform(new DOMSource(document), new StreamResult(out)); + + return out.toString("utf-8"); + } + + private Transformer getTransformer() throws TransformerConfigurationException { + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer transformer = tf.newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + return transformer; + } + + private Document doIndentDocument(final Document document) throws TransformerException, UnsupportedEncodingException { + + final Transformer transformer = getTransformer(); + + final DOMResult out = new DOMResult(); + transformer.transform(new DOMSource(document), out); + + return (Document) out.getNode(); + } + + /** + * Static helper Apply. + * + * @param xml + * the xml + * @return the indented xml string + */ + public static String apply(final String xml) { + return new IndentXmlString().evaluate(xml); + } + + /** + * Static helper Apply. + * + * @param xml + * the xml + * @return the indented xml string + */ + public static Document apply(final Document xml) throws TransformerException, UnsupportedEncodingException { + return new IndentXmlString().doIndentDocument(xml); + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/SerializeXml.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/SerializeXml.java new file mode 100644 index 0000000..efa00bb --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/SerializeXml.java @@ -0,0 +1,45 @@ +package eu.dnetlib.miscutils.functional.xml; + +import java.io.StringWriter; + +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.w3c.dom.Node; + +import eu.dnetlib.miscutils.functional.UnaryFunction; + +public class SerializeXml implements UnaryFunction { + + Transformer transformer; + + public SerializeXml() { + try { + this.transformer = TransformerFactory.newInstance().newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + } catch (TransformerConfigurationException e) { + throw new IllegalStateException(e); + } catch (TransformerFactoryConfigurationError e) { + throw new IllegalStateException(e); + } + } + + @Override + public String evaluate(Node arg) { + StreamResult result = new StreamResult(new StringWriter()); + DOMSource source = new DOMSource(arg); + try { + transformer.transform(source, result); + return result.getWriter().toString(); + } catch (TransformerException e) { + throw new IllegalStateException(e); + } + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/TryIndentXmlString.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/TryIndentXmlString.java new file mode 100644 index 0000000..86351c1 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/functional/xml/TryIndentXmlString.java @@ -0,0 +1,22 @@ +package eu.dnetlib.miscutils.functional.xml; + +/** + * The Class TryIndentXmlString. Tries to indent an xml string. If an error occurs (e.g. broken xml) it returns the original xml. + */ +public class TryIndentXmlString extends IndentXmlString { + + /* + * (non-Javadoc) + * + * @see eu.dnetlib.miscutils.functional.xml.IndentXmlString#evaluate(java.lang.String) + */ + @Override + public String evaluate(final String unformattedXml) { + try { + return doIndent(unformattedXml); + } catch (Exception e) { + return unformattedXml; + } + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/hstree/NilTreeNode.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/hstree/NilTreeNode.java new file mode 100644 index 0000000..3b6eb51 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/hstree/NilTreeNode.java @@ -0,0 +1,16 @@ +package eu.dnetlib.miscutils.hstree; + +/** + * This is the terminator node in a tree definition chain: + * + * TreeNode>> + * + * Note the use of "Void" as the next-resource-parameter value in the last level. + * + * + * @author marko + * + */ +abstract public class NilTreeNode extends TreeNode> { // NOPMD + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/hstree/TreeNode.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/hstree/TreeNode.java new file mode 100644 index 0000000..123ede0 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/hstree/TreeNode.java @@ -0,0 +1,252 @@ +package eu.dnetlib.miscutils.hstree; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * This class implement statically typed complete tree of finite depth. The type signature of each tree node determines + * fully the depth and the types of all the children. + * + *
+ * class MyTree extends TreeNode<RootPayload, L1Payload, TreeNode<L1Payload, L2Payload, TreeNode<L2Payload, Void, NilTreeNode>>> {
+ * 
+ * }
+ * 
+ * + * However since java doesn't have type inferencing we'll have to write often the full type of intermediate nodes, + * especially during tree construction. Thus it's recommended that you split the chain into a number of dummy classes, + * serving only to the purpuse of declaring the type chain: + * + *
+ * class MyTree extends TreeNode<RootPayload, L1Payload, L1Tree> {
+ * }
+ * 
+ * class L1Tree extends TreeNode<L1Payload, L2Payload, L2Tree> {
+ * }
+ * 
+ * class L2Tree extends TreeNode<L2Payload, Void, NilTreeNode> {
+ * }
+ * 
+ * + * NOTE: you could keep the whole definition inside a single file using inner classes. + * + * @author marko + * + * @param + * Type of the payload (or resource) + * @param + * Type of the next level payload + * @param + * Type of the next level node (another TreeNode) + */ +public class TreeNode> { + + public static final String CHILDR_UNDER_LEAF = "cannot create children under leaf nodes"; + + private static final Log log = LogFactory.getLog(TreeNode.class); // NOPMD by marko on 11/24/08 5:02 PM + + T resource; + List children = new ArrayList(); + transient Class childNodeType = autoChildNodeType(getClass()); + + /** + * Default constructor doesn't set the payload. This is used internally to construct a node. We cannot use the + * TreeNode(T resource) constructor only because it would force any implementor of "alias" subclasses + * of TreeNode to provide a dummy implementation of the constructor calling super(resource) + * + * However the constructor is protected because users should only create objects through addChild or in + * alternative they should provide they own constructor ovverrides. + */ + protected TreeNode() { + // no action + } + + /** + * However the constructor is protected because users should only create objects through addChild or in + * alternative they should provide they own constructor ovverrides. + * + * @param resource + * payload + */ + protected TreeNode(final T resource) { + this.resource = resource; + } + + /** + * Call this method to add a child node. + * + * Only the payload is needed, the tree node will be constructed automatically and it will be returned. + * + *
+	 * L1Child c1 = root.addChild(new L1Resource());
+	 * c1.addChild(new L2Resource());
+	 * c1.addChild(new L2Resource()).addChild(new L3Resource());
+	 * 
+ * + * @param resource + * payload + * @return the new node + */ + @SuppressWarnings("unchecked") + public C addChild(final N resource) { + try { + if (childNodeType.equals(NilTreeNode.class)) + throw new IllegalStateException(CHILDR_UNDER_LEAF); + + C test; + try { + test = childNodeType.newInstance(); + test.setResource(resource); + } catch (InstantiationException e) { + /* + * handle the situation when someone wants to create a one argument constructor hiding the default + * constructor provided by the base class. Nodes should normally be constructed using addChild but we + * don't want to force users to do it, and if they do it they shouldn't be punished with obscure + * InstantiationException caused by our evil usage of reflection. Of course we should do much more here + * in order to be more robust in the general case. + */ + try { + test = (C) childNodeType.getConstructors()[0].newInstance(resource); // NOPMD + } catch (InvocationTargetException e1) { + throw new IllegalStateException(e1); + } catch (InstantiationException e1) { + throw new IllegalStateException(e1); + } + } + + getChildren().add(test); + return test; + } catch (IllegalArgumentException e) { + throw new IllegalStateException(e); + } catch (SecurityException e) { + throw new IllegalStateException(e); + } catch (IllegalAccessException e) { + throw new IllegalStateException(e); + } + } + + /** + * This method is especially useful for leaf nodes when you want to append several children to the same parent node, + * without having to declare a temporary variable to hold the parent node (which could have long and ugly type) + * + * @param resource + * @return the parent node + */ + public TreeNode appendChild(final N resource) { + addChild(resource); + return this; + } + + /** + * This method applies a visitor to all nodes in a breadth first fashon + * + * Currently null payloads are skipped + * + * @see Visitor + * @param visitor + */ + public void breadthFirst(final V visitor) { + final Queue> queue = new LinkedList>(); + + queue.add(this); + while (!queue.isEmpty()) { + final TreeNode current = queue.remove(); + log.info("visiting " + current); + current.accept(visitor); + queue.addAll(current.getChildren()); + } + + } + + /** + * depth first. + * + * Currently null payloads are skipped + * + * @see Visitor + * @param Visitor + */ + public void depthFirst(final V visitor) { + baseDepthFirst(visitor); + } + + public void baseDepthFirst(final V visitor) { + accept(visitor); + + for (C el : children) + el.baseDepthFirst(visitor); + } + + /** + * For the curious, this method takes care of retrieving the runtime type information for the tree node element + * declared for children nodes. + * + * Because of java type erasure, this is not strictly needed for making this kind of tree work, but it's needed if + * we want to enable people typing ugly long signatures and use type aliases as described in the class + * documentation; otherwise a cast exception would occur. + * + * Aargh, any serious language which permits type polymorphysm should have a type alias feature + * + * @param clazz + * the class object of this class + * @return the class object of the node element describing children + */ + @SuppressWarnings({ "unchecked", "rawtypes"}) + protected Class autoChildNodeType(final Class clazz) { + + final Type superType = clazz.getGenericSuperclass(); + + if (superType instanceof ParameterizedType) { + final ParameterizedType paramSuperType = (ParameterizedType) superType; + + int argumentIndex; + if (paramSuperType.getRawType() == TreeNode.class) + argumentIndex = 3; + else + argumentIndex = 2; + + + final Type argument = (paramSuperType).getActualTypeArguments()[argumentIndex]; + + return getRawType(argument); + } else { + return autoChildNodeType((Class) superType); + } + } + + @SuppressWarnings("unchecked") + protected X getRawType(final Type type) { + if (type instanceof ParameterizedType) + return (X) ((ParameterizedType) type).getRawType(); + return (X) type; + } + + public List getChildren() { + return children; + } + + public void setChildren(final List children) { + this.children = children; + } + + public T getResource() { + return resource; + } + + public void setResource(final T resource) { + this.resource = resource; + } + + public void accept(final V dummy) { + log.fatal("should be ovverriden"); + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/iterators/IterableIterator.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/iterators/IterableIterator.java new file mode 100644 index 0000000..4c05cf4 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/iterators/IterableIterator.java @@ -0,0 +1,24 @@ +package eu.dnetlib.miscutils.iterators; + +import java.util.Iterator; + +/** + * Useful if you want to quickly iterate an iterable with the new java 5 syntax. + * + * @author marko + * + * @param + */ +public class IterableIterator implements Iterable { + private Iterator iter; + + public IterableIterator(Iterator iter) { + this.iter = iter; + } + + @Override + public Iterator iterator() { + return iter; + } +} + diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/iterators/IterablePair.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/iterators/IterablePair.java new file mode 100644 index 0000000..ab45ef7 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/iterators/IterablePair.java @@ -0,0 +1,21 @@ +package eu.dnetlib.miscutils.iterators; + +import java.util.Iterator; +import java.util.List; + +import eu.dnetlib.miscutils.collections.Pair; + +public class IterablePair implements Iterable> { + private final List
first; + private final List second; + + public IterablePair(List first, List second) { + this.first = first; + this.second = second; + } + + @Override + public Iterator> iterator() { + return new ParallelIterator(first.iterator(), second.iterator()); + } +} \ No newline at end of file diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/iterators/ParallelIterator.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/iterators/ParallelIterator.java new file mode 100644 index 0000000..bd05291 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/iterators/ParallelIterator.java @@ -0,0 +1,29 @@ +package eu.dnetlib.miscutils.iterators; + +import java.util.Iterator; + +import eu.dnetlib.miscutils.collections.Pair; + +public class ParallelIterator implements Iterator> { + + private final Iterator iA; + private final Iterator iB; + + public ParallelIterator(Iterator iA, Iterator iB) { + this.iA = iA; this.iB = iB; + } + + @Override + public boolean hasNext() { return iA.hasNext() && iB.hasNext(); } + + @Override + public Pair next() { + return new Pair(iA.next(), iB.next()); + } + + @Override + public void remove() { + iA.remove(); + iB.remove(); + } +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/iterators/xml/IterableXmlParser.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/iterators/xml/IterableXmlParser.java new file mode 100644 index 0000000..29a4bdb --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/iterators/xml/IterableXmlParser.java @@ -0,0 +1,29 @@ +package eu.dnetlib.miscutils.iterators.xml; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Iterator; + +public class IterableXmlParser implements Iterable { + + private String element; + + private InputStream inputStream; + + public IterableXmlParser(String element, InputStream inputStream) { + this.element = element; + this.inputStream = inputStream; + } + + public IterableXmlParser(String element, String xml) { + this.element = element; + this.inputStream = new ByteArrayInputStream(xml.getBytes(Charset.forName(XMLIterator.UTF_8))); + } + + @Override + public Iterator iterator() { + return new XMLIterator(element, inputStream); + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/iterators/xml/XMLIterator.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/iterators/xml/XMLIterator.java new file mode 100644 index 0000000..dc41973 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/iterators/xml/XMLIterator.java @@ -0,0 +1,170 @@ +package eu.dnetlib.miscutils.iterators.xml; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringWriter; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CodingErrorAction; +import java.util.Iterator; + +import javax.xml.stream.XMLEventFactory; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class XMLIterator implements Iterator { + + private static final Log log = LogFactory.getLog(XMLIterator.class); + + private ThreadLocal inputFactory = new ThreadLocal() { + + @Override + protected XMLInputFactory initialValue() { + return XMLInputFactory.newInstance(); + } + }; + + private ThreadLocal outputFactory = new ThreadLocal() { + + @Override + protected XMLOutputFactory initialValue() { + return XMLOutputFactory.newInstance(); + } + }; + + private ThreadLocal eventFactory = new ThreadLocal() { + + @Override + protected XMLEventFactory initialValue() { + return XMLEventFactory.newInstance(); + } + }; + + public static final String UTF_8 = "UTF-8"; + + final XMLEventReader parser; + + private XMLEvent current = null; + + private String element; + + private InputStream inputStream; + + public XMLIterator(final String element, final InputStream inputStream) { + super(); + this.element = element; + this.inputStream = inputStream; + this.parser = getParser(); + try { + this.current = findElement(parser); + } catch (XMLStreamException e) { + log.warn("cannot init parser position. No element found: " + element); + current = null; + } + } + + @Override + public boolean hasNext() { + return current != null; + } + + @Override + public String next() { + String result = null; + try { + result = copy(parser); + current = findElement(parser); + return result; + } catch (XMLStreamException e) { + throw new RuntimeException(String.format("error copying xml, built so far: '%s'", result), e); + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("finally") + private String copy(final XMLEventReader parser) throws XMLStreamException { + final StringWriter result = new StringWriter(); + try { + final XMLEventWriter writer = outputFactory.get().createXMLEventWriter(result); + final StartElement start = current.asStartElement(); + final StartElement newRecord = eventFactory.get().createStartElement(start.getName(), start.getAttributes(), start.getNamespaces()); + + // new root record + writer.add(newRecord); + + // copy the rest as it is + while (parser.hasNext()) { + final XMLEvent event = parser.nextEvent(); + + // TODO: replace with depth tracking instead of close tag tracking. + if (event.isEndElement() && event.asEndElement().getName().getLocalPart().equals(element)) { + writer.add(event); + break; + } + + writer.add(event); + } + writer.close(); + } finally { + return result.toString(); + } + } + + /** + * Looks for the next occurrence of the splitter element. + * + * @param parser + * @return + * @throws XMLStreamException + */ + private XMLEvent findElement(final XMLEventReader parser) throws XMLStreamException { + + /* + * if (current != null && element.equals(current.asStartElement().getName().getLocalPart())) { return current; } + */ + + XMLEvent peek = parser.peek(); + if (peek != null && peek.isStartElement()) { + String name = peek.asStartElement().getName().getLocalPart(); + if (element.equals(name)) { return peek; } + } + + while (parser.hasNext()) { + final XMLEvent event = parser.nextEvent(); + if (event != null && event.isStartElement()) { + String name = event.asStartElement().getName().getLocalPart(); + if (element.equals(name)) { return event; } + } + } + return null; + } + + private XMLEventReader getParser() { + try { + return inputFactory.get().createXMLEventReader(sanitize(inputStream)); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + } + + private Reader sanitize(final InputStream in) { + final CharsetDecoder charsetDecoder = Charset.forName(UTF_8).newDecoder(); + charsetDecoder.onMalformedInput(CodingErrorAction.REPLACE); + charsetDecoder.onUnmappableCharacter(CodingErrorAction.REPLACE); + return new InputStreamReader(in, charsetDecoder); + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/jaxb/JaxbFactory.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/jaxb/JaxbFactory.java new file mode 100644 index 0000000..0756fc7 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/jaxb/JaxbFactory.java @@ -0,0 +1,216 @@ +package eu.dnetlib.miscutils.jaxb; + +import java.io.StringReader; +import java.io.StringWriter; +import java.lang.annotation.Annotation; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlRegistry; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.namespace.QName; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; + +/** + * Common base class for implementing the Jaxb ObjectFactory pattern. + * + * @author marko + * + * @param + * type of the roote element + */ +@XmlRegistry +public class JaxbFactory { + + /** + * jaxb context. + */ + private JAXBContext context; + + /** + * class for the root element handled by this factory. + */ + private Class clazz; + + /** + * Prevent instantiating with 0 arguments. + * + * @throws JAXBException + */ + protected JaxbFactory() throws JAXBException { + // prevent instantiation + } + + /** + * creates a new jaxb factory. + * + * This constructor is needed because spring constructor injection doesn't work well will varargs. + * + * @param clazz + * @throws JAXBException + */ + public JaxbFactory(final Class clazz) throws JAXBException { + this(clazz, new Class[] {}); + } + + /** + * creates a new jaxb factory. + * + * @param clazz + * class for the root element + * @param classes + * other classes + * @throws JAXBException + * could happen + */ + @SuppressWarnings("unchecked") + public JaxbFactory(final Class clazz, Class... classes) throws JAXBException { + Class[] all = new Class[classes.length + 1]; + for (int i = 0; i < classes.length; i++) + all[i + 1] = classes[i]; + all[0] = clazz; + + this.clazz = (Class) clazz; + context = JAXBContext.newInstance(all); + } + + /** + * Create a new T instance. + * + * @return new T instance + */ + public T newInstance() { + try { + return clazz.newInstance(); + } catch (InstantiationException e) { + throw new IllegalStateException("jaxb bean not instantiable, e"); + } catch (IllegalAccessException e) { + throw new IllegalStateException("jaxb bean not instantiable, e"); + } + } + + /** + * Parses a given string and creates a java object. + * + * @param value + * serialized representation + * @return java object + * @throws JAXBException + * could happen + */ + public T parse(final String value) throws JAXBException { + return parse(new StreamSource(new StringReader(value))); + } + + /** + * Parses a given source and creates a java object. + * + * @param source + * serialized representation + * @return java object + * @throws JAXBException + * could happen + */ + @SuppressWarnings("unchecked") + public T parse(final Source source) throws JAXBException { + final Unmarshaller unmarshaller = context.createUnmarshaller(); + return (T) unmarshaller.unmarshal(source); + } + + /** + * Serializes a java object to the xml representation. + * + * @param value + * java object + * @return xml string + * @throws JAXBException + * could happen + */ + public String serialize(final T value) throws JAXBException { + final Marshaller marshaller = context.createMarshaller(); + final StringWriter buffer = new StringWriter(); + marshaller.marshal(createElement(value), buffer); + return buffer.toString(); + } + + /** + * Serializes a java object to a xml sink. + * + * @param value + * java object + * @param result + * transform sink + * @throws JAXBException + * could happen + */ + public void serialize(final T value, final Result result) throws JAXBException { + final Marshaller marshaller = context.createMarshaller(); + marshaller.marshal(createElement(value), result); + } + + /** + * creates a jax element for a given java object. + * + * @param value + * java object + * @return jaxb element + */ + protected JAXBElement createElement(final T value) { + final XmlRootElement ann = findAnnotation(XmlRootElement.class, clazz); + return new JAXBElement(new QName(ann.namespace(), ann.name()), this.clazz, null, value); + } + + /** + * recursively searches a given annotation. + * + * @param + * annotation type + * @param annotation + * annotation to search + * @param clazz + * root of the class hierarchy. + * @return annotation + */ + private X findAnnotation(final Class annotation, final Class clazz) { + if (clazz == null) + return null; + + final X ann = clazz.getAnnotation(annotation); + if (ann != null) + return ann; + + for (Class iface : clazz.getInterfaces()) { + final X iann = findAnnotation(annotation, iface); + if (iann != null) + return iann; + } + + final X parent = findAnnotation(annotation, clazz.getSuperclass()); + if (parent != null) + return parent; + + return null; + } + + public JAXBContext getContext() { + return context; + } + + public void setContext(final JAXBContext context) { + this.context = context; + } + + public Class getClazz() { + return clazz; + } + + public void setClazz(final Class clazz) { + this.clazz = clazz; + } + +} diff --git a/dnet-core-components/src/main/java/eu/dnetlib/miscutils/maps/ConcurrentSizedMap.java b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/maps/ConcurrentSizedMap.java new file mode 100644 index 0000000..da4fd65 --- /dev/null +++ b/dnet-core-components/src/main/java/eu/dnetlib/miscutils/maps/ConcurrentSizedMap.java @@ -0,0 +1,53 @@ +package eu.dnetlib.miscutils.maps; + +import java.util.Queue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; + +/** + * + * @author claudio + * + * @param + * @param + */ +public class ConcurrentSizedMap extends ConcurrentHashMap { + + private static final long serialVersionUID = 5864196164431521782L; + + public int DEFAULT_SIZE = 4; + + private int queueSize; + + private Queue queue; + + public ConcurrentSizedMap() { + super(); + queue = new ConcurrentLinkedQueue(); + this.queueSize = DEFAULT_SIZE; + } + + @Override + public V put(K key, V value) { + queue.add(key); + if (queue.size() > queueSize) + super.remove(queue.poll()); + + return super.put(key, value); + } + + @Override + public V remove(Object key) { + queue.remove(key); + return super.remove(key); + } + + public void setQueueSize(int queueSize) { + this.queueSize = queueSize; + } + + public int getQueueSize() { + return queueSize; + } + +} diff --git a/dnet-core-components/src/main/resources/META-INF/services/javax.xml.transform.TransformerFactory b/dnet-core-components/src/main/resources/META-INF/services/javax.xml.transform.TransformerFactory new file mode 100644 index 0000000..b53ca85 --- /dev/null +++ b/dnet-core-components/src/main/resources/META-INF/services/javax.xml.transform.TransformerFactory @@ -0,0 +1 @@ +net.sf.saxon.TransformerFactoryImpl \ No newline at end of file diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/collections/AffixCollectionTest.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/collections/AffixCollectionTest.java new file mode 100644 index 0000000..55f73fe --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/collections/AffixCollectionTest.java @@ -0,0 +1,22 @@ +package eu.dnetlib.miscutils.collections; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +public class AffixCollectionTest { + + @Test + public void testIterator() { + final List list = new ArrayList(); + list.add("100"); + + final AffixCollection mapped = new AffixCollection(list, "_test"); + for (String el : mapped) + assertEquals("check array", "100_test", el); + } + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/collections/BloomFilterTest.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/collections/BloomFilterTest.java new file mode 100644 index 0000000..6c7e221 --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/collections/BloomFilterTest.java @@ -0,0 +1,491 @@ +/** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package eu.dnetlib.miscutils.collections; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.UUID; + +import org.junit.Test; + +/** + * Tests for BloomFilter.java + * + * @author Magnus Skjegstad + */ +public class BloomFilterTest { + static Random r = new Random(); + + @Test + public void testConstructorCNK() throws Exception { + System.out.println("BloomFilter(c,n,k)"); + + for (int i = 0; i < 10000; i++) { + double c = r.nextInt(20) + 1; + int n = r.nextInt(10000) + 1; + int k = r.nextInt(20) + 1; + BloomFilter bf = new BloomFilter(c, n, k); + assertEquals(bf.getK(), k); + assertEquals(bf.getExpectedBitsPerElement(), c, 0); + assertEquals(bf.getExpectedNumberOfElements(), n); + assertEquals(bf.size(), c*n, 0); + } + } + + + /** + * Test of createHash method, of class BloomFilter. + * @throws Exception + */ + @Test + public void testCreateHash_String() throws Exception { + System.out.println("createHash"); + String val = UUID.randomUUID().toString(); + int result1 = BloomFilter.createHash(val); + int result2 = BloomFilter.createHash(val); + assertEquals(result2, result1); + int result3 = BloomFilter.createHash(UUID.randomUUID().toString()); + assertNotSame(result3, result2); + + int result4 = BloomFilter.createHash(val.getBytes("UTF-8")); + assertEquals(result4, result1); + } + + /** + * Test of createHash method, of class BloomFilter. + * @throws UnsupportedEncodingException + */ + @Test + public void testCreateHash_byteArr() throws UnsupportedEncodingException { + System.out.println("createHash"); + String val = UUID.randomUUID().toString(); + byte[] data = val.getBytes("UTF-8"); + int result1 = BloomFilter.createHash(data); + int result2 = BloomFilter.createHash(val); + assertEquals(result1, result2); + } + + /** + * Test of createHash method, of class BloomFilter. + * @throws UnsupportedEncodingException + */ + @Test + public void testCreateHashes_byteArr() throws UnsupportedEncodingException { + System.out.println("createHashes"); + String val = UUID.randomUUID().toString(); + byte[] data = val.getBytes("UTF-8"); + int[] result1 = BloomFilter.createHashes(data, 10); + int[] result2 = BloomFilter.createHashes(data, 10); + assertEquals(result1.length, 10); + assertEquals(result2.length, 10); + assertArrayEquals(result1, result2); + int[] result3 = BloomFilter.createHashes(data, 5); + assertEquals(result3.length, 5); + for (int i = 0; i < result3.length; i++) + assertEquals(result3[i], result1[i]); + + } + + /** + * Test of equals method, of class BloomFilter. + * @throws UnsupportedEncodingException + */ + @Test + public void testEquals() throws UnsupportedEncodingException { + System.out.println("equals"); + BloomFilter instance1 = new BloomFilter(1000, 100); + BloomFilter instance2 = new BloomFilter(1000, 100); + + for (int i = 0; i < 100; i++) { + String val = UUID.randomUUID().toString(); + instance1.add(val); + instance2.add(val); + } + + assert(instance1.equals(instance2)); + assert(instance2.equals(instance1)); + + instance1.add("Another entry"); // make instance1 and instance2 different before clearing + + instance1.clear(); + instance2.clear(); + + assert(instance1.equals(instance2)); + assert(instance2.equals(instance1)); + + for (int i = 0; i < 100; i++) { + String val = UUID.randomUUID().toString(); + instance1.add(val); + instance2.add(val); + } + + assertTrue(instance1.equals(instance2)); + assertTrue(instance2.equals(instance1)); + } + + /** + * Test of hashCode method, of class BloomFilter. + * @throws UnsupportedEncodingException + */ + @Test + public void testHashCode() throws UnsupportedEncodingException { + System.out.println("hashCode"); + + BloomFilter instance1 = new BloomFilter(1000, 100); + BloomFilter instance2 = new BloomFilter(1000, 100); + + assertTrue(instance1.hashCode() == instance2.hashCode()); + + for (int i = 0; i < 100; i++) { + String val = UUID.randomUUID().toString(); + instance1.add(val); + instance2.add(val); + } + + assertTrue(instance1.hashCode() == instance2.hashCode()); + + instance1.clear(); + instance2.clear(); + + assertTrue(instance1.hashCode() == instance2.hashCode()); + + instance1 = new BloomFilter(100, 10); + instance2 = new BloomFilter(100, 9); + assertFalse(instance1.hashCode() == instance2.hashCode()); + + instance1 = new BloomFilter(100, 10); + instance2 = new BloomFilter(99, 9); + assertFalse(instance1.hashCode() == instance2.hashCode()); + + instance1 = new BloomFilter(100, 10); + instance2 = new BloomFilter(50, 10); + assertFalse(instance1.hashCode() == instance2.hashCode()); + } + + /** + * Test of expectedFalsePositiveProbability method, of class BloomFilter. + */ + @Test + public void testExpectedFalsePositiveProbability() { + // These probabilities are taken from the bloom filter probability table at + // http://pages.cs.wisc.edu/~cao/papers/summary-cache/node8.html + System.out.println("expectedFalsePositiveProbability"); + BloomFilter instance = new BloomFilter(1000, 100); + double expResult = 0.00819; // m/n=10, k=7 + double result = instance.expectedFalsePositiveProbability(); + assertEquals(instance.getK(), 7); + assertEquals(expResult, result, 0.000009); + + instance = new BloomFilter(100, 10); + expResult = 0.00819; // m/n=10, k=7 + result = instance.expectedFalsePositiveProbability(); + assertEquals(instance.getK(), 7); + assertEquals(expResult, result, 0.000009); + + instance = new BloomFilter(20, 10); + expResult = 0.393; // m/n=2, k=1 + result = instance.expectedFalsePositiveProbability(); + assertEquals(1, instance.getK()); + assertEquals(expResult, result, 0.0005); + + instance = new BloomFilter(110, 10); + expResult = 0.00509; // m/n=11, k=8 + result = instance.expectedFalsePositiveProbability(); + assertEquals(8, instance.getK()); + assertEquals(expResult, result, 0.00001); + } + + /** + * Test of clear method, of class BloomFilter. + */ + @Test + public void testClear() { + System.out.println("clear"); + BloomFilter instance = new BloomFilter(1000, 100); + for (int i = 0; i < instance.size(); i++) + instance.setBit(i, true); + instance.clear(); + for (int i = 0; i < instance.size(); i++) + assertSame(instance.getBit(i), false); + } + + /** + * Test of add method, of class BloomFilter. + * @throws Exception + */ + @Test + public void testAdd() throws Exception { + System.out.println("add"); + BloomFilter instance = new BloomFilter(1000, 100); + + for (int i = 0; i < 100; i++) { + String val = UUID.randomUUID().toString(); + instance.add(val); + assert(instance.contains(val)); + } + } + + /** + * Test of addAll method, of class BloomFilter. + * @throws Exception + */ + @Test + public void testAddAll() throws Exception { + System.out.println("addAll"); + List v = new ArrayList(); + BloomFilter instance = new BloomFilter(1000, 100); + + for (int i = 0; i < 100; i++) + v.add(UUID.randomUUID().toString()); + + instance.addAll(v); + + for (int i = 0; i < 100; i++) + assert(instance.contains(v.get(i))); + } + + /** + * Test of contains method, of class BloomFilter. + * @throws Exception + */ + @Test + public void testContains() throws Exception { + System.out.println("contains"); + BloomFilter instance = new BloomFilter(10000, 10); + + for (int i = 0; i < 10; i++) { + instance.add(Integer.toBinaryString(i)); + assert(instance.contains(Integer.toBinaryString(i))); + } + + assertFalse(instance.contains(UUID.randomUUID().toString())); + } + + /** + * Test of containsAll method, of class BloomFilter. + * @throws Exception + */ + @Test + public void testContainsAll() throws Exception { + System.out.println("containsAll"); + List v = new ArrayList(); + BloomFilter instance = new BloomFilter(1000, 100); + + for (int i = 0; i < 100; i++) { + v.add(UUID.randomUUID().toString()); + instance.add(v.get(i)); + } + + assert(instance.containsAll(v)); + } + + /** + * Test of getBit method, of class BloomFilter. + */ + @Test + public void testGetBit() { + System.out.println("getBit"); + BloomFilter instance = new BloomFilter(1000, 100); + Random r = new Random(); + + for (int i = 0; i < 100; i++) { + boolean b = r.nextBoolean(); + instance.setBit(i, b); + assertSame(instance.getBit(i), b); + } + } + + /** + * Test of setBit method, of class BloomFilter. + */ + @Test + public void testSetBit() { + System.out.println("setBit"); + + BloomFilter instance = new BloomFilter(1000, 100); + + for (int i = 0; i < 100; i++) { + instance.setBit(i, true); + assertSame(instance.getBit(i), true); + } + + for (int i = 0; i < 100; i++) { + instance.setBit(i, false); + assertSame(instance.getBit(i), false); + } + } + + /** + * Test of size method, of class BloomFilter. + */ + @Test + public void testSize() { + System.out.println("size"); + for (int i = 100; i < 1000; i++) { + BloomFilter instance = new BloomFilter(i, 10); + assertEquals(instance.size(), i); + } + } + + /** Test error rate * + * @throws UnsupportedEncodingException + */ + @Test + public void testFalsePositiveRate1() throws UnsupportedEncodingException { + // Numbers are from // http://pages.cs.wisc.edu/~cao/papers/summary-cache/node8.html + System.out.println("falsePositiveRate1"); + + for (int j = 10; j < 21; j++) { + System.out.print(j-9 + "/11"); + List v = new ArrayList(); + BloomFilter instance = new BloomFilter(100*j,100); + + for (int i = 0; i < 100; i++) { + byte[] bytes = new byte[100]; + r.nextBytes(bytes); + v.add(bytes); + } + instance.addAll(v); + + long f = 0; + double tests = 300000; + for (int i = 0; i < tests; i++) { + byte[] bytes = new byte[100]; + r.nextBytes(bytes); + if (instance.contains(bytes)) { + if (!v.contains(bytes)) { + f++; + } + } + } + + double ratio = f / tests; + + System.out.println(" - got " + ratio + ", math says " + instance.expectedFalsePositiveProbability()); + assertEquals(instance.expectedFalsePositiveProbability(), ratio, 0.01); + } + } + + /** Test for correct k **/ + @Test + public void testGetK() { + // Numbers are from http://pages.cs.wisc.edu/~cao/papers/summary-cache/node8.html + System.out.println("testGetK"); + BloomFilter instance = null; + + instance = new BloomFilter(2, 1); + assertEquals(1, instance.getK()); + + instance = new BloomFilter(3, 1); + assertEquals(2, instance.getK()); + + instance = new BloomFilter(4, 1); + assertEquals(3, instance.getK()); + + instance = new BloomFilter(5, 1); + assertEquals(3, instance.getK()); + + instance = new BloomFilter(6, 1); + assertEquals(4, instance.getK()); + + instance = new BloomFilter(7, 1); + assertEquals(5, instance.getK()); + + instance = new BloomFilter(8, 1); + assertEquals(6, instance.getK()); + + instance = new BloomFilter(9, 1); + assertEquals(6, instance.getK()); + + instance = new BloomFilter(10, 1); + assertEquals(7, instance.getK()); + + instance = new BloomFilter(11, 1); + assertEquals(8, instance.getK()); + + instance = new BloomFilter(12, 1); + assertEquals(8, instance.getK()); + } + + /** + * Test of contains method, of class BloomFilter. + */ + @Test + public void testContains_GenericType() { + System.out.println("contains"); + int items = 100; + BloomFilter instance = new BloomFilter(0.01, items); + + for (int i = 0; i < items; i++) { + String s = UUID.randomUUID().toString(); + instance.add(s); + assertTrue(instance.contains(s)); + } + } + + /** + * Test of contains method, of class BloomFilter. + */ + @Test + public void testContains_byteArr() { + System.out.println("contains"); + + int items = 100; + BloomFilter instance = new BloomFilter(0.01, items); + + for (int i = 0; i < items; i++) { + byte[] bytes = new byte[500]; + r.nextBytes(bytes); + instance.add(bytes); + assertTrue(instance.contains(bytes)); + } + } + + /** + * Test of count method, of class BloomFilter. + */ + @Test + public void testCount() { + System.out.println("count"); + int expResult = 100; + BloomFilter instance = new BloomFilter(0.01, expResult); + for (int i = 0; i < expResult; i++) { + byte[] bytes = new byte[100]; + r.nextBytes(bytes); + instance.add(bytes); + } + int result = instance.count(); + assertEquals(expResult, result); + + instance = new BloomFilter(0.01, expResult); + for (int i = 0; i < expResult; i++) { + instance.add(UUID.randomUUID().toString()); + } + result = instance.count(); + assertEquals(expResult, result); + } + + +} \ No newline at end of file diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/collections/FilteredCollectionTest.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/collections/FilteredCollectionTest.java new file mode 100644 index 0000000..33339cb --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/collections/FilteredCollectionTest.java @@ -0,0 +1,47 @@ +package eu.dnetlib.miscutils.collections; + +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import eu.dnetlib.miscutils.functional.CompositeUnaryFunction; +import eu.dnetlib.miscutils.functional.UnaryFunction; + +public class FilteredCollectionTest { + + @Test + public void testFilterComposition() { + final List list = new ArrayList(); + list.add(1); + list.add(4); + list.add(8); + + final Filter fi1 = new Filter() { // NOPMD + @Override + public Boolean evaluate(final Integer arg) { + return arg < 8; + } + }; + + final UnaryFunction square = new UnaryFunction() { + @Override + public Integer evaluate(final Integer arg) { + return arg * arg; + } + }; + + final FilteredCollection fic = new FilteredCollection(list, fi1); + for (Integer el : fic) + assertTrue("check array", el < 8); + + final CompositeUnaryFunction cf1 = new CompositeUnaryFunction(fi1); + final FilteredCollection fc2 = new FilteredCollection(list, cf1.of(square)); + for (Integer el : fc2) + assertTrue("check array", el < 8); + + } + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/collections/MappedCollectionTest.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/collections/MappedCollectionTest.java new file mode 100644 index 0000000..d206c88 --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/collections/MappedCollectionTest.java @@ -0,0 +1,29 @@ +package eu.dnetlib.miscutils.collections; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import eu.dnetlib.miscutils.functional.UnaryFunction; + +public class MappedCollectionTest { + + @Test + public void testIterator() { + final List list = new ArrayList(); + list.add(100); + + final MappedCollection mapped = new MappedCollection(list, new UnaryFunction() { //NOPMD + @Override + public String evaluate(final Integer arg) { + return arg.toString(); + } + }); + for (String el : mapped) + assertEquals("check array", el, "100"); + } + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/collections/TypeFilteredCollectionTest.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/collections/TypeFilteredCollectionTest.java new file mode 100644 index 0000000..8353b2d --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/collections/TypeFilteredCollectionTest.java @@ -0,0 +1,69 @@ +package eu.dnetlib.miscutils.collections; + +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; + +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.Node; +import org.dom4j.io.SAXReader; +import org.junit.Test; + +import static org.junit.Assert.*; // NOPMD + + +public class TypeFilteredCollectionTest { + + private void checkContainsTestString(final Iterable iter) { + int count = 0; // NOPMD + for (String el : iter) { + assertEquals("check array", el, "test"); + count++; // NOPMD + } + assertEquals("check count", count, 1); + } + + @Test + public void testFilter() { + final List list = new ArrayList(); + list.add(1); + list.add("test"); + + final TypeFilteredCollection tfc; + tfc = new TypeFilteredCollection(list, String.class); + checkContainsTestString(tfc); + } + + @Test + public void testNull() { + final List list = new ArrayList(); + assertNotNull("dummy", list); + + list.add(null); + list.add("test"); + + final TypeFilteredCollection tfc; + tfc = new TypeFilteredCollection(list, String.class); + checkContainsTestString(tfc); + } + + @Test + public void testJDom() throws DocumentException { + final String xmlSource = "xxxxxxxx"; + + final Document document = new SAXReader().read(new StringReader(xmlSource)); + + @SuppressWarnings("unchecked") + final List children = document.selectNodes("//child"); + + final TypeFilteredCollection tfc; + tfc = new TypeFilteredCollection(children, Element.class); + for (Element el : tfc) { + assertEquals("check array", el.asXML(), ""); + } + + } + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/datetime/DateUtilsTest.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/datetime/DateUtilsTest.java new file mode 100644 index 0000000..1b12596 --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/datetime/DateUtilsTest.java @@ -0,0 +1,40 @@ +package eu.dnetlib.miscutils.datetime; + +import java.text.ParseException; +import java.util.Date; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class DateUtilsTest { + + private final DateUtils dateUtils = new DateUtils(); + + @Test + public void testGetDuration() { + String theDate = "1900-01-01T00:13:57"; + String duration = dateUtils.getDuration(theDate); + assertEquals("00:13:57", duration); + } + + @Test + public void getISOdateTimeFromLong(){ + Long dateLong = Long.parseLong("1520531435465"); + String iso = DateUtils.calculate_ISO8601(dateLong); + System.out.println(iso); + } + + + @Test + public void test1() throws ParseException { + String fromDate = "2019-04-11"; + Date date = org.apache.commons.lang3.time.DateUtils.parseDate( + fromDate, + new String[] { "yyyy-MM-dd", "yyyy-MM-dd'T'HH:mm:ssXXX", "yyyy-MM-dd'T'HH:mm:ss.SSSX", "yyyy-MM-dd'T'HH:mm:ssZ", + "yyyy-MM-dd'T'HH:mm:ss.SX" }); + long timestamp = date.toInstant().toEpochMilli(); + System.out.println(timestamp); + } + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/dom4j/XPathHelperTest.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/dom4j/XPathHelperTest.java new file mode 100644 index 0000000..b21e3bf --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/dom4j/XPathHelperTest.java @@ -0,0 +1,38 @@ +/** + * + */ +package eu.dnetlib.miscutils.dom4j; + +import static org.junit.Assert.assertEquals; + +import java.io.StringReader; + +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; +import org.junit.Test; + +/** + * @author marko + * + */ +public class XPathHelperTest { + + /** + * Test method for {@link eu.dnetlib.miscutils.dom4j.XPathHelper#selectElements(org.dom4j.Node, java.lang.String)}. + * + * @throws DocumentException + */ + @Test + public void testSelectElements() throws DocumentException { + final String xmlSource = "xxxxxxxx"; + + final Document document = new SAXReader().read(new StringReader(xmlSource)); + + for (Element el : XPathHelper.selectElements(document, "//child")) { + assertEquals("check elements", el.asXML(), ""); + } + } + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/CompositeUnaryFunctionTest.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/CompositeUnaryFunctionTest.java new file mode 100644 index 0000000..76e83d6 --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/CompositeUnaryFunctionTest.java @@ -0,0 +1,86 @@ +package eu.dnetlib.miscutils.functional; + +import static org.junit.Assert.*; // NOPMD + +import org.junit.Test; + +public class CompositeUnaryFunctionTest { + + @Test + public void testOf() { + final UnaryFunction toStringBase = new UnaryFunction() { // NOPMD + @Override + public String evaluate(final Integer arg) { + return arg.toString(); + } + }; + + final UnaryFunction fromStringBase = new UnaryFunction() { + @Override + public Integer evaluate(final String arg) { + return Integer.decode(arg); + } + }; + + final CompositeUnaryFunction toString = new CompositeUnaryFunction(toStringBase); + final CompositeUnaryFunction fromString = new CompositeUnaryFunction(fromStringBase); + + assertEquals("evaluation", toString.evaluate(10), "10"); + assertEquals("evaluation", fromString.evaluate("10"), (Integer) 10); + + final UnaryFunction stringIdentity = toString.of(fromString); + final UnaryFunction integerIdentity = fromString.of(toString); + final UnaryFunction integerIdentity2 = fromString.of(stringIdentity).of(toString).of(integerIdentity); + + assertEquals("string evaluation", stringIdentity.evaluate("10"), "10"); + assertEquals("integer evaluation", integerIdentity.evaluate(10), (Integer) 10); + assertEquals("integer identity", integerIdentity2.evaluate(10), (Integer) 10); + } + + private transient int calls; + private transient final static int TIMES = 100; + + @Test + public void testRecursive() { + calls = 0; + final UnaryFunction incrementBase = new UnaryFunction() { // NOPMD + @Override + public Integer evaluate(final Integer arg) { + calls++; + return arg + 1; + } + }; + + final CompositeUnaryFunction increment = new CompositeUnaryFunction(incrementBase); + + CompositeUnaryFunction comp = increment; + for (int i = 1; i <= 100; i++) { + assertEquals("compare", comp.evaluate(0), (Integer) i); + comp = comp.of(increment); + } + + assertEquals("number of calls", calls, (TIMES * (TIMES + 1) / 2)); + } + + @Test + public void testCurry() { + final UnaryFunction, Integer> add = new UnaryFunction, Integer>() { // NOPMD + @Override + public UnaryFunction evaluate(final Integer arg) { + return new UnaryFunction() { + @Override + public Integer evaluate(final Integer brg) { + return arg + brg; + } + }; + + } + }; + + final UnaryFunction increment = add.evaluate(1); + + assertEquals("check add", add.evaluate(1).evaluate(2), (Integer) 3); + assertEquals("check increment", increment.evaluate(1), (Integer) 2); + } + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/ThreadSafeUnaryFunctionTest.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/ThreadSafeUnaryFunctionTest.java new file mode 100644 index 0000000..6a4a000 --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/ThreadSafeUnaryFunctionTest.java @@ -0,0 +1,58 @@ +package eu.dnetlib.miscutils.functional; + +import static org.junit.Assert.*; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import org.junit.Before; +import org.junit.Test; + +import eu.dnetlib.miscutils.functional.ThreadSafeUnaryFunction; +import eu.dnetlib.miscutils.functional.UnaryFunction; + +public class ThreadSafeUnaryFunctionTest { + + /** + * Object under test. + */ + private ThreadSafeUnaryFunction tsUnaryFunction; + + private final static int N_THREAD = 10; + + private ExecutorService executor; + + @Before + public void setUp() { + executor = Executors.newFixedThreadPool(N_THREAD); + } + + /** + * method creates N_THREAD threads such that each one performs a function.evaluate call + * @param function + */ + private void createThreads(final ThreadSafeUnaryFunction function) { + for (int i = 0; i < N_THREAD; i++) { + final Integer j = i; + executor.execute(new Runnable() { + + @Override + public void run() { + assertEquals(String.valueOf(j), function.evaluate(j)); + } + }); + } + } + + @Test + public void testThreadSafeUnaryFunction_1() { + tsUnaryFunction = new ThreadSafeUnaryFunction(new ThreadLocal>() { + @Override + protected synchronized UnaryFunction initialValue() { + return new UnsafeUnaryFunction(); + } + }); + createThreads(tsUnaryFunction); + } + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/UnsafeUnaryFunction.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/UnsafeUnaryFunction.java new file mode 100644 index 0000000..8be2aa4 --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/UnsafeUnaryFunction.java @@ -0,0 +1,10 @@ +package eu.dnetlib.miscutils.functional; + +import eu.dnetlib.miscutils.functional.UnaryFunction; + +public class UnsafeUnaryFunction implements UnaryFunction { + @Override + public String evaluate(Integer arg) { + return String.valueOf(arg); + } +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/string/EscapeUnescapeTest.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/string/EscapeUnescapeTest.java new file mode 100644 index 0000000..b2e4d9e --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/string/EscapeUnescapeTest.java @@ -0,0 +1,34 @@ +package eu.dnetlib.miscutils.functional.string; + +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; + +import org.apache.commons.io.IOUtils; +import org.junit.Test; + +public class EscapeUnescapeTest { + + @Test + public void testEscape() throws IOException { + String xml = getRecord(); + System.out.println(xml); + System.out.println("##############"); + String escaped = new EscapeHtml().evaluate(xml); + System.out.println(escaped); + + String unescaped = new UnescapeHtml().evaluate(escaped); + System.out.println("##############"); + System.out.println(unescaped); + + } + + private String getRecord() throws IOException { + InputStream is = getClass().getResourceAsStream("record.xml"); + StringWriter sw = new StringWriter(); + IOUtils.copy(is, sw); + + return sw.toString(); + } + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/string/SanitizerTest.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/string/SanitizerTest.java new file mode 100644 index 0000000..7e10847 --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/string/SanitizerTest.java @@ -0,0 +1,43 @@ +package eu.dnetlib.miscutils.functional.string; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import java.io.StringWriter; + +import org.apache.commons.io.IOUtils; +import org.junit.Test; + +public class SanitizerTest { + + @Test + public void testIdentity() { + verifyIdentity("+-@°#()!$%&/()?' "); + verifyIdentity("asça"); + verifyIdentity("qwéèrtç°§"); + verifyIdentity("AÁaáCĆcćEÉeéIÍiíLĹlĺNŃnńOÓoóRŔrŕSŚsśUÚuúYÝyýZŹzź"); + verifyIdentity("AÂaâCĈcĉEÊeêGĜgĝHĤhĥIÎiîJĴjĵOÔoôSŜsŝUÛuûWŴwŵYŶyŷ"); + verifyIdentity("CÇcçGĢgģKĶkķLĻlļNŅnņRŖrŗSŞsşTŢtţ"); + verifyIdentity("ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΆΈΉΊΌΎΏΪΫαβγδεζηθικλμνξοπρσςτυφχψωάέήίόύώΐΰ"); + verifyIdentity("АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"); + verifyIdentity("абвгдеёжзийклмнопрстуфхцчшщъыьэюя"); + verifyIdentity("ـآ آ ـا ا بـبـب ب تـتـت ت ثـثـث ث جـجـج ج حـحـح ح خـخـخ خ ـد د ـذ ذ ـر ر ـز ز سـسـس س"); + } + + @Test + public void testInvalid() throws Exception { + StringWriter sw = new StringWriter(); + + IOUtils.copy(getClass().getResourceAsStream("invalid.txt"), sw); + + String pre = sw.toString(); + String post = Sanitizer.sanitize(pre); + + assertFalse(pre.equals(post)); + } + + private void verifyIdentity(String s) { + assertEquals(s, Sanitizer.sanitize(s)); + } + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/xml/ApplyXsltTest.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/xml/ApplyXsltTest.java new file mode 100644 index 0000000..7c86b5b --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/xml/ApplyXsltTest.java @@ -0,0 +1,41 @@ +package eu.dnetlib.miscutils.functional.xml; + +import static org.junit.Assert.*; + +import java.io.IOException; + +import javax.xml.transform.TransformerFactory; + +import org.apache.commons.io.IOUtils; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnit44Runner; +import org.springframework.core.io.ClassPathResource; + +@RunWith(MockitoJUnit44Runner.class) +public class ApplyXsltTest { + + TransformerFactory tf = TransformerFactory.newInstance(); + + private static final Class transformerClass = net.sf.saxon.TransformerFactoryImpl.class; + + @Test + public void testTransformerFactoryType() { + assertEquals(tf.getClass(), transformerClass); + } + + @Test + public void applyXslt() throws IOException { + String record = IOUtils.toString((new ClassPathResource("/eu/dnetlib/miscutils/functional/xml/sampleRecord.xml")).getInputStream()); + String layout = IOUtils.toString((new ClassPathResource("/eu/dnetlib/miscutils/functional/xml/sampleIndexLayout.xml")).getInputStream()); + String indexXsltOfXslt = IOUtils.toString((new ClassPathResource("/eu/dnetlib/miscutils/functional/xml/layoutToRecordStylesheet.xsl")).getInputStream()); + ApplyXslt applyXslt = new ApplyXslt(IOUtils.toString((new ClassPathResource("/eu/dnetlib/miscutils/functional/xml/recordStylesheet.xsl")).getInputStream())); + ApplyXslt xslt1 = new ApplyXslt(indexXsltOfXslt); + String indexXslt = xslt1.evaluate(layout); + ApplyXslt xslt2 = new ApplyXslt(indexXslt); + String response = xslt2.evaluate(record); + System.out.println(response); + + } + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/xml/IndentXmlStringTest.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/xml/IndentXmlStringTest.java new file mode 100644 index 0000000..43d8a8c --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/xml/IndentXmlStringTest.java @@ -0,0 +1,19 @@ +package eu.dnetlib.miscutils.functional.xml; + +import org.junit.Before; +import org.junit.Test; + +public class IndentXmlStringTest { + + @Before + public void setUp() throws Exception { + + } + + @Test + public void testEvaluate() { + String indented = new IndentXmlString().evaluate(""); + System.out.println(indented); + } + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/xml/dnetFunctionsTest.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/xml/dnetFunctionsTest.java new file mode 100644 index 0000000..67b98ec --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/functional/xml/dnetFunctionsTest.java @@ -0,0 +1,107 @@ +package eu.dnetlib.miscutils.functional.xml; + +import static org.junit.Assert.assertEquals; + +import java.io.StringReader; +import java.io.StringWriter; + +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.dom4j.Document; +import org.dom4j.io.SAXReader; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnit44Runner; + +@RunWith(MockitoJUnit44Runner.class) +public class dnetFunctionsTest { + + private static final String XSLT = + "" + + "" + + "" + + " " + + " " + + " " + + " " + + "" + + ""; + + private Transformer transformer; + + @Before + public void setUp() { + try { + transformer = TransformerFactory.newInstance().newTransformer(new StreamSource(new StringReader(XSLT))); + } catch (Exception e) { + System.out.println("**** INITIALIZATION FAILED ****"); + } + } + + @Test + public void testDecade_1() throws Exception { + assertEquals("1980-1989", process("primi anni 80", "decade")); + } + + @Test + public void testDecade_2() throws Exception { + assertEquals("2000-2009", process("04-05-2007", "decade")); + } + + @Test + public void testDecade_3() throws Exception { + assertEquals("1960-1969", process("1964", "decade")); + } + + @Test + public void testDecade_4() throws Exception { + assertEquals("n/a", process("XXXXXXXXXXXX", "decade")); + } + + @Test + public void testDecade_5() throws Exception { + assertEquals("1880-1889", process(" 1887-01-01 ", "decade")); + } + + @Test + public void testDecade_6() throws Exception { + assertEquals("1880-1889", process("\n\n 1887-01-01 \n\n", "decade")); + } + + @Test + public void testDecade_7() throws Exception { + assertEquals("1840-1849", process(" 1840-03-05 ", "decade")); + } + + @Test + public void testYear_1() throws Exception { + assertEquals("1840", process("1840-03-05", "year")); + } + + @Test + public void testYear_2() throws Exception { + assertEquals("1840", process("1840/03/05", "year")); + } + + private String process(String s, String attr) throws Exception { + String xml = "" + s + ""; + + StringWriter strw = new StringWriter(); + transformer.transform(new StreamSource(new StringReader(xml)), new StreamResult(strw)); + + Document document = (new SAXReader()).read(new StringReader((strw.toString()))); + + System.out.println(document.asXML()); + + String res = document.valueOf("/OUTS/OUTPUT/@" + attr); + + System.out.println(s + " --> " + res); + + return res; + } + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/TreeNodeTest.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/TreeNodeTest.java new file mode 100644 index 0000000..6a06a62 --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/TreeNodeTest.java @@ -0,0 +1,63 @@ +package eu.dnetlib.miscutils.hstree; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; + +import eu.dnetlib.miscutils.hstree.sample.resources.ChildResource; +import eu.dnetlib.miscutils.hstree.sample.resources.SampleResource; +import eu.dnetlib.miscutils.hstree.sample.resources.SubResource; +import eu.dnetlib.miscutils.hstree.sample.tree.FirstChild; +import eu.dnetlib.miscutils.hstree.sample.tree.MyTreeNode; +import eu.dnetlib.miscutils.hstree.sample.tree.RootTree; + +public class TreeNodeTest { + + private static final String EXISTS = "exists"; + + /** + * This test simply shows how to create a statically checked tree. The tree grammar for this test is defined in + * package eu.rinfrastructures.genericstest.sample.tree and it contains resource payloads defined in package + * eu.rinfrastructures.genericstest.sample.resources + */ + @Test + public void simpleTest() { + final MyTreeNode root = new RootTree(new SampleResource()); + + final FirstChild ch1 = root.addChild(new ChildResource()); + assertNotNull(EXISTS, ch1); + + ch1.addChild(new SubResource()); + ch1.addChild(new SubResource()); + + final FirstChild ch2 = root.addChild(new ChildResource()); + assertNotNull(EXISTS, ch2); + + ch2.addChild(new SubResource()); + ch2.addChild(new SubResource()); + ch2.addChild(new SubResource()); + + } + + @Test + public void typeSafeness() { + final MyTreeNode root = new RootTree(new SampleResource()); + + final FirstChild ch1 = root.addChild(new ChildResource()); + assertNotNull(EXISTS, ch1); + + ch1.addChild(new SubResource()); + + // ILLEGAL: + //c1.addChild(new SampleResource()); + } + + @Test + public void cascade() { + final MyTreeNode root = new RootTree(new SampleResource()); + assertNotNull(EXISTS, root); + + root.addChild(new ChildResource()).appendChild(new SubResource()).appendChild(new SubResource()).addChild(new SubResource()); + + } +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/VisitorTest.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/VisitorTest.java new file mode 100644 index 0000000..bbeb0ac --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/VisitorTest.java @@ -0,0 +1,90 @@ +package eu.dnetlib.miscutils.hstree; + +import static org.junit.Assert.*; // NOPMD + +import org.junit.Before; +import org.junit.Test; + +import eu.dnetlib.miscutils.hstree.sample.resources.ChildResource; +import eu.dnetlib.miscutils.hstree.sample.resources.SampleResource; +import eu.dnetlib.miscutils.hstree.sample.resources.SubResource; +import eu.dnetlib.miscutils.hstree.sample.tree.FirstChild; +import eu.dnetlib.miscutils.hstree.sample.tree.MyComputingVisitor; +import eu.dnetlib.miscutils.hstree.sample.tree.MyLoggingVisitor; +import eu.dnetlib.miscutils.hstree.sample.tree.MyTreeNode; +import eu.dnetlib.miscutils.hstree.sample.tree.MyTreeVisitor; +import eu.dnetlib.miscutils.hstree.sample.tree.RootTree; + +public class VisitorTest { + + transient RootTree root = null; + transient MyTreeVisitor loggingVisitor = null; + transient MyComputingVisitor computingVisitor = null; + + @Before + public void setUp() throws Exception { + root = new RootTree(new SampleResource()); + + root.addChild(new ChildResource()).appendChild(new SubResource()).appendChild(new SubResource()).addChild(new SubResource()); + + loggingVisitor = new MyLoggingVisitor(); + computingVisitor = new MyComputingVisitor(); + } + + @Test + public void testVisit() { + final MyTreeNode root = new RootTree(new SampleResource()); + assertNotNull("exists", root); + + final FirstChild ch1 = root.addChild(new ChildResource()); + ch1.addChild(new SubResource()); + ch1.addChild(new SubResource()); + + final FirstChild ch2 = root.addChild(new ChildResource()); + ch2.addChild(new SubResource()); + ch2.addChild(new SubResource()); + ch2.addChild(new SubResource()); + + root.breadthFirst(loggingVisitor); + } + + @Test + public void testVisit2() { + final MyTreeNode root = new RootTree(new SampleResource()); + assertNotNull("exists", root); + + root.addChild(new ChildResource()).appendChild(new SubResource()).appendChild(new SubResource()).addChild(new SubResource()); + root.appendChild(new ChildResource()).appendChild(new ChildResource()).appendChild(new ChildResource()).addChild(new ChildResource()).addChild( + new SubResource()); + + root.breadthFirst(loggingVisitor); + } + + @Test + public void testVisit3() { + final MyTreeNode root = new RootTree(new SampleResource()); + assertNotNull("exists", root); + + root.addChild(new ChildResource()).appendChild(new SubResource()).appendChild(new SubResource()).addChild(new SubResource()); + root.appendChild(new ChildResource()).appendChild(new ChildResource()).appendChild(new ChildResource()).addChild(new ChildResource()).addChild( + new SubResource()); + + root.depthFirst(loggingVisitor); + } + + @Test + public void testMyVisitor() { + assertNotNull("dummy", root); + + root.accept(loggingVisitor); + root.getChildren().get(0).accept(loggingVisitor); + } + + @Test + public void testComputingVisitor() { + assertNotNull("dummy", root); + + root.breadthFirst(computingVisitor); + assertEquals("check count", 113, computingVisitor.getCount()); + } +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/WrongTreeNodeTest.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/WrongTreeNodeTest.java new file mode 100644 index 0000000..5cc409b --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/WrongTreeNodeTest.java @@ -0,0 +1,44 @@ +package eu.dnetlib.miscutils.hstree; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import eu.dnetlib.miscutils.hstree.sample.resources.ChildResource; +import eu.dnetlib.miscutils.hstree.sample.resources.SampleResource; +import eu.dnetlib.miscutils.hstree.sample.resources.SubResource; +import eu.dnetlib.miscutils.hstree.sample.wrongtree.WrongFirstChild; +import eu.dnetlib.miscutils.hstree.sample.wrongtree.WrongRootTree; +import eu.dnetlib.miscutils.hstree.sample.wrongtree.WrongSecondChild; + +public class WrongTreeNodeTest { + + /** + * Try to break/misalign the signatures of the 'sample.wrongtree' package. The code should not be able to compile. + */ + @Test + public void simpleTest() { + final WrongRootTree root = new WrongRootTree(new SampleResource()); + + final WrongFirstChild ch1 = root.addChild(new ChildResource()); + ch1.addChild(new SubResource()); + ch1.addChild(new SubResource()); + + final WrongFirstChild ch2 = root.addChild(new ChildResource()); + ch2.addChild(new SubResource()); + ch2.addChild(new SubResource()); + final WrongSecondChild sc1 = ch2.addChild(new SubResource()); + + // of course we can do obscene things like this, + // but if somebody casts there is no escape. + boolean gotRuntimeEx = false; // NOPMD + try { + sc1.addChild((Void) null); + } catch (RuntimeException e) { + if (e.getMessage().equals(TreeNode.CHILDR_UNDER_LEAF)) + gotRuntimeEx = true; + } + assertTrue("got exception", gotRuntimeEx); // TODO: exploit junit4 for checking exceptions + + } +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/resources/ChildResource.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/resources/ChildResource.java new file mode 100644 index 0000000..255879c --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/resources/ChildResource.java @@ -0,0 +1,5 @@ +package eu.dnetlib.miscutils.hstree.sample.resources; + +public class ChildResource extends Resource { // NOPMD + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/resources/Resource.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/resources/Resource.java new file mode 100644 index 0000000..9127039 --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/resources/Resource.java @@ -0,0 +1,5 @@ +package eu.dnetlib.miscutils.hstree.sample.resources; + +public class Resource { // NOPMD + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/resources/SampleResource.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/resources/SampleResource.java new file mode 100644 index 0000000..35edf3f --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/resources/SampleResource.java @@ -0,0 +1,5 @@ +package eu.dnetlib.miscutils.hstree.sample.resources; + +public class SampleResource extends Resource { // NOPMD + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/resources/SubResource.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/resources/SubResource.java new file mode 100644 index 0000000..a4fd642 --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/resources/SubResource.java @@ -0,0 +1,5 @@ +package eu.dnetlib.miscutils.hstree.sample.resources; + +public class SubResource extends Resource { // NOPMD + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/FirstChild.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/FirstChild.java new file mode 100644 index 0000000..261505e --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/FirstChild.java @@ -0,0 +1,12 @@ +package eu.dnetlib.miscutils.hstree.sample.tree; + +import eu.dnetlib.miscutils.hstree.sample.resources.ChildResource; +import eu.dnetlib.miscutils.hstree.sample.resources.SubResource; + +public class FirstChild extends MyTreeNode { + @Override + public void accept(final MyTreeVisitor visitor) { + visitor.visit(getResource()); + } + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/MyComputingVisitor.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/MyComputingVisitor.java new file mode 100644 index 0000000..f77f05d --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/MyComputingVisitor.java @@ -0,0 +1,41 @@ +package eu.dnetlib.miscutils.hstree.sample.tree; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import eu.dnetlib.miscutils.hstree.sample.resources.ChildResource; +import eu.dnetlib.miscutils.hstree.sample.resources.SampleResource; +import eu.dnetlib.miscutils.hstree.sample.resources.SubResource; + +public class MyComputingVisitor implements MyTreeVisitor { + private static final Log log = LogFactory.getLog(MyComputingVisitor.class); // NOPMD by marko on 11/24/08 5:02 PM + + int count; + + @Override + public void visit(final SampleResource resource) { + log.info("increasing sampleresource"); + count += 100; + } + + @Override + public void visit(final ChildResource resource) { + log.info("increasing childresource"); + count += 10; + } + + @Override + public void visit(final SubResource resource) { + log.info("increasing subresource"); + count += 1; + } + + public int getCount() { + return count; + } + + public void setCount(final int count) { + this.count = count; + } + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/MyLoggingVisitor.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/MyLoggingVisitor.java new file mode 100644 index 0000000..b2ab8a5 --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/MyLoggingVisitor.java @@ -0,0 +1,49 @@ +package eu.dnetlib.miscutils.hstree.sample.tree; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import eu.dnetlib.miscutils.hstree.sample.resources.ChildResource; +import eu.dnetlib.miscutils.hstree.sample.resources.SampleResource; +import eu.dnetlib.miscutils.hstree.sample.resources.SubResource; + +public class MyLoggingVisitor implements MyTreeVisitor { + private static final Log log = LogFactory.getLog(MyLoggingVisitor.class); // NOPMD by marko on 11/24/08 5:02 PM + + /* + * (non-Javadoc) + * + * @see + * eu.rinfrastructures.genericstest.sample.wrongtree.MyTreeVisitor#visit(eu.rinfrastructures.genericstest.sample + * .resources.SampleResource) + */ + @Override + public void visit(final SampleResource resource) { + log.info("sample"); + } + + /* + * (non-Javadoc) + * + * @see + * eu.rinfrastructures.genericstest.sample.wrongtree.MyTreeVisitor#visit(eu.rinfrastructures.genericstest.sample + * .resources.ChildResource) + */ + @Override + public void visit(final ChildResource resource) { + log.info("child"); + } + + /* + * (non-Javadoc) + * + * @see + * eu.rinfrastructures.genericstest.sample.wrongtree.MyTreeVisitor#visit(eu.rinfrastructures.genericstest.sample + * .resources.SubResource) + */ + @Override + public void visit(final SubResource resource) { + log.info("sub"); + } + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/MyTreeNode.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/MyTreeNode.java new file mode 100644 index 0000000..f94ae95 --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/MyTreeNode.java @@ -0,0 +1,14 @@ +package eu.dnetlib.miscutils.hstree.sample.tree; + +import eu.dnetlib.miscutils.hstree.TreeNode; + +public class MyTreeNode> extends TreeNode { + + public MyTreeNode() { + // no action + } + + public MyTreeNode(final T resource) { + super(resource); + } +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/MyTreeVisitor.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/MyTreeVisitor.java new file mode 100644 index 0000000..6a1e20c --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/MyTreeVisitor.java @@ -0,0 +1,15 @@ +package eu.dnetlib.miscutils.hstree.sample.tree; + +import eu.dnetlib.miscutils.hstree.sample.resources.ChildResource; +import eu.dnetlib.miscutils.hstree.sample.resources.SampleResource; +import eu.dnetlib.miscutils.hstree.sample.resources.SubResource; + +public interface MyTreeVisitor { + + void visit(SampleResource resource); + + void visit(ChildResource resource); + + void visit(SubResource resource); + +} \ No newline at end of file diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/RootTree.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/RootTree.java new file mode 100644 index 0000000..5bb734e --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/RootTree.java @@ -0,0 +1,16 @@ +package eu.dnetlib.miscutils.hstree.sample.tree; + +import eu.dnetlib.miscutils.hstree.sample.resources.ChildResource; +import eu.dnetlib.miscutils.hstree.sample.resources.SampleResource; + +public class RootTree extends MyTreeNode { + + public RootTree(final SampleResource resource) { + super(resource); + } + + @Override + public void accept(final MyTreeVisitor visitor) { + visitor.visit(getResource()); + } +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/SecondChild.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/SecondChild.java new file mode 100644 index 0000000..aaa298f --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/tree/SecondChild.java @@ -0,0 +1,12 @@ +package eu.dnetlib.miscutils.hstree.sample.tree; + +import eu.dnetlib.miscutils.hstree.NilTreeNode; +import eu.dnetlib.miscutils.hstree.sample.resources.SubResource; + +public class SecondChild extends MyTreeNode> { + @Override + public void accept(final MyTreeVisitor visitor) { + visitor.visit(getResource()); + } + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/wrongtree/WrongFirstChild.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/wrongtree/WrongFirstChild.java new file mode 100644 index 0000000..9895a53 --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/wrongtree/WrongFirstChild.java @@ -0,0 +1,10 @@ +package eu.dnetlib.miscutils.hstree.sample.wrongtree; + +import eu.dnetlib.miscutils.hstree.TreeNode; +import eu.dnetlib.miscutils.hstree.sample.resources.ChildResource; +import eu.dnetlib.miscutils.hstree.sample.resources.SubResource; +import eu.dnetlib.miscutils.hstree.sample.tree.MyLoggingVisitor; + +public class WrongFirstChild extends TreeNode { // NOPMD + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/wrongtree/WrongRootTree.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/wrongtree/WrongRootTree.java new file mode 100644 index 0000000..bf46930 --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/wrongtree/WrongRootTree.java @@ -0,0 +1,14 @@ +package eu.dnetlib.miscutils.hstree.sample.wrongtree; + +import eu.dnetlib.miscutils.hstree.TreeNode; +import eu.dnetlib.miscutils.hstree.sample.resources.ChildResource; +import eu.dnetlib.miscutils.hstree.sample.resources.SampleResource; +import eu.dnetlib.miscutils.hstree.sample.tree.MyLoggingVisitor; + +public class WrongRootTree extends TreeNode { + + public WrongRootTree(final SampleResource resource) { + super(resource); + } + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/wrongtree/WrongSecondChild.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/wrongtree/WrongSecondChild.java new file mode 100644 index 0000000..34362eb --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/hstree/sample/wrongtree/WrongSecondChild.java @@ -0,0 +1,10 @@ +package eu.dnetlib.miscutils.hstree.sample.wrongtree; + +import eu.dnetlib.miscutils.hstree.NilTreeNode; +import eu.dnetlib.miscutils.hstree.TreeNode; +import eu.dnetlib.miscutils.hstree.sample.resources.SubResource; +import eu.dnetlib.miscutils.hstree.sample.tree.MyLoggingVisitor; + +public class WrongSecondChild extends TreeNode> { // NOPMD + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/iterators/xml/IterableXmlParserTest.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/iterators/xml/IterableXmlParserTest.java new file mode 100644 index 0000000..4e4e777 --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/iterators/xml/IterableXmlParserTest.java @@ -0,0 +1,113 @@ +package eu.dnetlib.miscutils.iterators.xml; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.zip.GZIPInputStream; +import java.util.zip.ZipInputStream; + +import org.apache.commons.io.IOUtils; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.io.SAXReader; +import org.junit.Before; +import org.junit.Test; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +public class IterableXmlParserTest { + + private Resource xmlZip = new ClassPathResource("eu/dnetlib/miscutils/iterators/xml/opendoar.zip"); + + private Resource xmlGz = new ClassPathResource("eu/dnetlib/miscutils/iterators/xml/opendoar.xml.gz"); + + private Resource xmlZipErr = new ClassPathResource("eu/dnetlib/miscutils/iterators/xml/opendoarErr.zip"); + + private Resource xmlSingle = new ClassPathResource("eu/dnetlib/miscutils/iterators/xml/singleRepo.xml"); + + private String element = "repository"; + + private IterableXmlParser parser; + + private SAXReader reader; + + @Before + public void setUp() throws Exception { + reader = new SAXReader(); + } + + @Test + public void testGz() throws Exception { + doTest(new GZIPInputStream(xmlGz.getInputStream()), element); + } + + @Test + public void test() throws Exception { + doTest(read(new ZipInputStream(xmlZip.getInputStream())), element); + } + + @Test + public void testErr() throws Exception { + doTest(read(new ZipInputStream(xmlZipErr.getInputStream())), element); + } + + @Test + public void testSingle() throws Exception { + doTest(xmlSingle.getInputStream(), element); + } + + @Test + public void testOaiRecord() throws Exception { + int count = doTest(new ClassPathResource("eu/dnetlib/miscutils/iterators/xml/oaiRecord.xml").getInputStream(), "record"); + assertTrue(count == 1); + } + + @Test + public void testWeird() throws Exception { + int count = doTest(new ClassPathResource("eu/dnetlib/miscutils/iterators/xml/weirdRecords.xml").getInputStream(), "record"); + assertTrue(count == 3); + } + + @Test + public void testWeirdGz() throws Exception { + int count = doTest(new GZIPInputStream(new ClassPathResource("eu/dnetlib/miscutils/iterators/xml/weirdRecords.xml.gz").getInputStream()), "record"); + assertTrue(count == 3); + } + + private int doTest(final InputStream stream, final String element) throws DocumentException { + parser = new IterableXmlParser(element, stream); + int count = 0; + for (String xml : parser) { + System.out.println(xml); + Document doc = reader.read(new StringReader(xml)); + assertNotNull(doc); + assertNotNull(doc.selectSingleNode("//" + element)); + count++; + } + return count; + } + + // helper method, reads the compressed text out of the xmlZip file + private InputStream read(final ZipInputStream zis) throws IOException { + + final StringWriter sw = new StringWriter(); + while (zis.getNextEntry() != null) { + + byte[] buffer = new byte[1]; + + while (zis.read(buffer) != -1) { + IOUtils.write(buffer, sw, "UTF-8"); + } + } + zis.close(); + sw.close(); + + return new ByteArrayInputStream(sw.toString().getBytes()); + } + +} diff --git a/dnet-core-components/src/test/java/eu/dnetlib/miscutils/maps/ConcurrentSizedMapTest.java b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/maps/ConcurrentSizedMapTest.java new file mode 100644 index 0000000..1265588 --- /dev/null +++ b/dnet-core-components/src/test/java/eu/dnetlib/miscutils/maps/ConcurrentSizedMapTest.java @@ -0,0 +1,44 @@ +package eu.dnetlib.miscutils.maps; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import org.junit.Before; +import org.junit.Test; + +import eu.dnetlib.miscutils.maps.ConcurrentSizedMap; + +public class ConcurrentSizedMapTest { + + private ConcurrentSizedMap map; + + private int size = 2; + + @Before + public void setUp() throws Exception { + map = new ConcurrentSizedMap(); + map.setQueueSize(size); + } + + @Test + public void testMap() throws InterruptedException { + + map.put("a", "value a"); + assertNotNull((map.get("a"))); + + map.put("b", "value b"); + assertNotNull((map.get("b"))); + + map.put("c", "value c"); + assertNotNull((map.get("c"))); + assertEquals(size, map.size()); + + assertNull(map.get("a")); + map.put("a", "new value a"); + + assertEquals("new value a", map.get("a")); + assertEquals(size, map.size()); + } + +} diff --git a/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/encoding/testSource.xml b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/encoding/testSource.xml new file mode 100644 index 0000000..47b0cec --- /dev/null +++ b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/encoding/testSource.xml @@ -0,0 +1 @@ +
http://localhost:8090/app/services/resultSet
rs-a1028c6a-bdab-4dbd-b6d1-d97e997bcbf0ns1:ResultSetServicens2:ResultSetServiceServicedevelopment
\ No newline at end of file diff --git a/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/functional/string/invalid.txt b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/functional/string/invalid.txt new file mode 100644 index 0000000..6078ccd --- /dev/null +++ b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/functional/string/invalid.txt @@ -0,0 +1,2 @@ +Experimental electron densities were determined from high-resolution X-ray diffraction data sets measured with synchrotron radiation at 100 K, +whereas theoretical calculations were performed using DFT methods at the B3LYP-311++G(3df,3pd) level of approximation. diff --git a/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/functional/string/record.xml b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/functional/string/record.xml new file mode 100644 index 0000000..051934a --- /dev/null +++ b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/functional/string/record.xml @@ -0,0 +1,46 @@ + + +
+ od_______908::92a0e1241032a6c3817c9e248ad570ee + d2b15e4e-6596-4add-a0d9-865fa6152c9c_TURTdG9yZURTUmVzb3VyY2VzL01EU3RvcmVEU1Jlc291cmNlVHlwZQ==::oai:europepmc.org:2701111 + 2013-07-17T18:30:00Z + + + 4fd8cd43-226c-408b-8401-0840456a678a_UmVwb3NpdG9yeVNlcnZpY2VSZXNvdXJjZXMvUmVwb3NpdG9yeVNlcnZpY2VSZXNvdXJjZVR5cGU= + jcbfm + pmc-open + od_______908 +
+ + + TIMP-1 attenuates blood–brain barrier permeability in mice with acute liver failure + Chen, Feng + Radisky, Evette S + Das, Pritam + Batra, Jyotica + Hata, Toshiyuki + Hori, Tomohide + Baine, Ann-Marie T + Gardner, Lindsay + Yue, Mei Y + Bu, Guojun + del Zoppo, Gregory + Patel, Tushar C + Nguyen, Justin H + Original Article + Blood–brain barrier (BBB) dysfunction in acute liver failure (ALF) results in increased BBB permeability that often precludes the patients from obtaining a life-saving liver transplantation. It remains controversial whether matrix metalloproteinase-9 (MMP-9) from the injured liver contributes to the deregulation of BBB function in ALF. We selectively upregulated a physiologic inhibitor of MMP-9 (TIMP-1) with a single intracerebroventricular injection of TIMP-1 cDNA plasmids at 48 and 72 hours, or with pegylated-TIMP-1 protein. Acute liver failure was induced with tumor necrosis factor-α and 𝒟-(+)-galactosamine in mice. Permeability of BBB was assessed with sodium fluorescein (NaF) extravasation. We found a significant increase in TIMP-1 within the central nervous system (CNS) after the administration of TIMP-1 cDNA plasmids and that increased TIMP-1 within the CNS resulted in an attenuation of BBB permeability, a reduction in activation of epidermal growth factor receptor and p38 mitogen-activated protein kinase signals, and a restoration of the tight junction protein occludin in mice with experimental ALF. Pegylated TIMP-1 provided similar protection against BBB permeability in mice with ALF. Our results provided a proof of principle that MMP-9 contributes to the BBB dysfunction in ALF and suggests a potential therapeutic role of TIMP-1 in ALF. + Nature Publishing Group + http://europepmc.org/articles/PMC3705430/ + Text + en + + PMC: PMC3705430 + 2013 + doi: 10.1038/jcbfm.2013.45 + + +
\ No newline at end of file diff --git a/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/functional/xml/layoutToRecordStylesheet.xsl b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/functional/xml/layoutToRecordStylesheet.xsl new file mode 100644 index 0000000..1d4d8fb --- /dev/null +++ b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/functional/xml/layoutToRecordStylesheet.xsl @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+ + + +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + . + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/functional/xml/recordStylesheet.xsl b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/functional/xml/recordStylesheet.xsl new file mode 100644 index 0000000..653370b --- /dev/null +++ b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/functional/xml/recordStylesheet.xsl @@ -0,0 +1,109 @@ + + + + EMF + + + + + + + + + + + <xsl:value-of select="."/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + +
+ + + + + +
+
+
+
diff --git a/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/functional/xml/sampleIndexLayout.xml b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/functional/xml/sampleIndexLayout.xml new file mode 100644 index 0000000..1952d46 --- /dev/null +++ b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/functional/xml/sampleIndexLayout.xml @@ -0,0 +1,42 @@ + + +
+ + + + + +
+ + + EMF + Eagle Metadata Format + cleaned + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/functional/xml/sampleRecord.xml b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/functional/xml/sampleRecord.xml new file mode 100644 index 0000000..1551220 --- /dev/null +++ b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/functional/xml/sampleRecord.xml @@ -0,0 +1,87 @@ + +
+ 367b05cf-13f6-4d3a-8c2d-9fd172b353ce_UmVwb3NpdG9yeVNlcnZpY2VSZXNvdXJjZXMvUmVwb3NpdG9yeVNlcnZpY2VSZXNvdXJjZVR5cGU=::http://irt.kcl.ac.uk/irt2009/IRT001.html_artifact + 2014-03-19T11:41:15+01:00 + + 367b05cf-13f6-4d3a-8c2d-9fd172b353ce_UmVwb3NpdG9yeVNlcnZpY2VSZXNvdXJjZXMvUmVwb3NpdG9yeVNlcnZpY2VSZXNvdXJjZVR5cGU= + +
+ + + artifact::BSR::f85e57d02d6efd679ce5a7a689c7960b + http://irt.kcl.ac.uk/irt2009/IRT001.html + + 2014-02-12 + PML + + + Creative Commons licence Attribution UK 2.0 + (http://creativecommons.org/licenses/by/2.0/uk/). + All reuse or distribution of this work must contain somewhere a link back to the URL + http://irt.kcl.ac.uk/ + + + Reference to Apollo (?) + Fragment from the lower part of a small, white + marble + panel ( + 0.09 + 0.14 + 0.02 + ; no edges + surviving, but there is a space after 1. 3); re-used at a later date for an + inscription cut in third century capitals, of which the letters [...]TT[...] alone survive. + Artifact + + Inscription + panel + white + marble + + + + + + + + Second to early third centuries A.D. (lettering) + + + Tripolitania + Sabratha: Capitolium + + + + + + + Libya + Marsa + Zawaghah + + + + + + + ###refersTrismegistosCard0### + + + + + + + + Rustic capitals: line 1, 0.05; line 2, 0.04; line 3, 0.03. + + 0 + 0 + + visual::BSR::f85e57d02d6efd679ce5a7a689c7960b::1 + ###relTranslationObj### + transcription::BSR::f85e57d02d6efd679ce5a7a689c7960b + + + + +
\ No newline at end of file diff --git a/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/iterators/xml/oaiRecord.xml b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/iterators/xml/oaiRecord.xml new file mode 100644 index 0000000..1894ea9 --- /dev/null +++ b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/iterators/xml/oaiRecord.xml @@ -0,0 +1,36 @@ + + + + + webcrawl____::6469a2bd0de26af9612c1869d19edd18 + webcrawl____::6469a2bd0de26af9612c1869d19edd18 + + + webcrawl____ + + + Independent Associations of Glucose Status and Arterial + Stiffness With Left Ventricular Diastolic Dysfunction An 8-year + follow-up of the Hoorn Study + 2012-01-01 + AMER DIABETES ASSOC + eng + DIABETES CARE + + + + + 10.2337/dc11-1336 + webcrawl____::6469a2bd0de26af9612c1869d19edd18 + CLOSED + 0001 + + http://dx.doi.org/10.2337/dc11-1336 + + + \ No newline at end of file diff --git a/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/iterators/xml/opendoar.xml.gz b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/iterators/xml/opendoar.xml.gz new file mode 100644 index 0000000..4ad43fb Binary files /dev/null and b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/iterators/xml/opendoar.xml.gz differ diff --git a/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/iterators/xml/singleRepo.xml b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/iterators/xml/singleRepo.xml new file mode 100644 index 0000000..c6791f5 --- /dev/null +++ b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/iterators/xml/singleRepo.xml @@ -0,0 +1,36 @@ + + + + Copyright 2012, University of Nottingham + OpenDOAR data is available for re-use under a Creative Commons Attribution-Non-Commercial-Share Alike licence + + + Aalborg University - Electronic Library + + Y + http://www.aub.aau.dk/ + + Aalborg Universitetsbiblioteks + + Y + http://www.aub.aau.dk/ + Aalborg Universitet + + Y + http://www.aau.dk/ + Aalborg Universitetsbibliotek, Langagervej 2, 9220 Aalborg + + DK + Denmark + + 57.035000 + 9.932300 + 96 359400 + + This site is a university repository providing access to the research papers and publications of lecturers, and Ph.D theses, of Aalborg University. This site is poor in supporting information and background documentation, however contact details are readily available if problems are encountered. + + 35 + 2012-06-27 + + + \ No newline at end of file diff --git a/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/iterators/xml/weirdRecords.xml b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/iterators/xml/weirdRecords.xml new file mode 100644 index 0000000..7d62dc0 --- /dev/null +++ b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/iterators/xml/weirdRecords.xml @@ -0,0 +1,129 @@ + + +
+ oai:HAL:hal-00782129v1 + 2013-01-29 + type:COMM + subject:info + collection:UNIV-RENNES1 + collection:CNRS + collection:INRIA + collection:INRIA-RENNES + collection:IRISA + collection:IRISA_SET + collection:TESTINRIA +
+ + + HAL CCSD + Coupling 3G with DVB networks for low cost services + Jedidi, Azza + Tlais, Mazen + Weis, Frédéric + ACES (INRIA - IRISA) ; INRIA - Université de Rennes 1 - Institut National des Sciences Appliquées (INSA) - Rennes - CNRS + International audience + MASS'09 : International Conference on Management and Service Science + Wuhan, China + IEEE + IEEE + hal-00782129 + https://hal.inria.fr/hal-00782129 + https://hal.inria.fr/hal-00782129 + IEEE. MASS'09 : International Conference on Management and Service Science, Sep 2009, Wuhan, China. IEEE, pp.1-5, &lt;10.1109/ICMSS.2009.5303609&gt; + DOI : 10.1109/ICMSS.2009.5303609 + en + [INFO.INFO-OH] Computer Science/Other + Conference papers + Next generation networks will result from the convergence of the different existing technologies, taking benefit from their complementary properties . In this context, recent research has addressed Digital Video Broadcast (DVB) networks, which benefit of very high broadcast capacities, and has tried to couple them with complementary networks. In our work, we focus on DVB-SH, satellite services for hand-held devices, which is a hybrid (satellite/terrestrial) standard. We couple DVB-SH with a 3G cellular network, thus providing a bidirectional interactivity path. DVB-SH benefits from a very high bandwidth capacity that allows unidirectional IP-TV channels broadcast. A residual bandwidth in the DVB-SH path may still be available because of two reasons; the variable bit rates of served flows and/or some DVB reserved channels by the 3G provider. In our work, we focus on this small residual bandwidth and its potential utilization. The idea is to realize an efficient switching of IP data, coming from 3G networks, to the residual bandwidth of DVB Networks. The goal is to use this architecture in order to provide interactive low cost services over DVB networks. Keyword: Network convergence, DVB, 3G, residual bandwidth, switching, multimedia, low cost services + 2009-09-16 + + +
+ +
+ oai:HAL:hal-00782130v1 + 2013-06-03 + type:COMM + subject:shs + collection:CNRS + collection:UNIV-MONTP3 + collection:SHS + collection:PRAXILING + collection:AO-LINGUISTIQUE +
+ + + HAL CCSD + Révolution et disparition + Steuckardt, Agnès + PRAXILING UMR5267 (Praxiling) ; Université Paul Valéry - Montpellier III - CNRS + International audience + Disparitions et changements linguistiques + Disparitions et changements linguistiques + Claire Badiou-Monferran; Thomas Verjans + hal-00782130 + https://hal.archives-ouvertes.fr/hal-00782130 + https://hal.archives-ouvertes.fr/hal-00782130 + Claire Badiou-Monferran; Thomas Verjans. Disparitions et changements linguistiques, Dec 2010, France. à paraître + fr + Changement linguistique + Référent + Révolution française + [SHS.LANGUE] Humanities and Social Sciences/Linguistics + Conference papers + Cette étude suit, du début de l'âge classique à la Révolution, les représentations de la disparition linguistique : si elles s'opposent sur la place réservée aux mots du passé, elles se rejoignent dans une conception de la langue que Sylvain Auroux (1986) qualifiait de " politique ", où est attribué aux locuteurs un rôle de véritables " sujets de la langue ". Dans un second temps, elle met à l'épreuve de l'expérience cette conception politique de la disparition, en prenant l'exemple des abolitions opérées pendant la période révolutionnaire. + 2011 + + +
+ +
+ oai:HAL:hal-00504740v2 + 2013-06-12 + type:COMM + subject:info + subject:spi + collection:L2S + collection:SUPELEC + collection:SUP_LSS + collection:SUP_SIGNAUX +
+ + + HAL CCSD + GPU implementation of a 3D bayesian CT algorithm and its application on real foam reconstruction + Gac, Nicolas + Vabre, Alexandre + Mohammad-Djafari, Ali + Rabanal, Asier + Buyens, Fanny + Laboratoire des signaux et systèmes (L2S) ; Université Paris XI - Paris Sud - SUPELEC - UMR8506 CNRS + Laboratoire d'Intégration des Systèmes et des Technologies (LIST) + Financement OMTE DIGITEO + 5 pages + International audience + The 1st CT Meeting Proceedings + The First International Conference on Image Formation in X-Ray Computed Tomography + Salt Lake City, United States + hal-00504740 + https://hal.archives-ouvertes.fr/hal-00504740 + https://hal.archives-ouvertes.fr/hal-00504740/document + https://hal.archives-ouvertes.fr/hal-00504740 + The First International Conference on Image Formation in X-Ray Computed Tomography, Jun 2010, Salt Lake City, United States. http://www.ucair.med.utah.edu/CTmeeting/ProceedingsCTMeeting2010.pdf, pp.151-155 + en + Computed Tomograhy (CT) + Iterative 3D reconstruction + Bayesian estimation + GPU implementation + [INFO.INFO-IM] Computer Science/Medical Imaging + [INFO.INFO-DC] Computer Science/Distributed, Parallel, and Cluster Computing + [INFO.INFO-TS] Computer Science/Signal and Image Processing + [SPI.SIGNAL] Engineering Sciences/Signal and Image processing + Conference papers + A great number of image reconstruction algorithms, based on analytical filtered backprojection, are implemented for X-ray Computed Tomography (CT) [1, 3]. The limits of these methods appear when the number of projections is small, and/or not equidistributed around the object. In this specific context, iterative algebraic methods are implemented. A great number of them are mainly based on least square criterion. Recently, we proposed a regularized version based on Bayesian estimation approach. The main problem that appears when using such methods as well as any iterative algebraic methods is the computation time and especially for projection and backprojection steps. In this paper, first we show how we implemented some main steps of such algorithems which are the forward projection and backward backprojection steps on GPU hardware, and then we show some results on real application of the 3D tomographic reconstruction of metallic foams from a small number of projections. Through this application, we also show the good quality of results as well as a significant speed up of the computation with GPU implementation. + projet TomoX + 2010-06-21 + + +
+
\ No newline at end of file diff --git a/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/iterators/xml/weirdRecords.xml.gz b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/iterators/xml/weirdRecords.xml.gz new file mode 100644 index 0000000..da42d87 Binary files /dev/null and b/dnet-core-components/src/test/resources/eu/dnetlib/miscutils/iterators/xml/weirdRecords.xml.gz differ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..4e62568 --- /dev/null +++ b/pom.xml @@ -0,0 +1,270 @@ + + + + 4.0.0 + dnet-core + eu.dnetlib + pom + 1.0.0-SNAPSHOT + + + + dnet-core-components + + + + + + GNU Affero General Public License, Version 3 + https://www.gnu.org/licenses/agpl-3.0.html + repo + + + + + + + Redmine + https://issue.openaire.research-infrastructures.eu/projects/dnet + + + + + + jenkins + https://jenkins-dnet.d4science.org + + + + + + scm:git:gitea@code-repo.d4science.org:D-Net/dnet-core.git + scm:git:gitea@code-repo.d4science.org:D-Net/dnet-core.git + https://code-repo.d4science.org/D-Net/dnet-core + HEAD + + + + + + + + + + + dnet-deps + dnet-dependencies + http://maven.research-infrastructures.eu/nexus/content/repositories/dnet-deps + default + + + dnet45-releases + D-Net 45 Releases + http://maven.research-infrastructures.eu/nexus/content/repositories/dnet45-releases + default + + true + + + + + + + + + + + org.apache.commons + commons-lang3 + 3.5 + + + commons-codec + commons-codec + 1.9 + + + dom4j + dom4j + 1.6.1 + + + jaxen + jaxen + 1.1.6 + + + saxonica + saxon + 9.1.0.8 + + + saxonica + saxon-dom + 9.1.0.8 + + + jgrapht + jgrapht + 0.7.2 + + + net.sf.ehcache + ehcache + 2.8.0 + + + com.google.guava + guava + 23.3-jre + + + org.mockito + mockito-core + 1.6 + test + + + junit + junit + 4.9 + test + + + org.springframework + spring-test + [4.2.5.RELEASE] + false + + + commons-io + commons-io + 2.5 + test + + + + + + + + + + target + target/classes + ${project.artifactId}-${project.version} + target/test-classes + + + + + org.apache.maven.plugins + maven-release-plugin + 2.5 + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + UTF-8 + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.0.2 + + + + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + attach-sources + verify + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + true + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + true + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.0.0 + + + + + + + + org.apache.maven.plugins + maven-release-plugin + 2.5.3 + + + + + + org.apache.maven.wagon + wagon-ssh + 2.10 + + + + + + + dnet45-snapshots + D-Net 45 Snapshots + http://maven.research-infrastructures.eu/nexus/content/repositories/dnet45-snapshots + default + + + dnet45-releases + D-Net 45 Releases + http://maven.research-infrastructures.eu/nexus/content/repositories/dnet45-releases + default + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + true + + + + + + +