Nuiton-utils-commits
Threads by month
- ----- 2026 -----
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
June 2011
- 3 participants
- 4 discussions
r2151 - in trunk/nuiton-utils: . src/main/java/org/nuiton/util src/test/java/org/nuiton/util
by bpoussin@users.nuiton.org 21 Jun '11
by bpoussin@users.nuiton.org 21 Jun '11
21 Jun '11
Author: bpoussin
Date: 2011-06-21 13:00:42 +0200 (Tue, 21 Jun 2011)
New Revision: 2151
Url: http://nuiton.org/repositories/revision/nuiton-utils/2151
Log:
Implantation de Map multikey en se basant sur le code des matrix (test a ameliorer/faire)
(commit pour ne pas perdre le travail)
Added:
trunk/nuiton-utils/src/main/java/org/nuiton/util/MatrixMap.java
trunk/nuiton-utils/src/test/java/org/nuiton/util/MatrixMapTest.java
Modified:
trunk/nuiton-utils/pom.xml
Modified: trunk/nuiton-utils/pom.xml
===================================================================
--- trunk/nuiton-utils/pom.xml 2011-06-16 08:31:43 UTC (rev 2150)
+++ trunk/nuiton-utils/pom.xml 2011-06-21 11:00:42 UTC (rev 2151)
@@ -41,6 +41,11 @@
<dependencies>
<dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ </dependency>
+
+ <dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</dependency>
Added: trunk/nuiton-utils/src/main/java/org/nuiton/util/MatrixMap.java
===================================================================
--- trunk/nuiton-utils/src/main/java/org/nuiton/util/MatrixMap.java (rev 0)
+++ trunk/nuiton-utils/src/main/java/org/nuiton/util/MatrixMap.java 2011-06-21 11:00:42 UTC (rev 2151)
@@ -0,0 +1,2296 @@
+package org.nuiton.util;
+
+import java.io.Serializable;
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.RandomAccess;
+import org.apache.commons.lang.ObjectUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Permet de stocker des informations dans une matrix a N dimension
+ * Si lors de l'ajout on indique une dimension qui n'existe pas encore ou
+ * un element dans une dimension qui n'existe pas, la matrice ajoute
+ * automatiquement les elements manquant pour que l'ajout se passe bien.
+ * <p>
+ * MatrixMap permet de stocker les elements avec des cles de n'importe quel
+ * type. Les coordonnees utilisant ces objets sont converti en coordonnees
+ * numeriques qui est la seul chose que sait gere Matrix. Ces coordonnees
+ * numeriques sont alors convertis en coordonnees lineaire pour le stockage
+ * dans Vector. On decoupe ainsi les problemes et on minimise le stockage et
+ * certain traitement sur les données puisqu'au final toutes les données sont
+ * dans une simple liste.
+ * <p>
+ * Pour créer une nouvelle matrice, il faut utiliser une des méthodes de
+ * {@link MatrixMap#Factory}
+ *
+ * @author poussin
+ * @version $Revision$
+ * @since 2.2.1
+ *
+ * Last update: $Date$
+ * by : $Author$
+ */
+public interface MatrixMap<E> extends Iterable<E> {
+
+ /**
+ * Classe permettant la creation de matrice
+ */
+ static public class Factory {
+ static public <T> MatrixMap<T> create(List ... semantics) {
+ MatrixMap<T> result = new MatrixMapFixed<T>(semantics);
+ return result;
+ }
+
+ static public <T> MatrixMap<T> create(String name, List... semantics) {
+ MatrixMap<T> result = new MatrixMapFixed<T>(name, semantics);
+ return result;
+ }
+
+ static public <T> MatrixMap<T> create(String name, String[] dimNames, List... semantics) {
+ MatrixMap<T> result = new MatrixMapFixed<T>(name, dimNames, semantics);
+ return result;
+ }
+
+ static public <T> MatrixMap<T> create(MatrixMap<T> matrix) {
+ MatrixMap<T> result = new MatrixMapFixed<T>(matrix);
+ return result;
+ }
+
+ static public <T> MatrixMap<T> createElastic(List ... semantics) {
+ MatrixMap<T> result = create(semantics);
+ result = createElastic(result);
+ return result;
+ }
+
+ static public <T> MatrixMap<T> createElastic(String name, List... semantics) {
+ MatrixMap<T> result = create(name, semantics);
+ result = createElastic(result);
+ return result;
+ }
+
+ static public <T> MatrixMap<T> createElastic(String name, String[] dimNames, List... semantics) {
+ MatrixMap<T> result = create(name, dimNames, semantics);
+ result = createElastic(result);
+ return result;
+ }
+
+ static public <T> MatrixMap<T> createElastic(MatrixMap<T> matrix) {
+ MatrixMap<T> result = new MatrixMapElastic<T>(matrix);
+ return result;
+ }
+ }
+
+ @Override
+ public MatrixMapIterator<E> iterator();
+
+ /**
+ * Copy la matrice pour pouvoir la modifier sans perdre les donnees
+ * initiales.
+ *
+ * @return new matrix
+ */
+ public MatrixMap<E> copy();
+
+ public SemanticList[] getSemantics();
+
+ public SemanticList getSemantic(int dim);
+
+ public void setSemantic(int dim, List sem);
+
+ public void setName(String name);
+
+ public String getName();
+
+ public String[] getDimensionNames();
+
+ public void setDimensionNames(String[] names);
+
+ public void setDimensionName(int dim, String name);
+
+ public String getDimensionName(int dim);
+
+ public int getDimCount();
+
+ public int[] getDim();
+
+ public int getDim(int d);
+
+ /**
+ * Applique sur chaque element de la matrice la fonction f
+ *
+ * @param f la fonction a appliquer
+ * @return Retourne la matrice elle meme. Les modifications sont faites directement
+ * dessus
+ */
+ public MatrixMap<E> map(MapFunction<E> f);
+
+ /**
+ * Retourne l'element a une certaine position en utilisant des indices
+ * ex: 2,3,1
+ * @param coordinates
+ * @return
+ */
+ public E getValueIndex(int ... coordinates);
+
+ /**
+ * Modifie l'element a une certaine position en utilisant des indices
+ * ex: 2,3,1
+ * @param value la nouvelle valeur
+ * @param coordinates
+ * @return
+ */
+ public void setValueIndex(E value, int ... coordinates);
+
+ /**
+ * Retourne l'element a une certaine position en utilisant les semantiques
+ *
+ * @param coordinates
+ * @return
+ */
+ public E getValue(Object ... coordinates);
+
+ /**
+ * Modifie l'element a une certaine position en utilisant les semantiques
+ *
+ * @param value la nouvelle valeur
+ * @param coordinates
+ * @return
+ */
+ public void setValue(E value, Object ... coordinates);
+
+ /**
+ * Verifie que deux matrices sont completement equals
+ * (dimension, semantique, nom, valeur, ...)
+ * @param mat
+ * @return
+ */
+ public boolean equals(MatrixMap mat);
+
+ /**
+ * Verifie si les matrices sont egales en ne regardant que les valeurs et
+ * pas les semantiques
+ *
+ * @param mat
+ * @return equality on values
+ */
+ public boolean equalsValues(MatrixMap<E> mat);
+
+ /**
+ * Representation string de la matrice quelque soit le nombre de dimension
+ * @return
+ */
+ public String toStringGeneric();
+
+ /**
+ * Indique si les semantiques passées en argument sont valable pour la
+ * matrice courante
+ *
+ * @param semantics
+ * @return
+ */
+ public boolean isValidCoordinates(Object[] semantics);
+
+ /**
+ * Copie une matrice dans la matrice actuelle. La matrice à copier à le même
+ * nombre de dimension. Si la matrice à copier est trop grande seul les
+ * éléments pouvant être copier le seront.
+ *
+ * @param mat la matrice à copier
+ * @return return la matrice courante.
+ */
+ public MatrixMap paste(MatrixMap<E> mat);
+
+ /**
+ * Permet de prendre une sous matrice dans la matrice courante. La sous
+ * matrice a le même nombre de dimensions mais sur une des dimensions on ne
+ * prend que certain élément.
+ *
+ * @param dim la dimension dans lequel on veut une sous matrice
+ * @param start la position dans dim d'ou il faut partir pour prendre la
+ * sous matrice. 0 <= start < dim.size si start est négatif alors
+ * la position de départ est calculé par rapport à la fin de la
+ * dimension, pour avoir le dernier élément il faut passer -1
+ * @param nb le nombre d'élément à prendre dans la dimension si nb est
+ * inférieur ou égal à 0 alors cela indique qu'il faut prendre
+ * tous les éléments jusqu'à la fin de la dimension.
+ * @return new matrix
+ */
+ public MatrixMap<E> getSubMatrix(int dim, Object start, int nb);
+
+ /**
+ * Permet de prendre une sous matrice dans la matrice courante. La sous
+ * matrice a le même nombre de dimensions mais sur une des dimensions on ne
+ * prend que certain élément.
+ *
+ * @param dim la dimension dans lequel on veut une sous matrice
+ * @param elem les éléments dans la dimension à conserver
+ * @return new matrix
+ */
+ public MatrixMap<E> getSubMatrix(int dim, Object... elem);
+
+ /**
+ * Permet de prendre une sous matrice dans la matrice courante.
+ *
+ * Réalise plusieurs appels à {@link #getSubMatrix(int, Object...)} suivant
+ * l'implémentation.
+ *
+ * @param elem les éléments dans la dimension à conserver
+ * @return new matrix
+ */
+ public MatrixMap<E> getSubMatrix(Object[]... elems);
+
+ /**
+ * Reduit la matrice de sorte que toutes les dimensions qui n'ont qu'un
+ * élement soit supprimée. Au pire cette méthode retourne une matrice à une
+ * seule dimension à un seul élément.
+ *
+ * @return une nouvelle matrice plus petite que la matrice actuelle ou egal
+ * s'il n'y a aucune dimension à supprimer
+ */
+ public MatrixMap<E> reduce();
+
+ /**
+ * Reduit le matrice seulement sur les dimensions passées en argument. Si
+ * une des dimensions passées en arguement n'a pas qu'un seul élément, cette
+ * dimension n'est pas prise en compte.
+ *
+ * @param dims les dimensions sur lequel il faut faire la reduction
+ * @return une nouvelle matrice
+ */
+ public MatrixMap<E> reduceDims(int... dims);
+ /**
+ * Reduit la matrice de sorte que toutes les dimensions qui n'ont qu'un
+ * élement soit supprimée. Au pire cette méthode retourne une matrice à une
+ * seule dimension à un seul élément.
+ *
+ * @param minNbDim le nombre minimum de dimension que l'on souhaite pour la
+ * matrice résultat
+ * @return une nouvelle matrice plus petite que la matrice actuelle ou egal
+ * s'il n'y a aucune dimension à supprimer
+ */
+ public MatrixMap<E> reduce(int minNbDim);
+
+ /**
+ * Permet de retourner une nouvelle matrice ayant les semantiques passées
+ * en parametre. La nouvelle matrice contient les données de l'ancienne
+ * matrice par copie en fonction des semantiques
+ *
+ * @param sems
+ * @return
+ */
+ public MatrixMap<E> extend(Object... sems);
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // C L A S S E I N T E R N E
+ //
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Classe contenant des méthodes statiques pour aider a la manipulation
+ * des matrices
+ */
+ static public class MatrixHelper {
+
+ /**
+ * Mais en forme un texte pour qu'il fasse exactement la longueur
+ * demandee (length). Si length est possitif alors s'il y besoin
+ * d'ajouter des espaces, ils seront mis devant le texte, sinon il
+ * seront mis apres le texte
+ *
+ * @param o l'objet a convertir en string
+ * @param length la longueur de representation souhaite
+ * @param valueIfNull la valeur a utilise si l'objet est null
+ * @return
+ */
+ public static String format(Object o, int length, String valueIfNull) {
+ if (o == null) {
+ o = valueIfNull;
+ }
+ int absLength = Math.abs(length);
+
+ String result = String.valueOf(o);
+ if (absLength > 3) {
+ result = StringUtils.abbreviate(result, absLength);
+ }
+ if (length < 0) {
+ result = StringUtils.leftPad(result, absLength);
+ } else if (length > 0) {
+ result = StringUtils.rightPad(result, absLength);
+ }
+
+ return result;
+ }
+
+ /**
+ * Permet de convertir des coordonnées définies par des entiers en coordonnées
+ * semantique par des objets
+ *
+ * @param semantics la semantique à utilisé pour la conversion
+ * @param coordinates les coordonnées à convertir
+ * @return un tableau donnant les coordonnées sous forme semantique s'il n'y
+ * a pas de semantique (liste pleine de null) alors un objet Integer
+ * est créer pour représenter la semantique de la dimension.
+ */
+ public static Object[] dimensionToSemantics(List[] semantics,
+ int[] coordinates) {
+ Object[] result = new Object[coordinates.length];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = semantics[i].get(coordinates[i]);
+ }
+ return result;
+ }
+
+ /**
+ * Permet de convertir des coordonnées sémantiques en coordonnées défini par
+ * des entiers. Cette fonction est l'inverse de
+ * {@link #dimensionToSemantics}.
+ *
+ * @param semantics la semantique à utiliser pour la conversion
+ * @param coordinates les coordonnées sémantique
+ * @return les coordonnées en entier.
+ */
+ public static int[] semanticsToDimension(List[] semantics,
+ Object[] coordinates) {
+ int[] result = new int[coordinates.length];
+ for (int i = 0; i < coordinates.length; i++) {
+ result[i] = indexOf(semantics, i, coordinates[i]);
+ }
+ return result;
+ }
+
+ /**
+ * Permet de retrouver la position d'un objet dans une liste
+ *
+ * @param semantics la semantique à utilisé pour la recherche
+ * @param dim la dimension dans lequel il faut faire la recherche
+ * @param o l'objet à rechercher
+ * @return la position de l'objet dans la dimension demandée
+ *
+ * @throws NoSuchElementException If element doesn't exists
+ */
+ public static int indexOf(List[] semantics, int dim, Object o)
+ throws NoSuchElementException {
+ int result = -1;
+ if ((0 <= dim) && (dim < semantics.length)) {
+ result = semantics[dim].indexOf(o);
+ }
+ if (result == -1) {
+ throw new NoSuchElementException(
+ "L'objet passé en argument n'a pas été retrouvé ou la dimension donnée ne convient pas:"
+ + o + " in " + semantics[dim]);
+ }
+ return result;
+ }
+
+ /**
+ * Permet de savoir si deux dimension sont identiques.
+ *
+ * @param dim1 first dimensions
+ * @param dim2 second dimensions
+ * @return dimension equality
+ */
+ public static boolean sameDimension(int[] dim1, int[] dim2) {
+ return Arrays.equals(dim1, dim2);
+ }
+
+ }
+
+ /**
+ * Iterateur de matrice
+ *
+ * @param <E>
+ */
+ static public interface MatrixMapIterator<E> extends Iterator<E> {
+ public int[] getCoordinates();
+ public E getValue();
+ public void setValue(E value);
+ public Object[] getSemanticsCoordinates();
+ }
+
+ static public class MatrixMapIteratorImpl<E> implements MatrixMapIterator<E> { // MatrixMapIteratorImpl
+
+ protected MatrixIterator<E> iterator = null;
+ protected List[] semantics = null;
+ protected int pos = 0;
+
+ /**
+ * @param iterator la matrice sur lequel l'iterator doit travailler
+ * @param semantics la semantique de matrix, si matrix n'a pas de semantique
+ * alors il faut passer null
+ */
+ public MatrixMapIteratorImpl(MatrixIterator<E> iterator, List[] semantics) {
+ this.iterator = iterator;
+ this.semantics = semantics;
+ pos = 0;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
+
+ @Override
+ public E next() {
+ return iterator.next();
+ }
+
+ @Override
+ public void remove() {
+ iterator.remove();
+ }
+
+ public int[] getCoordinates() {
+ return iterator.getCoordinates();
+ }
+
+ public E getValue() {
+ return iterator.getValue();
+ }
+
+ public void setValue(E value) {
+ iterator.setValue(value);
+ }
+
+ public Object[] getSemanticsCoordinates() {
+ Object[] result = null;
+ if (semantics != null) {
+ int[] coordinates = getCoordinates();
+ result = MatrixHelper.dimensionToSemantics(semantics,
+ coordinates);
+ }
+ return result;
+ }
+
+ } // MatrixMapIteratorImpl
+
+ /**
+ * Collection particuliere utilisee pour la stockage des semantiques.
+ * <p>
+ * Sert a optimiser la recherche de la position d'une donnee dans la liste.
+ * Permet aussi de verifier qu'on ajoute pas de doublon dans la liste
+ *
+ * @param <T>
+ */
+ public static class SemanticList<T> extends AbstractList<T> implements RandomAccess {
+
+ protected ArrayList<T> datas = null;
+ protected Map<T, Integer> index = new HashMap<T, Integer>();
+
+ public SemanticList() {
+ this(new ArrayList<T>());
+ }
+
+ public SemanticList(Collection<T> c) {
+ datas = new ArrayList<T>(c);
+ }
+
+ /*
+ * @see java.util.AbstractList#get(int)
+ */
+ @Override
+ public T get(int index) {
+ T result = datas.get(index);
+ return result;
+ }
+
+ @Override
+ public void add(int index, T element) {
+ datas.add(index, element);
+ this.index.clear();
+ }
+
+ @Override
+ public T set(int index, T element) {
+ T result = datas.set(index, element);
+ this.index.clear();
+ return result;
+ }
+
+ @Override
+ public T remove(int index) {
+ T result = super.remove(index);
+ this.index.clear();
+ return result;
+ }
+
+
+ /*
+ * @see java.util.AbstractCollection#size()
+ */
+ @Override
+ public int size() {
+ int result = datas.size();
+ return result;
+ }
+
+ /*
+ * @see java.util.AbstractList#indexOf(java.lang.Object)
+ */
+ @Override
+ public int indexOf(Object o) {
+ Map<T, Integer> index = getIndex();
+ Integer result = index.get(o);
+ int resultIndex = -1;
+ if (result != null) {
+ resultIndex = result.intValue();
+ }
+ return resultIndex;
+ }
+
+ protected Map<T, Integer> getIndex() {
+ if (index.isEmpty()) {
+ for (int i = 0; i < datas.size(); i++) {
+ index.put(datas.get(i), Integer.valueOf(i));
+ }
+ }
+ return index;
+ }
+ }
+
+ /**
+ * Implantation particuliere de matrice, qui lorsqu'on lui passe des
+ * dimension qui n'existe pas, elle les ajoutes dans les semantiques. Ceci
+ * n'est vrai que pour le set avec des semantiques, le set avec des indices
+ * ne rend pas la matrice elastique.
+ * <p>
+ * Cette classe fonctionne avec une matrice interne que l'on change lorsque
+ * l'on a besoin de modifier les dimensions. Le changement de dimension
+ * a donc un cout (creation d'une nouvelle matrice, copie des elements)
+ * <p>
+ * Si on cree une sous matrice, et que l'on modifie la matrice mere
+ * La sous matrice n'est pas impacter, puisqu'elle est base sur l'ancienne
+ * represention interne de la matrice elastique, les deux matrices n'ont donc
+ * plus de lien.
+ * <p>
+ * Les methodes reduce et extend retourne de nouvelle matrice qui ne sont
+ * pas elastique. Si on veut qu'elle le soit, il faut les reencapsuler
+ *
+ * @param <E>
+ */
+ static public class MatrixMapElastic<E> implements MatrixMap<E> {
+
+ protected MatrixMap<E> internalMatrixMap;
+
+ public MatrixMapElastic() {
+ internalMatrixMap = Factory.create();
+ }
+
+ public MatrixMapElastic(MatrixMap<E> m) {
+ setInternalMatrixMap(m);
+ }
+
+ public MatrixMap<E> getInternalMatrixMap() {
+ return internalMatrixMap;
+ }
+
+ public void setInternalMatrixMap(MatrixMap<E> internalMatrixMap) {
+ this.internalMatrixMap = internalMatrixMap;
+ }
+
+ public MatrixMapIterator<E> iterator() {
+ return getInternalMatrixMap().iterator();
+ }
+
+ public MatrixMap<E> copy() {
+ return getInternalMatrixMap().copy();
+ }
+
+ public SemanticList[] getSemantics() {
+ return getInternalMatrixMap().getSemantics();
+ }
+
+ public SemanticList getSemantic(int dim) {
+ return getInternalMatrixMap().getSemantic(dim);
+ }
+
+ public void setSemantic(int dim, List sem) {
+ getInternalMatrixMap().setSemantic(dim, sem);
+ }
+
+ public void setName(String name) {
+ getInternalMatrixMap().setName(name);
+ }
+
+ public String getName() {
+ return getInternalMatrixMap().getName();
+ }
+
+ public String[] getDimensionNames() {
+ return getInternalMatrixMap().getDimensionNames();
+ }
+
+ public void setDimensionNames(String[] names) {
+ getInternalMatrixMap().setDimensionNames(names);
+ }
+
+ public void setDimensionName(int dim, String name) {
+ getInternalMatrixMap().setDimensionName(dim, name);
+ }
+
+ public String getDimensionName(int dim) {
+ return getInternalMatrixMap().getDimensionName(dim);
+ }
+
+ public int getDimCount() {
+ return getInternalMatrixMap().getDimCount();
+ }
+
+ public int[] getDim() {
+ return getInternalMatrixMap().getDim();
+ }
+
+ public int getDim(int d) {
+ return getInternalMatrixMap().getDim(d);
+ }
+
+ public MatrixMap<E> map(MapFunction<E> f) {
+ return getInternalMatrixMap().map(f);
+ }
+
+ public E getValueIndex(int... coordinates) {
+ return getInternalMatrixMap().getValueIndex(coordinates);
+ }
+
+ public void setValueIndex(E value, int... coordinates) {
+ // la matrice est elastique que pour le set avec des semantics
+ getInternalMatrixMap().setValueIndex(value, coordinates);
+ }
+
+ public E getValue(Object... coordinates) {
+ return getInternalMatrixMap().getValue(coordinates);
+ }
+
+ public void setValue(E value, Object... coordinates) {
+ // check si les coordonnees sont valide.
+ // si non valide alors on extend la matrice interne
+ // et on appelle sur la nouvelle matrice interne
+ if (!isValidCoordinates(coordinates)) {
+ MatrixMap<E> newMatrixMap = getInternalMatrixMap().extend(coordinates);
+ setInternalMatrixMap(newMatrixMap);
+ }
+ getInternalMatrixMap().setValue(value, coordinates);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return getInternalMatrixMap().equals(obj);
+ }
+
+ public boolean equals(MatrixMap mat) {
+ return getInternalMatrixMap().equals(mat);
+ }
+
+ public boolean equalsValues(MatrixMap<E> mat) {
+ return getInternalMatrixMap().equalsValues(mat);
+ }
+
+ @Override
+ public String toString() {
+ return getInternalMatrixMap().toString();
+ }
+
+ public String toStringGeneric() {
+ return getInternalMatrixMap().toStringGeneric();
+ }
+
+ public boolean isValidCoordinates(Object[] semantics) {
+ return getInternalMatrixMap().isValidCoordinates(semantics);
+ }
+
+ public MatrixMap paste(MatrixMap<E> mat) {
+ return getInternalMatrixMap().paste(mat);
+ }
+
+ public MatrixMap<E> getSubMatrix(int dim, Object start, int nb) {
+ return getInternalMatrixMap().getSubMatrix(dim, start, nb);
+ }
+
+ public MatrixMap<E> getSubMatrix(int dim, Object... elem) {
+ return getInternalMatrixMap().getSubMatrix(dim, elem);
+ }
+
+ public MatrixMap<E> getSubMatrix(Object[]... elems) {
+ return getInternalMatrixMap().getSubMatrix(elems);
+ }
+
+ public MatrixMap<E> reduce() {
+ return getInternalMatrixMap().reduce();
+ }
+
+ public MatrixMap<E> reduceDims(int... dims) {
+ return getInternalMatrixMap().reduceDims(dims);
+ }
+
+ public MatrixMap<E> reduce(int minNbDim) {
+ return getInternalMatrixMap().reduce(minNbDim);
+ }
+
+ public MatrixMap<E> extend(Object... sems) {
+ return getInternalMatrixMap().extend(sems);
+ }
+
+ }
+
+ /**
+ * Implantation de MatrixMap dont les dimensions sont fixees a la creation
+ * Les dimensions ne change plus par la suite
+ */
+ static public class MatrixMapFixed<E> extends AbstractMatrixMap<E> {
+ /** to use log facility, just put in your code: log.info(\"...\"); */
+ static private Log log = LogFactory.getLog(MatrixMapFixed.class);
+
+ protected Matrix<E> matrix = null;
+
+ public MatrixMapFixed(List ... semantics) {
+ super(semantics);
+ }
+
+ public MatrixMapFixed(String name, List... semantics) {
+ this(semantics);
+ setName(name);
+ }
+
+ public MatrixMapFixed(String name, String[] dimNames, List... semantics) {
+ this(name, semantics);
+ for (int i = 0; dimNames != null && i < dimNames.length; i++) {
+ setDimensionName(i, dimNames[i]);
+ }
+ }
+
+ public MatrixMapFixed(MatrixMap<E> matrix) {
+ this(matrix.getName(), matrix.getDimensionNames(), matrix.getSemantics());
+ this.pasteIndex(matrix);
+ }
+
+ protected Matrix<E> getMatrix(){
+ if (matrix == null) {
+ matrix = new Matrix<E>(getDim());
+ }
+ return matrix;
+ }
+
+ @Override
+ public MatrixMapIterator<E> iterator() {
+ return new MatrixMapIteratorImpl<E>(getMatrix().iterator(), getSemantics());
+ }
+
+ @Override
+ public MatrixMap<E> map(MapFunction<E> f) {
+ getMatrix().data.map(f);
+ return this;
+ }
+
+ @Override
+ public E getValueIndex(int ... coordinates) {
+ if (coordinates.length == 0) {
+ throw new IllegalArgumentException("Coordinates must not be empty");
+ }
+ return getMatrix().getValue(coordinates);
+ }
+
+ /**
+ * Modifie un element de la matrice en fonction des dimensions passé en
+ * paramètre.<br>
+ *
+ * Exemple: Si on a un matrice 3D.<br>
+ * m.set(v, [1,1,1]) modifie un element de la matrice.<br>
+ *
+ * @param dimensions les différentes dimension à extraire.
+ *
+ * @param d l'entier double qui doit remplacer l'entier double spécifié par
+ * l'argument dimensions
+ */
+ @Override
+ public void setValueIndex(E value, int ... coordinates) {
+ if (coordinates.length == 0) {
+ throw new IllegalArgumentException("Coordinates must not be empty");
+ }
+ getMatrix().setValue(coordinates, value);
+ }
+
+ /**
+ * Copie une matrice dans la matrice actuelle. La matrice à copier à le même
+ * nombre de dimension. Si la matrice à copier est trop grande seul les
+ * éléments pouvant être copier le seront.
+ *
+ * @param origin le point à partir duquel il faut faire la copie
+ * @param mat la matrice à copier
+ * @return return la matrice courante.
+ */
+ public MatrixMap<E> paste(int[] origin, MatrixMap<E> mat) {
+ if (mat != null) {
+ // si les matrice mat et this on les memes dimensions
+ // et que origin est 0, on optimise en appeler une methode paste
+ // sur Matrix qui l'appel sur le vector
+
+ // permet de savoir si l'origin est bien le point 0 de la matrice
+ boolean origin0 = true;
+ for (int i = 0; i < origin.length && origin0; i++) {
+ origin0 = origin0 && origin[i] == 0;
+ }
+ if (origin0
+ && mat instanceof MatrixMapFixed
+ && Arrays.equals(mat.getDim(), this.getDim())) {
+ getMatrix().data.paste(((MatrixMapFixed<E>)mat).getMatrix().data);
+ } else {
+ super.paste(origin, mat);
+ }
+ }
+ return this;
+ }
+
+ }
+
+ /**
+ * Classe abstraite permettant de facilement implanter les matrice fixe,
+ * elastique et submatrix
+ *
+ * @param <E>
+ */
+ static public abstract class AbstractMatrixMap<E> implements MatrixMap<E> {
+
+ /** to use log facility, just put in your code: log.info(\"...\"); */
+ static private Log log = LogFactory.getLog(AbstractMatrixMap.class);
+
+ protected String name = null;
+
+ protected String[] dimNames = null;
+
+ protected int[] dim = null;
+
+ protected SemanticList[] semantics = null;
+
+ protected void init(int[] dim) {
+ this.dim = new int[dim.length];
+ System.arraycopy(dim, 0, this.dim, 0, dim.length);
+ semantics = new SemanticList[dim.length];
+ dimNames = new String[dim.length];
+ }
+
+ protected AbstractMatrixMap(int[] dim) {
+ init(dim);
+ for (int i = 0; i < getDimCount(); i++) {
+ // par defaut les listes des semantiques contiennent des nulls
+ // FIXME no multiple null allowed
+ setSemantic(i, Collections.nCopies(dim[i], null));
+ }
+ }
+
+ public AbstractMatrixMap(List ... semantics) {
+ int[] dim = new int[semantics.length];
+ for (int i = 0; i < dim.length; i++) {
+ if (semantics[i] == null) {
+ dim[i] = 0;
+ } else {
+ dim[i] = semantics[i].size();
+ }
+ }
+ init(dim);
+ for (int i = 0; i < getDimCount(); i++) {
+ setSemantic(i, semantics[i]);
+ }
+ }
+
+ protected AbstractMatrixMap(String name, int[] dim) {
+ this(dim);
+ setName(name);
+ }
+
+ protected AbstractMatrixMap(String name, int[] dim, String[] dimNames) {
+ this(dim);
+ setName(name);
+ for (int i = 0; dimNames != null && i < dimNames.length; i++) {
+ setDimensionName(i, dimNames[i]);
+ }
+ }
+
+ public AbstractMatrixMap(String name, List... semantics) {
+ this(semantics);
+ setName(name);
+ }
+
+ public AbstractMatrixMap(String name, String[] dimNames, List... semantics) {
+ this(name, semantics);
+ for (int i = 0; dimNames != null && i < dimNames.length; i++) {
+ setDimensionName(i, dimNames[i]);
+ }
+ }
+
+ public AbstractMatrixMap(MatrixMap<E> matrix) {
+ this(matrix.getName(), matrix.getDimensionNames(), matrix.getSemantics());
+ this.pasteIndex(matrix);
+ }
+
+ /**
+ * Copy la matrice pour pouvoir la modifier sans perdre les donnees
+ * initiales.
+ *
+ * @return new matrix
+ */
+ public MatrixMap<E> copy() {
+ MatrixMap<E> result = new MatrixMapFixed<E>(this);
+ return result;
+ }
+
+ /*
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public MatrixMap clone() {
+ return copy();
+ }
+
+ public SemanticList[] getSemantics() {
+ return semantics;
+ }
+
+ public SemanticList getSemantic(int dim) {
+ return semantics[dim];
+ }
+
+ public void setSemantic(int dim, List sem) {
+ // make copy because this matrix can change semantics
+ SemanticList l = new SemanticList(sem);
+ semantics[dim] = l;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String[] getDimensionNames() {
+ return dimNames;
+ }
+
+ public void setDimensionNames(String[] names) {
+ for (int i = 0; names != null && i < names.length; i++) {
+ setDimensionName(i, names[i]);
+ }
+ }
+
+ public void setDimensionName(int dim, String name) {
+ dimNames[dim] = name;
+ }
+
+ public String getDimensionName(int dim) {
+ return dimNames[dim];
+ }
+
+ public int getDimCount() {
+ return dim.length;
+ }
+
+ public int[] getDim() {
+ return dim;
+ }
+
+ public int getDim(int d) {
+ return dim[d];
+ }
+
+ /**
+ * Retourne la matrice elle meme. Les modifications sont faites directement
+ * dessus
+ */
+ @Override
+ public MatrixMap<E> map(MapFunction<E> f) {
+ for (MatrixMapIterator<E> i = iterator(); i.hasNext();) {
+ i.setValue(f.apply(i.next()));
+ }
+ return this;
+ }
+
+ public E getValue(Object ... coordinates) {
+ if (coordinates.length == 0) {
+ throw new IllegalArgumentException("Coordinates must not be empty");
+ }
+ int[] intCoordinates =
+ MatrixHelper.semanticsToDimension(getSemantics(), coordinates);
+ E result = getValueIndex(intCoordinates);
+ return result;
+ }
+
+ public void setValue(E value, Object ... coordinates) {
+ if (coordinates.length == 0) {
+ throw new IllegalArgumentException("Coordinates must not be empty");
+ }
+ int[] intCoordinates =
+ MatrixHelper.semanticsToDimension(getSemantics(), coordinates);
+ setValueIndex(value, intCoordinates);
+ }
+
+ // TODO peut-etre faire une variante de equals qui regarde par rapport au
+ // coordonnées sémantique
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof MatrixMap && equals((MatrixMap) o);
+ }
+
+ public boolean equals(MatrixMap mat) {
+ boolean result = true;
+ // le nom doit être le même
+ result = result && getName().equals(mat.getName());
+
+ result = result && equalsValues(mat);
+
+ // les sémantiques doivent-être identique
+ for (int i = 0; result && i < getDimCount(); i++) {
+ String dimName1 = getDimensionName(i);
+ String dimName2 = mat.getDimensionName(i);
+ result = ObjectUtils.equals(dimName1, dimName2);
+ if (log.isTraceEnabled()) {
+ log.trace("dimName1(" + dimName1 + ")==dimName2(" + dimName2
+ + ")=" + result);
+ }
+ // System.out.println("dimName1("+dimName1+")==dimName2("+dimName2+
+ // ")="+result);
+
+ List sem1 = getSemantic(i);
+ List sem2 = mat.getSemantic(i);
+ result = result && ObjectUtils.equals(sem1, sem2);
+ if (log.isTraceEnabled()) {
+ log.trace("sem1(" + sem1 + ")==sem2(" + sem2 + ")=" + result);
+ }
+ // System.out.println("sem1("+sem1+")==sem1("+sem2+ ")="+result);
+ }
+
+ if (log.isTraceEnabled()) {
+ log.trace("result=" + result);
+ }
+ // System.out.println("result="+result);
+ return result;
+ }
+
+ /**
+ * Verifie si les matrices sont egales en ne regardant que les valeurs et
+ * pas les semantiques
+ *
+ * @param mat
+ * @return equality on values
+ */
+ public boolean equalsValues(MatrixMap mat) {
+ boolean result = true;
+ // les dimensions doivent-être identique
+ result = result && MatrixHelper.sameDimension(getDim(), mat.getDim());
+
+ // toutes les données doivent être identique
+ for (MatrixMapIterator<E> i = mat.iterator(); result && i.hasNext();) {
+ E v1 = i.next();
+ E v2 = getValueIndex(i.getCoordinates());
+ result = v1 == v2;
+ if (log.isTraceEnabled()) {
+ log.trace("v1(" + v1 + ")==v2(" + v2 + ")=" + result);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Si la matrice est 1D
+ * <pre>
+ * MaMatrice(matrix1D) [
+ * MaDimName: Dim1, Dim2, Dim3,
+ * v1, v2, v3
+ * ]
+ * </pre>
+ *
+ * Si la matrice est 2D
+ * <pre>
+ * MaMatrice(matrix2D) [
+ * MaDimX
+ * MaDimY Dim1, Dim2, Dim3,
+ * DimA v1, v2, v3
+ * DimB v4, v5, v6
+ * DimC v7, v8, v9
+ * ]
+ * </pre>
+ *
+ * Pour les autres types de matrice la methode {@link #toStringGeneric() }
+ * est utilise
+ *
+ * @return
+ */
+ @Override
+ public String toString() {
+ int LENGTH = 10;
+ StringBuilder result = new StringBuilder();
+ if (getDimCount() == 1) {
+ result.append(MatrixHelper.format(getName(), -LENGTH, "#NoNameMat"));
+ result.append("(matrix1D)[\n");
+ String dimName = getDimensionName(0);
+ result.append(MatrixHelper.format(dimName, LENGTH, "#NoNameDim"));
+ for (Object sem : getSemantic(0)) {
+ result.append(",");
+ result.append(MatrixHelper.format(sem, -LENGTH, null));
+ }
+ result.append(StringUtils.repeat(" ", LENGTH + 1));
+ for (int i = 0; i < getDim(0); i++) {
+ Object v = getValueIndex(i);
+ result.append(MatrixHelper.format(v, -LENGTH, null) + ",");
+ }
+ result.append("\n]");
+ } else if (getDimCount() == 2) {
+ int[] pos = new int[2];
+ result.append(MatrixHelper.format(getName(), -LENGTH, "#NoNameMat"));
+ result.append("(matrix2D) [\n");
+
+ result.append(StringUtils.repeat(" ", LENGTH + 1));
+ String dimNameX = getDimensionName(0);
+ result.append(MatrixHelper.format(dimNameX, LENGTH, "#DimX"));
+ result.append("\n");
+ String dimNameY = getDimensionName(1);
+ result.append(MatrixHelper.format(dimNameY, LENGTH, "#DimY"));
+ result.append(" ");
+ for (Object sem : getSemantic(0)) {
+ result.append(MatrixHelper.format(sem, -LENGTH, null));
+ result.append(",");
+ }
+
+ for (int y = 0; y < getDim(1); y++) {
+ result.append("\n");
+ Object sem = getSemantic(1).get(y);
+ result.append(MatrixHelper.format(sem, LENGTH, null));
+ result.append(" ");
+ for (int x = 0; x < getDim(0); x++) {
+ pos[0] = x;
+ pos[1] = y;
+ Object v = getValueIndex(pos);
+ result.append(MatrixHelper.format(v, -LENGTH, null) + ",");
+ }
+ }
+ result.append("\n]");
+ } else {
+ result.append(toStringGeneric());
+ }
+ return result.toString();
+ }
+
+ /**
+ * Representation string de la matrice quelque soit le nombre de dimension
+ * @return
+ */
+ public String toStringGeneric() {
+ StringBuilder result = new StringBuilder();
+ result.append(MatrixHelper.format(getName(), 0, "#NoNameMat"));
+ result.append("(matrix" + getDimCount() + "D)[\n");
+ result.append("dimensions = [");
+ for (int i = 0; i < getDim().length; i++) {
+ result.append(getDim()[i] + ",");
+ }
+ result.append("]\ndata = [");
+ for (MatrixMapIterator i = this.iterator(); i.hasNext();) {
+ result.append(i.next() + ",");
+ }
+ result.append("]\n");
+ return result.toString();
+ }
+
+ public boolean isValidCoordinates(int[] dim) {
+ boolean result = getDimCount() == dim.length;
+ for (int i = 0; result && i < dim.length; i++) {
+ result = 0 <= dim[i] && dim[i] < getDim(i);
+ }
+ return result;
+ }
+
+ public boolean isValidCoordinates(Object[] semantics) {
+ boolean result = getDimCount() == semantics.length;
+ for (int i = 0; result && i < semantics.length; i++) {
+ List semantic = getSemantic(i);
+ result = semantic.contains(semantics[i]);
+ }
+ return result;
+ }
+
+ /**
+ * Copie une matrice dans la matrice actuelle. La matrice à copier à le même
+ * nombre de dimension. Si la matrice à copier est trop grande seul les
+ * éléments pouvant être copier le seront.
+ *
+ * @param mat la matrice à copier
+ * @return return la matrice courante.
+ */
+ public MatrixMap pasteIndex(MatrixMap<E> mat) {
+ return paste(new int[getDimCount()], mat);
+ }
+
+ protected MatrixMap<E> paste(int[] origin, MatrixMap<E> mat) {
+ if (mat != null) {
+ for (MatrixMapIterator<E> mi = mat.iterator(); mi.hasNext();) {
+ E value = mi.next();
+ int[] coordinates = ArrayUtil.sum(origin, mi.getCoordinates());
+ if (isValidCoordinates(coordinates)) {
+ setValueIndex(value, coordinates);
+ }
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Modifie la matrice actuel en metant les valeurs de mat passé en parametre
+ * La copie se fait en fonction de la semantique, si un element dans une
+ * dimension n'est pas trouvé, alors il est passé
+ */
+ public MatrixMap<E> paste(MatrixMap<E> mat) {
+ if (mat != null) {
+ for (MatrixMapIterator<E> mi = mat.iterator(); mi.hasNext();) {
+ E value = mi.next();
+ Object[] sems = mi.getSemanticsCoordinates();
+ if (isValidCoordinates(sems)) {
+ setValue(value, sems);
+ }
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Permet de prendre une sous matrice dans la matrice courante. La sous
+ * matrice a le même nombre de dimensions mais sur une des dimensions on ne
+ * prend que certain élément.
+ *
+ * @param dim la dimension dans lequel on veut une sous matrice si dim est
+ * négatif alors la dimension est prise à partir de la fin par
+ * exemple si l'on veut la derniere dimension il faut passer -1
+ * pour dim
+ * @param start la position dans dim d'ou il faut partir pour prendre la
+ * sous matrice.
+ * @param nb le nombre d'élément à prendre dans la dimension. si nb est
+ * inférieur ou égal à 0 alors cela indique qu'il faut prendre
+ * tous les éléments jusqu'à la fin de la dimension.
+ * @return new matrix
+ */
+ public MatrixMap<E> getSubMatrix(int dim, int start, int nb) {
+ if (dim < 0) {
+ dim = getDimCount() + dim;
+ }
+ if (start < 0) {
+ start = getDim(dim) + start;
+ }
+ if (nb <= 0) {
+ nb = getDim(dim) - start;
+ }
+ return new SubMatrix<E>(this, dim, start, nb);
+ }
+
+ /**
+ * Permet de prendre une sous matrice dans la matrice courante. La sous
+ * matrice a le même nombre de dimensions mais sur une des dimensions on ne
+ * prend que certain élément.
+ *
+ * @param dim la dimension dans lequel on veut une sous matrice
+ * @param start la position dans dim d'ou il faut partir pour prendre la
+ * sous matrice. 0 <= start < dim.size si start est négatif alors
+ * la position de départ est calculé par rapport à la fin de la
+ * dimension, pour avoir le dernier élément il faut passer -1
+ * @param nb le nombre d'élément à prendre dans la dimension si nb est
+ * inférieur ou égal à 0 alors cela indique qu'il faut prendre
+ * tous les éléments jusqu'à la fin de la dimension.
+ * @return new matrix
+ */
+ public MatrixMap<E> getSubMatrix(int dim, Object start, int nb) {
+ int begin = MatrixHelper.indexOf(getSemantics(), dim, start);
+ return getSubMatrix(dim, begin, nb);
+ }
+
+ /**
+ * Add to desambiguas some call with xpath engine, but do the same thing
+ * {@link #getSubMatrix(int, Object[])}
+ *
+ * @param dim
+ * @param elem
+ * @return new matrix
+ */
+ public MatrixMap<E> getSubMatrixOnSemantic(int dim, Object... elem) {
+ MatrixMap<E> result = getSubMatrix(dim, elem);
+ return result;
+ }
+
+ /**
+ * Permet de prendre une sous matrice dans la matrice courante. La sous
+ * matrice a le même nombre de dimensions mais sur une des dimensions on ne
+ * prend que certain élément.
+ *
+ * @param dim la dimension dans lequel on veut une sous matrice
+ * @param elem les éléments dans la dimension à conserver
+ * @return new matrix
+ */
+ public MatrixMap<E> getSubMatrix(int dim, Object... elem) {
+ int[] ielem = new int[elem.length];
+ for (int i = 0; i < ielem.length; i++) {
+ ielem[i] = MatrixHelper.indexOf(getSemantics(), dim, elem[i]);
+ }
+ return getSubMatrix(dim, ielem);
+ }
+
+ /**
+ * Permet de prendre une sous matrice dans la matrice courante.
+ *
+ * Réalise plusieurs appels à {@link #getSubMatrix(int, Object...)} suivant
+ * l'implémentation.
+ *
+ * @param elem les éléments dans la dimension à conserver
+ * @return new matrix
+ */
+ public MatrixMap<E> getSubMatrix(Object[]... elems) {
+
+ // la reduction doit se faire sur le meme nombre de dimension
+ if (elems.length != dim.length) {
+ throw new IllegalArgumentException(String.format(
+ "Can't get sub matrix with different dimension count "
+ + "(expected: %d, got %d)", dim.length, elems.length));
+ }
+
+ MatrixMap<E> result = this;
+ for (int i = 0; i < elems.length; ++i) {
+ if (elems[i] != null) {
+ result = result.getSubMatrix(i, elems[i]);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Permet de prendre une sous matrice dans la matrice courante. La sous
+ * matrice a le même nombre de dimensions mais sur une des dimensions on ne
+ * prend que certain élément.
+ *
+ * @param dim la dimension dans lequel on veut une sous matrice
+ * @param elem les indices des éléments dans la dimension à conserver
+ * @return new matrix
+ */
+ public MatrixMap<E> getSubMatrix(int dim, int[] elem) {
+ return new SubMatrix<E>(this, dim, elem);
+ }
+
+ /**
+ * Permet de prendre une sous matrice dans la matrice courante.
+ *
+ * Réalise plusieurs appels a {@link #getSubMatrix(int, int[])} suivant
+ * l'implementation.
+ *
+ * @param elems les indices des éléments pour chaque dimension à conserver
+ * @return new matrix
+ */
+ public MatrixMap<E> getSubMatrix(int[]... elems) {
+
+ // la reduction doit se faire sur le meme nombre de dimension
+ if (elems.length != dim.length) {
+ throw new IllegalArgumentException(String.format(
+ "Can't get sub matrix with different dimension count "
+ + "(expected: %d, got %d)", dim.length, elems.length));
+ }
+
+ MatrixMap<E> result = this;
+ for (int i = 0; i < elems.length; ++i) {
+ if (elems[i] != null) {
+ result = new SubMatrix<E>(result, i, elems[i]);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Reduit la matrice de sorte que toutes les dimensions qui n'ont qu'un
+ * élement soit supprimée. Au pire cette méthode retourne une matrice à une
+ * seule dimension à un seul élément.
+ *
+ * @return une nouvelle matrice plus petite que la matrice actuelle ou egal
+ * s'il n'y a aucune dimension à supprimer
+ */
+ public MatrixMap<E> reduce() {
+ return reduce(1);
+ }
+
+ /**
+ * Reduit le matrice seulement sur les dimensions passées en argument. Si
+ * une des dimensions passées en arguement n'a pas qu'un seul élément, cette
+ * dimension n'est pas prise en compte.
+ *
+ * @param dims les dimensions sur lequel il faut faire la reduction
+ * @return une nouvelle matrice
+ */
+ public MatrixMap<E> reduceDims(int... dims) {
+ Arrays.sort(dims);
+ // tableau permettant de faire la correspondance entre les dimensions
+ // de la matrice actuelle et les dimentsions de la nouvelle matrice
+ // l'element i du tableau qui correcpond à la dimensions i de la
+ // nouvelle matrice contient la dimension equivalente dans
+ // la matrice actuelle
+ int[] correspondance = new int[getDimCount()];
+ // les nouvelles semantiques
+ List<List> sem = new ArrayList<List>();
+ // les nouveaux noms de dimensions
+ List<String> dimName = new ArrayList<String>();
+ // il faut au moins une dimension pour la matrice
+ int minNbDim = 1;
+ for (int j = getDimCount() - 1; j >= 0; j--) {
+ // si la dimension à plus d'un élément ou qu'il n'est pas dans dims
+ // on garde la dimension
+ if (getDim(j) > 1 || Arrays.binarySearch(dims, j) < 0
+ || j < minNbDim) {
+ // on ne conserve que les dimensions supérieure à 1
+ correspondance[sem.size()] = j;
+ sem.add(getSemantic(j));
+ dimName.add(getDimensionName(j));
+ minNbDim--;
+ }
+ }
+ MatrixMap<E> result = reduce(dimName, sem, correspondance);
+ return result;
+ }
+
+ /**
+ * Reduit la matrice de sorte que toutes les dimensions qui n'ont qu'un
+ * élement soit supprimée. Au pire cette méthode retourne une matrice à une
+ * seule dimension à un seul élément.
+ *
+ * @param minNbDim le nombre minimum de dimension que l'on souhaite pour la
+ * matrice résultat
+ * @return une nouvelle matrice plus petite que la matrice actuelle ou egal
+ * s'il n'y a aucune dimension à supprimer
+ */
+ public MatrixMap<E> reduce(int minNbDim) {
+ // tableau permettant de faire la correspondance entre les dimensions
+ // de la matrice actuelle et les dimentsions de la nouvelle matrice
+ // l'element i du tableau qui correcpond à la dimensions i de la
+ // nouvelle matrice contient la dimension equivalente dans
+ // la matrice actuelle
+ int[] correspondance = new int[getDimCount()];
+ // les nouvelles semantiques
+ List<List> sem = new ArrayList<List>();
+ // les nouveaux noms de dimensions
+ List<String> dimName = new ArrayList<String>();
+ for (int j = getDimCount() - 1; j >= 0; j--) {
+ // si la dimension à plus d'un élément ou si on a pas assez de
+ // dimension pour avoir le minimum demandé on prend la dimension
+ if (getDim(j) > 1 || j < minNbDim) {
+ // on ne conserve que les dimensions supérieure à 1
+ correspondance[sem.size()] = j;
+ sem.add(getSemantic(j));
+ dimName.add(getDimensionName(j));
+ // on vient de prendre une dimension il nous en faut une de
+ // moins
+ minNbDim--;
+ }
+ }
+
+ MatrixMap<E> result = reduce(dimName, sem, correspondance);
+ return result;
+ }
+
+ /**
+ * Create new matrice from the current matrix.
+ *
+ * @param dimName dimension name for new matrix
+ * @param sem semantic for new matrix
+ * @param correspondance array to do the link between current matrix and
+ * returned matrix
+ * @return new matrix
+ */
+ protected MatrixMap<E> reduce(List<String> dimName, List<List> sem, int[] correspondance) {
+ // on converti les listes en tableau en inversant l'ordre car on
+ // a fait un parcours en sens inverse
+ int nbDim = sem.size();
+ List[] newSemantics = new List[nbDim];
+ String[] newDimNames = new String[nbDim];
+ int[] tmpcorrespondance = new int[nbDim];
+ for (int i = 0; i < nbDim; i++) {
+ newSemantics[i] = sem.get(nbDim - 1 - i);
+ newDimNames[i] = dimName.get(nbDim - 1 - i);
+ tmpcorrespondance[i] = correspondance[nbDim - 1 - i];
+ }
+ correspondance = tmpcorrespondance;
+
+ MatrixMap<E> result = new MatrixMapFixed<E>(getName(), newDimNames, newSemantics);
+
+ // on reprend les valeurs
+ int[] newCoordinates = new int[result.getDimCount()];
+ for (MatrixMapIterator<E> mi = iterator(); mi.hasNext();) {
+ E value = mi.next();
+ int[] oldCoordinates = mi.getCoordinates();
+ for (int i = 0; i < newCoordinates.length; i++) {
+ newCoordinates[i] = oldCoordinates[correspondance[i]];
+ }
+ result.setValueIndex(value, newCoordinates);
+ }
+ return result;
+ }
+
+ public MatrixMap<E> extend(Object... sems) {
+ String name = getName();
+ String[] dimNames = getDimensionNames();
+ SemanticList[] semantics = getSemantics();
+
+ // si pas assez de dimension on en rajoute
+ if (sems.length > semantics.length) {
+ String[] newDimNames = new String[sems.length];
+ System.arraycopy(dimNames, 0, newDimNames, 0, dimNames.length);
+ dimNames = newDimNames;
+
+ SemanticList[] newSems = new SemanticList[sems.length];
+ System.arraycopy(semantics, 0, newSems, 0, semantics.length);
+ semantics = newSems;
+
+ for (int i = semantics.length; i < newSems.length; i++) {
+ newSems[i] = new SemanticList();
+ }
+ }
+
+ // si les objets demande n'existe pas dans la semantics on l'ajoute
+ for (int i = 0; i<sems.length; i++) {
+ if (semantics[i].indexOf(sems[i]) == -1) {
+ semantics[i].add(sems[i]);
+ }
+ }
+
+ MatrixMap<E> result = MatrixMap.Factory.create(name, dimNames, semantics);
+ result.paste(this);
+ return result;
+ }
+
+ }
+
+ /**
+ * Pour l'instant une sous matrice a obligatoirement le meme nombre de dimension
+ * que la matrice qu'elle contient. Elle permet juste de reduire le nombre
+ * d'element d'une dimension.
+ *
+ * C'est comme une "vue" réduite sur la vraie matrices.
+ */
+ static public class SubMatrix<E> extends AbstractMatrixMap<E> { // SubMatrix
+
+ protected MatrixMap<E> matrix = null;
+ protected DimensionConverter converter = null;
+
+ public SubMatrix(MatrixMap<E> matrix, int dim, int start, int nb) {
+ super(matrix.getName(), matrix.getDimensionNames(), matrix.getSemantics());
+ this.matrix = matrix;
+
+ converter = new ShiftConverter(dim, start, nb);
+ setSemantic(dim, getSemantic(dim).subList(start, start + nb));
+ getDim()[dim] = nb;
+ }
+
+ public SubMatrix(MatrixMap<E> matrix, int dim, int[] elem) {
+ super(matrix.getName(), matrix.getDimensionNames(), matrix.getSemantics());
+ this.matrix = matrix;
+
+ converter = new MappingConverter(dim, elem);
+
+ List oldSemantic = getSemantic(dim);
+ List newSemantic = new LinkedList();
+ for (int i = 0; i < elem.length; i++) {
+ newSemantic.add(oldSemantic.get(elem[i]));
+ }
+ setSemantic(dim, newSemantic);
+ getDim()[dim] = elem.length;
+ }
+
+ @Override
+ public MatrixMapIterator<E> iterator() {
+ return new SubMatrixIterator<E>(this);
+ }
+
+ @Override
+ public E getValueIndex(int ... coordinates) {
+ return matrix.getValueIndex(converter.convertCoordinates(coordinates));
+ }
+
+ @Override
+ public void setValueIndex(E value, int ... coordinates) {
+ matrix.setValueIndex(value, converter.convertCoordinates(coordinates));
+ }
+
+ protected class SubMatrixIterator<E> implements MatrixMapIterator<E> {
+
+ protected SubMatrix<E> subMatrix = null;
+ protected int[] cpt = null;
+ protected int[] last = null;
+
+ public SubMatrixIterator(SubMatrix<E> subMatrix) {
+ this.subMatrix = subMatrix;
+ cpt = new int[subMatrix.getDimCount()];
+ cpt[cpt.length - 1] = -1;
+
+ last = new int[subMatrix.getDimCount()];
+ for (int i = 0; i < last.length; i++) {
+ last[i] = subMatrix.getDim(i) - 1;
+ }
+
+ }
+
+ @Override
+ public boolean hasNext() {
+ return !Arrays.equals(cpt, last);
+ }
+
+ @Override
+ public E next() {
+ int ret = 1;
+ int[] dim = getDim();
+ for (int i = cpt.length - 1; i >= 0; i--) {
+ cpt[i] = cpt[i] + ret;
+ ret = cpt[i] / dim[i];
+ cpt[i] = cpt[i] % dim[i];
+ }
+ E result = getValue();
+ return result;
+ }
+
+ @Override
+ public void remove() {
+ setValue(null);
+ }
+
+ public int[] getCoordinates() {
+ return cpt;
+ }
+
+ public Object[] getSemanticsCoordinates() {
+ int[] coordinates = getCoordinates();
+ Object[] result = MatrixHelper.dimensionToSemantics(subMatrix.getSemantics(), coordinates);
+ return result;
+ }
+
+ public E getValue() {
+ return subMatrix.getValueIndex(getCoordinates());
+ }
+
+ public void setValue(E value) {
+ subMatrix.setValue(value, getCoordinates());
+ }
+ }
+
+ /**
+ * Permet de faire une conversion de la dimension demandé dans la sous
+ * matrice avec la position reel de la matrice sous jacente.
+ */
+ protected interface DimensionConverter extends Serializable {
+ public int[] convertCoordinates(int[] coordinates);
+ }
+
+ /**
+ * La conversion est juste un decalage d'indice
+ */
+ protected static class ShiftConverter implements DimensionConverter {
+
+ /** serialVersionUID. */
+ private static final long serialVersionUID = 1L;
+
+ protected int dim;
+ protected int start;
+ protected int nb;
+
+ public ShiftConverter(int dim, int start, int nb) {
+ this.dim = dim;
+ this.start = start;
+ this.nb = nb;
+ }
+
+ @Override
+ public int[] convertCoordinates(int[] coordinates) {
+ int[] result = null;
+ if (coordinates[dim] < nb) {
+ result = new int[coordinates.length];
+ System.arraycopy(coordinates, 0, result, 0, result.length);
+ result[dim] = result[dim] + start;
+ } else {
+ throw new NoSuchElementException(
+ "L'indice est supérieur au nombre d'élement de la sous matrice pour cette dimension.");
+ }
+ return result;
+ }
+ }
+
+ /**
+ * La conversion est le mapping d'un element vers un autre element.
+ */
+ protected static class MappingConverter implements DimensionConverter {
+
+ /** serialVersionUID. */
+ private static final long serialVersionUID = -6367416559713556559L;
+ protected int dim;
+ protected int[] elem = null;
+
+ public MappingConverter(int dim, int[] elem) {
+ this.dim = dim;
+ this.elem = new int[elem.length];
+ System.arraycopy(elem, 0, this.elem, 0, elem.length);
+ }
+
+ @Override
+ public int[] convertCoordinates(int[] coordinates) {
+ int[] result = null;
+ if (coordinates[dim] < elem.length) {
+ result = new int[coordinates.length];
+ System.arraycopy(coordinates, 0, result, 0, result.length);
+ result[dim] = elem[coordinates[dim]];
+
+ } else {
+ throw new NoSuchElementException(
+ "L'indice est supérieur au nombre d'élements de la sous matrice pour cette dimension.");
+ }
+ return result;
+ }
+ }
+ } // SubMatrix
+
+ /**
+ * Objet matrice qui ne permet que le stockage avec des positions int
+ * dans une matrice a autant de dimension que l'on souhaite.
+ */
+ static public class Matrix<E> implements Iterable<E> { // BasicMatrix
+
+ /** Les dimensions de la matrice */
+ protected int[] dimensions = null;
+ /** La matrice en représentation linéaire */
+ protected Vector<E> data = null;
+
+ /**
+ * tableau de facteur permettant de convertir les coordonnées dans la
+ * matrice en un indice dans la représentation linéaire de la matrice
+ */
+ protected int[] linearFactor = null;
+
+ /**
+ * Crée une nouvelle matrice ayant les dimensions demandées.
+ *
+ * @param factory factory
+ * @param dimensions dimensions
+ */
+ public Matrix(int[] dimensions) {
+ checkDim(dimensions);
+
+ // copie des dimensions pour que personne à l'extérieur de l'objet
+ // ne puisse les modifiers par la suite
+ this.dimensions = new int[dimensions.length];
+ System.arraycopy(dimensions, 0, this.dimensions, 0, dimensions.length);
+
+ // calcul du linearFactor
+ linearFactor = new int[dimensions.length];
+ linearFactor[linearFactor.length - 1] = 1;
+ for (int i = linearFactor.length - 2; i >= 0; i--) {
+ linearFactor[i] = linearFactor[i + 1] * dimensions[i + 1];
+ }
+
+ // creation de la matrice lineaire
+ data = new Vector<E>(linearFactor[0] * dimensions[0]);
+ }
+
+ /**
+ * Retourne le nombre de dimension de la matrice
+ *
+ * @return le nombre de dimension de la matrice;
+ */
+ public int getNbDim() {
+ return dimensions.length;
+ }
+
+ /**
+ * Retourne la taille d'une dimension
+ *
+ * @param dim la dimension dont on souhaite la taille
+ * @return la taille d'une dimension
+ */
+ public int getDim(int dim) {
+ checkDim(dim);
+ return dimensions[dim];
+ }
+
+ /**
+ * Retourne un tableau representant les dimensions de la matrice. Le tableau
+ * retourné n'est pas une copie, il ne faut donc pas le modifier
+ *
+ * @return le tableau des dimensions.
+ */
+ public int[] getDim() {
+ return dimensions;
+ }
+
+ /**
+ * Retourne un element de la matrice
+ *
+ * @param pos la position de l'element à retourner
+ * @return un element de la matrice
+ */
+ public E getValue(int[] pos) {
+ int indice = coordonatesToLinear(pos);
+ return data.getValue(indice);
+ }
+
+ /**
+ * Modifie un élement de la matrice
+ *
+ * @param pos la position de l'element à modifier
+ * @param value la nouvelle valeur à mettre dans la matrice
+ */
+ public void setValue(int[] pos, E value) {
+ int indice = coordonatesToLinear(pos);
+ data.setValue(indice, value);
+ }
+
+ /**
+ * Retourne un objet Inc pret a etre utilisé pour boucler sur tous les
+ * element de la matrice.
+ *
+ * @return un objet Inc pret à être utilisé
+ */
+ public MatrixIterator<E> iterator() {
+ return new MatrixIterator<E>(this);
+ }
+
+ /**
+ * Permet de faire un traitement sur chaque valeur de la matrice
+ *
+ * @param f la fonction a appliquer à chaque élement de la matrice
+ */
+ public void map(MapFunction f) {
+ data.map(f);
+ }
+
+ /**
+ * Permet de convertir les coordonnées d'un élément en un indice dans la
+ * représentation linéraire de la matrice.
+ *
+ * @param coordonates les coordonnées à lineariser
+ * @return un indice réprésentant les coordonnées de façon linéaire
+ */
+ protected int coordonatesToLinear(int[] coordonates) {
+ checkPos(coordonates);
+
+ int result = 0;
+ for (int i = 0; i < linearFactor.length; i++) {
+ result += coordonates[i] * linearFactor[i];
+ }
+ return result;
+ }
+
+ /**
+ * Convertie une coordonnée lineaire en coordonnées spaciales
+ *
+ * @param pos la coordonnée linéaire
+ * @return les coordonnées spaciales de l'élément
+ */
+ protected int[] linearToCoordinates(int pos) {
+ int[] result = new int[linearFactor.length];
+
+ for (int i = 0; i < result.length; i++) {
+ result[i] = pos / linearFactor[i];
+ pos -= result[i] * linearFactor[i];
+ }
+ return result;
+ }
+
+ /**
+ * Permet de vérifier que les dimensions de la nouvelle matrice sont
+ * corrects
+ *
+ * @param dim les dimensions de la nouvelle matrice
+ * @throws IllegalArgumentException si une dimension n'est pas valide
+ */
+ protected void checkDim(int[] dim) {
+ for (int i = 0; i < dim.length; i++) {
+ if (dim[i] <= 0) {
+ throw new IllegalArgumentException(String.format(
+ "Dimension %s is invalid %s", i, dim[i]));
+ }
+ }
+ }
+
+ /**
+ * Permet de vérifier qu'une dimension demandé existe bien dans la matrice
+ *
+ * @param dim la position de la dimension que l'on souhaite
+ * @throws IndexOutOfBoundsException si la dimension demandée n'existe pas
+ */
+ protected void checkDim(int dim) {
+ if (dim < 0 || dim >= getNbDim()) {
+ throw new IndexOutOfBoundsException(String.format(
+ "Invalid dimension %s max dimension is %s",
+ dim, getNbDim()));
+ }
+ }
+
+ /**
+ * Verifie que les coordonnées demandé appartiennent bien à la matrice
+ *
+ * @param pos les coordonnées souhaitées dans la matrice
+ * @throws NoSuchElementException si les coordonnées ne correspondent pas à
+ * un élement de la matrice
+ */
+ protected void checkPos(int[] pos) {
+ int[] dim = getDim();
+ boolean result = dim.length == pos.length;
+ for (int i = 0; result && i < dim.length; i++) {
+ result = (0 <= pos[i]) && (pos[i] < dim[i]);
+ }
+ if (!result) {
+ throw new NoSuchElementException(String.format(
+ "Invalid element asked %s for real dimension %s", Arrays.toString(pos), Arrays
+ .toString(dim)));
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer result = new StringBuffer();
+ if (getNbDim() == 1) {
+ result.append("matrix1D [");
+ for (int i = 0; i < data.size(); i++) {
+ result.append(data.getValue(i) + ",");
+ }
+ result.append("]");
+ } else if (getNbDim() == 2) {
+ int[] pos = new int[2];
+ result.append("matrix2D [");
+ for (int y = 0; y < getDim(1); y++) {
+ result.append("\n");
+ for (int x = 0; x < getDim(0); x++) {
+ pos[0] = x;
+ pos[1] = y;
+ result.append(getValue(pos) + ",");
+ }
+ }
+ result.append("]");
+ } else {
+ result.append("dimensions = [\n");
+ for (int i = 0; i < dimensions.length; i++) {
+ result.append(dimensions[i] + ",");
+ }
+ result.append("\n]\nmatrice = [\n");
+ for (int i = 0; i < data.size(); i++) {
+ result.append(data.getValue(i) + ",");
+ }
+ result.append("\n]\nlinearFactor = [\n");
+ for (int i = 0; i < linearFactor.length; i++) {
+ result.append(linearFactor[i] + ",");
+ }
+ result.append("\n]\n");
+ }
+ return result.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof Matrix) {
+ Matrix other = (Matrix) o;
+ return this == o
+ || (Arrays.equals(this.dimensions, other.dimensions) && this.data
+ .equals(other.data));
+ }
+ return false;
+ }
+
+ } // BasicMatrix
+
+ static public class MatrixIterator<E> implements Iterator<E> { // MatrixIteratorImpl
+
+ protected Matrix<E> matrix = null;
+ protected int pos = -1;
+
+ /**
+ * @param matrix la matrice sur lequel l'iterator doit travailler
+ */
+ public MatrixIterator(Matrix<E> matrix) {
+ this.matrix = matrix;
+ pos = -1;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return pos + 1 < matrix.data.size();
+ }
+
+ @Override
+ public E next() {
+ if (hasNext()) {
+ pos++;
+ } else {
+ throw new NoSuchElementException();
+ }
+ E result = getValue();
+ return result;
+ }
+
+ @Override
+ public void remove() {
+ setValue(null);
+ }
+
+ public E getValue() {
+ return matrix.data.getValue(pos);
+ }
+
+ public void setValue(E value) {
+ matrix.data.setValue(pos, value);
+ }
+
+ public int[] getCoordinates() {
+ return matrix.linearToCoordinates(pos);
+ }
+
+ } // MatrixIteratorImpl
+
+ /**
+ * Permet de stocker des données à une position lineaire et de la redemander.
+ * Cette classe ne gére que les données lineaire. L'avantage de cette classe est
+ * de ne conserver que les elements differents de la valeur par defaut, ce qui
+ * minimize la taille du tableau necessaire a conserver les données.
+ *
+ */
+ static public class Vector<E> { // Vector
+
+ /** maximum number of element, maximum pos value */
+ protected int capacity = 0;
+
+ /** la valeur par defaut */
+ protected E defaultValue = null;
+
+ /** contient la position de l'element, le tableau est trie */
+ protected int[] position;
+ protected int positionSize = 0;
+
+ /** contient la valeur de l'element */
+ protected ArrayList<E> data = new ArrayList<E>();
+
+ public Vector(int capacity) {
+ this.capacity = capacity;
+ position = new int[8];
+ Arrays.fill(position, Integer.MAX_VALUE);
+ }
+
+ public Vector(int capacity, E defaultValue) {
+ this(capacity);
+ this.defaultValue = defaultValue;
+ }
+
+ public int size() {
+ return capacity;
+ }
+
+ // poussin 20060827 TODO: verifier l'implantation, il semble quelle soit
+ // fausse et ne puisse pas recherche le nombre max correctement
+ public E getMaxOccurrence() {
+ E result = defaultValue;
+
+ E[] tmp = (E[])data.toArray();
+
+ // si potentiellement il y a plus d'element identique dans data
+ // que de valeur par defaut, on recherche la valeur possible
+ if (this.capacity < 2 * tmp.length) {
+ Arrays.sort(tmp);
+
+ // le nombre de fois que l'on a rencontrer la valeur la plus
+ // nombreuse
+ int max = 1;
+ // le nombre de fois que l'on a rencontrer la valeur courante
+ int count = 1;
+ // la valeur la plus rencontrer
+ result = tmp[0];
+ // la valeur que l'on vient de traiter précédement
+ E old = tmp[0];
+ // la valeur courante lu dans le tableaux
+ E current = tmp[0];
+ // tant que l'on peut encore trouve un element plus nombreux dans le
+ // tableau on le parcours
+ for (int i = 1; max < tmp.length - i + count && i < tmp.length; i++) {
+ current = tmp[i];
+
+ if (current == old) {
+ count++;
+ } else {
+ if (count > max) {
+ max = count;
+ result = old;
+ }
+ count = 1;
+ old = current;
+ }
+ }
+ if (count > max) {
+ max = count;
+ result = current;
+ }
+
+ if (max <= capacity - tmp.length) {
+ // en fin de compte, il n'y a pas plus d'element identique
+ // dans data que de defaultValue
+ result = defaultValue;
+ }
+ }
+
+ return result;
+ }
+
+ protected void checkPos(int pos) {
+ if (pos < 0 || pos >= capacity) {
+ throw new IllegalArgumentException("pos " + pos + " is not in [0, "
+ + capacity + "]");
+ }
+ }
+
+ public E getValue(int pos) {
+ checkPos(pos);
+
+ E result = defaultValue;
+ int index = findIndex(pos);
+ if (index >= 0) {
+ result = data.get(index);
+ }
+ return result;
+ }
+
+ public void setValue(int pos, E value) {
+ checkPos(pos);
+
+ int index = findIndex(pos);
+ if (index >= 0) {
+ if (value == defaultValue) {
+ // il etait present, on supprime l'element
+ removeElementAt(index);
+ data.remove(index);
+ } else {
+ // il etait deja present, on modifie la valeur
+ data.set(index, value);
+ }
+ } else {
+ // il n'etait pas present
+ if (value != defaultValue) {
+ // il faut ajouter dans position et dans data
+ index = -index - 1;
+
+ addElementAt(index, pos);
+ data.add(index, value);
+ }
+ }
+ }
+
+ public boolean equals(Object o) {
+ boolean result = false;
+ if (o instanceof Vector) {
+ Vector other = (Vector) o;
+ result = Arrays.equals(this.position, other.position)
+ && data.equals(other.data);
+ }
+ return result;
+ }
+
+ /**
+ * retourne la position dans le tableau position de la position lineaire
+ *
+ * @param pos
+ * @return la position ou < 0 donnant la position de l'element s'il etait
+ * present
+ */
+ protected int findIndex(int pos) {
+ return Arrays.binarySearch(position, pos);
+ }
+
+ protected void ensureCapacity(int mincap) {
+ if (mincap > position.length) {
+ int newcap = (position.length * 3) / 2 + 1;
+ int olddata[] = position;
+ position = new int[newcap >= mincap ? newcap : mincap];
+ System.arraycopy(olddata, 0, position, 0, positionSize);
+ for (int i = positionSize; i < position.length; i++) {
+ position[i] = Integer.MAX_VALUE;
+ }
+ }
+ }
+
+ protected void addElementAt(int index, int element) {
+ ensureCapacity(positionSize + 1);
+ int numtomove = positionSize - index;
+ System.arraycopy(position, index, position, index + 1, numtomove);
+ position[index] = element;
+ positionSize++;
+ }
+
+ protected int removeElementAt(int index) {
+ int oldval = position[index];
+ int numtomove = positionSize - index - 1;
+ if (numtomove > 0) {
+ System.arraycopy(position, index + 1, position, index, numtomove);
+ }
+ positionSize--;
+ position[positionSize] = Integer.MAX_VALUE;
+ return oldval;
+ }
+
+ /**
+ * On recopie tous les attributs pour que le vector ressemble exactement a
+ * celui passé en argument
+ */
+ public void paste(Vector<E> v) {
+ this.capacity = v.capacity;
+ this.defaultValue = v.defaultValue;
+ this.positionSize = v.positionSize;
+ this.position = new int[v.position.length];
+ System.arraycopy(v.position, 0, this.position, 0,
+ this.position.length);
+ this.data.clear();
+ this.data.addAll(v.data);
+ }
+
+ /**
+ * on applique sur chaque donnée existante et sur default
+ */
+ public void map(MapFunction<E> f) {
+ // on commence toujours par modifier la valeur par defaut
+ // car les valeurs suivante pourrait prendre cette valeur
+ // et donc disparaitre des tableaux si besoin
+ defaultValue = f.apply(defaultValue);
+ // on fait la boucle a l'envers au cas ou on supprime des valeurs
+ for (int i = data.size() - 1; i >= 0; i--) {
+ E value = f.apply(data.get(i));
+ if (value == defaultValue) {
+ // il etait present, on supprime l'element
+ removeElementAt(i);
+ data.remove(i);
+ } else {
+ // il etait deja present, on modifie la valeur
+ data.set(i, value);
+ }
+ }
+ }
+ } // Vector
+
+ /**
+ * Permet de faire un traitement sur des valeurs et d'en retourner
+ * des nouvelles.
+ */
+ static public interface MapFunction<E> { // MapFunction
+
+ /**
+ * Permet de faire un traitement sur value et de retourne une nouvelle
+ * valeur.
+ *
+ * @param value la valeur courante sur lequel il faut faire le traitement
+ * @return la nouvelle valeur à mettre dans la matrice à la place de
+ * l'ancienne.
+ */
+ E apply(E value);
+
+ } // MapFunction
+
+}
Added: trunk/nuiton-utils/src/test/java/org/nuiton/util/MatrixMapTest.java
===================================================================
--- trunk/nuiton-utils/src/test/java/org/nuiton/util/MatrixMapTest.java (rev 0)
+++ trunk/nuiton-utils/src/test/java/org/nuiton/util/MatrixMapTest.java 2011-06-21 11:00:42 UTC (rev 2151)
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2011 poussin. All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.nuiton.util;
+
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author poussin
+ */
+public class MatrixMapTest {
+
+ @Test
+ public void testSubMatrix() {
+ List<String> sem1 = Arrays.asList("xA", "xB", "xC", "xD");
+ List<String> sem2 = Arrays.asList("ya", "yb", "yc", "yd", "ye");
+ MatrixMap<String> m = MatrixMap.Factory.create(new List[]{sem1, sem2});
+
+ m.setValue("a1", "xA", "ya");
+ m.setValue("a2", "xA", "yb");
+ m.setValue("a3", "xA", "yc");
+ m.setValue("a4", "xA", "yd");
+ m.setValue("a5", "xA", "ye");
+
+ m.setValue("b1", "xB", "ya");
+ m.setValue("b2", "xB", "yb");
+ m.setValue("b3", "xB", "yc");
+ m.setValue("b4", "xB", "yd");
+ m.setValue("b5", "xB", "ye");
+
+ m.setValue("c1", "xC", "ya");
+ m.setValue("c2", "xC", "yb");
+ m.setValue("c3", "xC", "yc");
+ m.setValue("c4", "xC", "yd");
+ m.setValue("c5", "xC", "ye");
+
+ m.setValue("d1", "xD", "ya");
+ m.setValue("d2", "xD", "yb");
+ m.setValue("d3", "xD", "yc");
+ m.setValue("d4", "xD", "yd");
+ m.setValue("d5", "xD", "ye");
+
+ System.out.println(m.toString());
+
+ MatrixMap sub = m.getSubMatrix(0, "xA", "xC");
+
+ System.out.println(sub);
+ }
+
+ @Test
+ public void testExtend() {
+ List<String> sem1 = Arrays.asList("xA", "xB", "xC");
+ List<String> sem2 = Arrays.asList("ya", "yb", "yc", "yd", "ye");
+ MatrixMap<String> m = MatrixMap.Factory.createElastic(new List[]{sem1, sem2});
+
+ m.setValue("a1", "xA", "ya");
+ m.setValue("a2", "xA", "yb");
+ m.setValue("a3", "xA", "yc");
+ m.setValue("a4", "xA", "yd");
+ m.setValue("a5", "xA", "ye");
+
+ m.setValue("b1", "xB", "ya");
+ m.setValue("b2", "xB", "yb");
+ m.setValue("b3", "xB", "yc");
+ m.setValue("b4", "xB", "yd");
+ m.setValue("b5", "xB", "ye");
+
+ m.setValue("c1", "xC", "ya");
+ m.setValue("c2", "xC", "yb");
+ m.setValue("c3", "xC", "yc");
+ m.setValue("c4", "xC", "yd");
+ m.setValue("c5", "xC", "ye");
+
+ System.out.println(m.toString());
+
+ m.setValue("d1", "xD", "ya");
+ m.setValue("d2", "xD", "yb");
+ m.setValue("d3", "xD", "yc");
+ m.setValue("d4", "xD", "yd");
+ m.setValue("d5", "xD", "ye");
+
+ System.out.println(m.toString());
+ }
+
+}
1
0
Author: echatellier
Date: 2011-06-16 10:31:43 +0200 (Thu, 16 Jun 2011)
New Revision: 2150
Url: http://nuiton.org/repositories/revision/nuiton-utils/2150
Log:
#1594 Update xwork to 2.2.3
Modified:
trunk/pom.xml
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2011-06-08 14:05:35 UTC (rev 2149)
+++ trunk/pom.xml 2011-06-16 08:31:43 UTC (rev 2150)
@@ -185,7 +185,7 @@
<nuitonI18nVersion>2.4</nuitonI18nVersion>
<aspectwerkzVersion>2.0</aspectwerkzVersion>
- <xworkVersion>2.2.1.1</xworkVersion>
+ <xworkVersion>2.2.3</xworkVersion>
<!-- i18n configuration -->
<i18n.bundles>fr_FR,en_GB,es_ES</i18n.bundles>
1
0
08 Jun '11
Author: echatellier
Date: 2011-06-08 16:05:35 +0200 (Wed, 08 Jun 2011)
New Revision: 2149
Url: http://nuiton.org/repositories/revision/nuiton-utils/2149
Log:
Add comment about grep and sed methods on windows
Modified:
trunk/nuiton-utils/src/main/java/org/nuiton/util/FileUtil.java
Modified: trunk/nuiton-utils/src/main/java/org/nuiton/util/FileUtil.java
===================================================================
--- trunk/nuiton-utils/src/main/java/org/nuiton/util/FileUtil.java 2011-06-07 20:09:12 UTC (rev 2148)
+++ trunk/nuiton-utils/src/main/java/org/nuiton/util/FileUtil.java 2011-06-08 14:05:35 UTC (rev 2149)
@@ -1181,6 +1181,9 @@
*
* http://java.sun.com/javase/6/docs/technotes/guides/io/example/Grep.java
*
+ * May fail on windows with error :
+ * The requested operation cannot be performed on a file with a user-mapped section open
+ *
* @param searchRegex regex to search into file
* @param f file to search into
* @param encoding encoding to use
@@ -1230,6 +1233,9 @@
/**
* Java implementation for the unix grep command.
*
+ * May fail on windows with error :
+ * The requested operation cannot be performed on a file with a user-mapped section open
+ *
* @param searchRegex regex to search into file
* @param rootDirectory directory to seacrh into
* @param fileRegex regex for file to find in {@code rootDirectory}
@@ -1257,6 +1263,9 @@
/**
* Search for files matching regex in current directory.
*
+ * May fail on windows with error :
+ * The requested operation cannot be performed on a file with a user-mapped section open
+ *
* @param searchRegex regex to search into file
* @param fileRegex regex for file to find in current dir
* @param encoding encoding to use
@@ -1279,6 +1288,9 @@
*
* Oginal source code from http://kickjava.com/src/org/apache/lenya/util/SED.java.htm.
*
+ * May fail on windows with error :
+ * The requested operation cannot be performed on a file with a user-mapped section open
+ *
* @param searchRegex Prefix which shall be replaced
* @param replace Prefix which is going to replace the original
* @param file File which sed shall be applied
@@ -1328,6 +1340,9 @@
/**
* Java implementation for the unix sed command.
*
+ * May fail on windows with error :
+ * The requested operation cannot be performed on a file with a user-mapped section open
+ *
* @param searchRegex regex to search into file
* @param replace string to replace matching patterns
* @param rootDirectory directory to search into
@@ -1350,6 +1365,9 @@
/**
* Java implementation for the unix sed command.
*
+ * May fail on windows with error :
+ * The requested operation cannot be performed on a file with a user-mapped section open
+ *
* @param searchRegex regex to search into file
* @param replace string to replace matching patterns
* @param fileRegex regex for file to find in current dir
1
0
Author: tchemit
Date: 2011-06-07 22:09:12 +0200 (Tue, 07 Jun 2011)
New Revision: 2148
Url: http://nuiton.org/repositories/revision/nuiton-utils/2148
Log:
Update mavenpom4redmineAndCentral to 2.5.5.
Modified:
trunk/pom.xml
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2011-05-26 16:00:41 UTC (rev 2147)
+++ trunk/pom.xml 2011-06-07 20:09:12 UTC (rev 2148)
@@ -33,7 +33,7 @@
<parent>
<groupId>org.nuiton</groupId>
<artifactId>mavenpom4redmineAndCentral</artifactId>
- <version>2.5.4</version>
+ <version>2.5.5</version>
</parent>
<artifactId>nuiton-utils-parent</artifactId>
1
0