All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.math.matrix.MatrixStringEncoder Maven / Gradle / Ivy

The newest version!
/* *##% NuitonMatrix
 * Copyright (C) 2004 - 2009 CodeLutin
 *
 * 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 General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * . ##%*/

package org.nuiton.math.matrix;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.ConvertUtilsBean;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.util.StringUtil;

/**
 * Convert matrix into {@link String} and inverse.
 *
 * Method from this class are non "static" to be overriden.
 * 
 * Created: 04 mar. 2009
 *
 * @author chatellier
 * @version $Revision: 120 $
 *
 * Mise a jour: $Date: 2009-03-03 11:19:18 +0100 (mar. 03 mars 2009) $
 * par : $Author: chatellier $
 */
public class MatrixStringEncoder { // MatrixStringEncoder

    /** Class logger */
    private static Log log = LogFactory.getLog(MatrixStringEncoder.class);

    /**
     * Convert a matrix in string representation.
     * 
     * String representation is composed in (ordered) :
     *  - name
     *  - dim
     *  - dimNames
     *  - semantics
     *  - data
     *  
     * @param matrix matrix to convert
     * @return a {@link String} representation
     */
    public String getMatrixAsString(MatrixND matrix) {
        StringBuffer representationBuffer = new StringBuffer();
        representationBuffer.append("["); // top level
        representationBuffer.append(matrix.getName());
        representationBuffer.append(",");
        representationBuffer.append(getDimToString(matrix.getDim()));
        representationBuffer.append(",");
        representationBuffer.append(getDimensionNamesToString(matrix
                .getDimensionNames()));
        representationBuffer.append(",");
        representationBuffer
                .append(getSemanticsToString(matrix.getSemantics()));
        representationBuffer.append(",");
        representationBuffer.append(matrix.toList().toString());
        representationBuffer.append("]"); // top level
        return representationBuffer.toString();
    }

    /**
     * Parse string as matrix representation.
     * 
     * str must be in following format :
     *  - [name,dim,dimNames,semantics,data]
     * @param str
     * @return matrix representation
     */
    public MatrixND getMatrixFromString(String str) {

        MatrixND matrix = null;

        // composed of 5 groups
        Pattern matrixPattern = Pattern
                .compile("^\\[(.*),(\\[.*\\]),(\\[.*\\]),(\\[.*\\]),(\\[.*\\])\\]$");
        Matcher matcher = matrixPattern.matcher(str);

        if (matcher.find()) {
            String name = matcher.group(1);
            String dimString = matcher.group(2);
            String dimNamesString = matcher.group(3);
            String semanticsString = matcher.group(4);
            String dataString = matcher.group(5);

            int[] dim = getDimFromString(dimString);
            String[] dimNames = getDimensionNamesFromString(dimNamesString);
            List[] semantics = getSemanticsFromString(semanticsString);

            matrix = MatrixFactory.getInstance().create(name, semantics,
                    dimNames);
            List data = MatrixHelper.convertStringToList(dataString);
            matrix.fromList(data);
        } else {
            throw new IllegalArgumentException("Can't parse \"" + str
                    + "\" as string");
        }

        return matrix;
    }

    /**
     * Matrix dim to string.
     * 
     * @param dimArray dim to convert.
     * @return a {@link String} representation
     */
    public String getDimToString(int[] dimArray) {
        String result = "[";
        String sep = "";
        for (int i = 0; i < dimArray.length; i++) {
            result += sep + dimArray[i];
            sep = ", ";
        }
        result += "]";
        return result;
    }

    /**
     * String to matrix dim.
     * 
     * @param str string to parse
     * @return dim array
     */
    public int[] getDimFromString(String str) {
        String localStr = str.trim();
        if (localStr.startsWith("[") && localStr.endsWith("]")) {
            localStr = localStr.substring(1, localStr.length() - 1); // remove [ and ]
        }
        String[] dimAsString = StringUtil.split(localStr, ",");
        int[] result = new int[dimAsString.length];
        int i = 0;
        for (String dim : dimAsString) {
            int val = Integer.parseInt(dim.trim());
            result[i++] = val;
        }
        return result;
    }

    /**
     * Dim names to string.
     * 
     * @param dimNamesArray dim array to convert
     * @return a {@link String} representation
     */
    public String getDimensionNamesToString(String[] dimNamesArray) {
        String result = "[";
        String sep = "";
        for (int i = 0; i < dimNamesArray.length; i++) {
            result += sep + '"' + StringEscapeUtils.escapeJava(dimNamesArray[i]) + '"';
            sep = ", ";
        }
        result += "]";
        return result;
    }

    /**
     * String to dim names array.
     * 
     * @param str string to parse
     * @return a {@link String} representation
     */
    public String[] getDimensionNamesFromString(String str) {
        String localStr = str.trim();
        if (localStr.startsWith("[") && localStr.endsWith("]")) {
            localStr = localStr.substring(1, localStr.length() - 1); // remove [ and ]
        }
        String[] result = StringUtil.split(localStr, ",");
        for (int i = 0; i < result.length; i++) {
            result[i] = result[i].trim();
            if (result[i].startsWith("\"") && result[i].endsWith("\"")) {
                String resultString = result[i].substring(1, result[i].length() - 1);// remove " and "
                resultString = StringEscapeUtils.unescapeJava(resultString);
                result[i] = resultString;
            }
        }
        return result;
    }

    /**
     * Semantics array to string.
     * 
     * @param semanticsArray semantics array
     * @return string names array
     */
    public String getSemanticsToString(List[] semanticsArray) {
        StringBuffer result = new StringBuffer("[");
        for (int i = 0; i < semanticsArray.length; i++) {
            result.append("[");
            List semantics = semanticsArray[i];
            for (Iterator it = semantics.iterator(); it.hasNext();) {
                appendString(result, it.next());
                if (it.hasNext()) {
                    result.append(", ");
                }
            }
            result.append("]");
            if ((i + 1) < semanticsArray.length) {
                result.append(", ");
            }
        }
        return result.append("]").toString();
    }

    /**
     * String to semantics.
     * 
     * @param str la chaine representant la semantique
     * @return semantics list
     */
    public List[] getSemanticsFromString(String str) {
        String localStr = str.trim();
        if (localStr.startsWith("[") && localStr.endsWith("]")) {
            localStr = localStr.substring(1, localStr.length() - 1); // remove [ and ]
        }
        String[] sems = StringUtil.split(localStr, ",");

        List[] result = new List[sems.length];

        for (int i = 0; i < sems.length; i++) {
            result[i] = splitObjects(sems[i]);
        }

        return result;
    }

    /**
     * Recréé chaque object de la chaine de caractere et l'ajoute dans une liste
     * la chaine est de la forme.
     * 
     * [null(), java.lang.String("toto"), ...]
     * 
     * @param str la chaine representant
     * @return semantics list
     */
    public List splitObjects(String str) {
        List result = new LinkedList();
        String localStr = str.trim();
        if (localStr.startsWith("[") && localStr.endsWith("]")) {
            localStr = localStr.substring(1, localStr.length() - 1);
        }
        String[] elems = StringUtil.split(localStr, ",");
        for (String elem : elems) {
            elem = elem.trim();
            int openbrace = elem.indexOf('(');
            String objectType = elem.substring(0, openbrace);
            String objectString = elem.substring(openbrace + 1,
                    elem.length() - 1);

            if ("null".equals(objectType)) {
                result.add(null);
            } else {
                ConvertUtilsBean converter = getConverter();
                Object o;
                try {
                    o = converter.convert(objectString, Class
                            .forName(objectType));
                } catch (Exception e) {
                    // if can't create objet, put String representation as semantics
                    o = objectType + "(" + objectString + ")";
                    if (log.isWarnEnabled()) {
                        log.warn("Continuing but can't convert object in matrix from String: '"
                                        + o + "'");
                    }
                    if (log.isDebugEnabled()) {
                        log.debug(
                                "Continuing but can't convert object in matrix from String: '"
                                        + o + "'", e);
                    }
                }
                result.add(o);
            }
        }

        return result;
    }

    /**
     * Append object type and value.
     * 
     * qualifiedName(value)
     * java.lang.String(test)
     * java.lang.Double(4.5)
     * 
     * @param buffer buffer to append to
     * @param o object to put on buffer
     * @return buffer
     */
    public StringBuffer appendString(StringBuffer buffer, Object o) {
        if (o == null) {
            buffer.append("null()");
        } else {
            String qualifiedName = getQualifiedName(o);
            buffer.append(qualifiedName).append("(");
            ConvertUtilsBean converter = getConverter();
            buffer.append(converter.convert(o));
            buffer.append(")");
        }
        return buffer;
    }

    /**
     * Get object qualified name.
     * 
     * Can't be overridden to put another impl.
     * 
     * @param o object to get qualified name
     * @return object qualified class name
     */
    public String getQualifiedName(Object o) {
        String qualifiedName = o.getClass().getName();
        return qualifiedName;
    }

    /**
     * Get commons-beanutils bean converter.
     * @return a {@link ConvertUtilsBean}
     */
    public ConvertUtilsBean getConverter() {
        BeanUtilsBean instance = BeanUtilsBean.getInstance();
        ConvertUtilsBean cub = instance.getConvertUtils();
        return cub;
    }

} // MatrixStringEncoder