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

org.nuiton.wikitty.WikittyUtil Maven / Gradle / Ivy

The newest version!
/*
 * #%L
 * Wikitty :: api
 * %%
 * Copyright (C) 2009 - 2010 CodeLutin, Benjamin Poussin
 * %%
 * 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
 * .
 * #L%
 */

package org.nuiton.wikitty;

import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.security.Key;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import net.iharder.Base64;
import net.objecthunter.exp4j.ExpressionBuilder;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.converters.DateTimeConverter;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.util.DateUtil;
import org.nuiton.wikitty.entities.BusinessEntity;
import org.nuiton.wikitty.entities.BusinessEntityImpl;
import org.nuiton.wikitty.entities.FieldType;
import org.nuiton.wikitty.entities.Wikitty;
import org.nuiton.wikitty.entities.WikittyExtension;
import org.nuiton.wikitty.entities.WikittyField;
import org.nuiton.wikitty.entities.WikittyImpl;
import org.nuiton.wikitty.entities.WikittyTypes;
import org.nuiton.wikitty.generator.WikittyTransformerUtil;
import org.nuiton.wikitty.services.WikittyServiceEnhanced;

/**
 * Util static method for wikitty.
 * 
 * @author poussin
 * @version $Revision$ki
 * 
 * Last update: $Date$ by : $Author$
 */
public class WikittyUtil implements WikittyConstants {

    /** Pattern que doivent respecter les noms des extensions */
    public static final String extensionNamePattern = "\\w+";
    /** Pattern que doivent respecter les noms des champs des extensions */
    public static final String extensionFieldNamePattern = "\\w+";

    public static final String DEFAULT_MAJOR_VERSION = "0";
    public static final String DEFAULT_MINOR_VERSION = "0";
    public static final String DEFAULT_MAJOR_VERSION_PREFIX = DEFAULT_MAJOR_VERSION + ".";
    public static final String DEFAULT_VERSION = DEFAULT_MAJOR_VERSION_PREFIX + DEFAULT_MINOR_VERSION;

    public static final String DATE_NOW = "NOW";
    public static final String DATE_TODAY = "TODAY";

    public static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ'Z'";

    // #1386 sletellier 20110309 : solr date is return like 2011-03-09T08:06:27.593Z
    public static final String SOLR_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

    /** to use log facility, just put in your code: log.info(\"...\"); */
    static private Log log = LogFactory.getLog(WikittyUtil.class);

    /** used to format date for solr */
    protected static final TimeZone CANONICAL_TZ = TimeZone.getTimeZone("UTC");
    protected static final Locale CANONICAL_LOCALE = Locale.US;

    // FastDateFormat is thread-safe
    static final protected FastDateFormat solrDateFormat = FastDateFormat.getInstance(
            DATE_FORMAT, CANONICAL_TZ, CANONICAL_LOCALE);

    public static final String[] DATE_FORMAT_ALLOWED = {
        solrDateFormat.getPattern(),
        DATE_FORMAT,
        SOLR_DATE_FORMAT,
        new SimpleDateFormat().toPattern(),  // local dependent
        "dd/MM/yy",
        "dd/MM/yy hh:mm",
        "dd/MM/yyyy",
        "dd/MM/yyyy hh:mm",
        "dd-MM-yy",
        "dd-MM-yy hh:mm",
        "dd-MM-yyyy",
        "dd-MM-yyyy hh:mm",
        "yyyyMMdd",
        "yyyy-MM-dd",
        "yyyy-MM-dd hh:mm",
        "yyyy-MM-dd'T'hh:mm:ss'Z'",
        "yyMMdd",
    };

    /** no break space, used to parse BigDecimal */
    static final public String nbsp = new String(new int[]{160}, 0, 1);
    
//    /** All date format parser used to convert string to date */
//    static final protected DateFormat[] parserDateFormats = new DateFormat[] {
//            solrDateFormat, DateFormat.getInstance(),
//    // TODO poussin 20090813: add other date syntax
//    };

    static public Date parseDate(String dateAsString) throws ParseException {        
        return DateUtils.parseDate(dateAsString, DATE_FORMAT_ALLOWED);
    }

    static public String formatDate(Date date) throws ParseException {
        if (date == null) {
            return null;
        }
        return solrDateFormat.format(date);
    }
    
    // TODO poussin 20090902 use spring configuration to add mapping in this
    // variable
    /** contains mapping between interface and concret class that must be used */
    static public Map, Class> interfaceToClass = new HashMap, Class>();

    /**
     * Pattern for tag value: tag="value" or tag=value. value can contains '"'
     */
    static protected String tagValuesPatternString = "(\\w*)=(\".*?(?group 1: type (string)
     * 
  • group 2: name (string) *
  • group 3: lower bound (number) can be null *
  • group 4: upper bound (number) can be null, mutually exclusive with group 5 *
  • group 5: upper bound (n or *) can be null *
  • group 6: unique can be null (legacy configuration, prefer use of {@code unique="true"} *
  • group 7: not null can be null (legacy configuration, prefer use of {@code notNull="true"} *
  • group 8: all tag/value (toto=titi tutu=tata;lala tata="truc bidulle") */ static protected Pattern fieldPattern = Pattern .compile( "\\s*(\\w+)\\s+(\\w+)(?:\\s*\\[(\\d+)-(?:(\\d+)|([\\*n]))\\])?(?:\\s+(unique))?(?:\\s+(not null))?((?:\\s+" + tagValuesPatternString + ")*)", Pattern.DOTALL); /** * parse FieldType definition and return field name. All field information * are stored in fieldType object passed in argument * * @param def string field definition * @param fieldType object used to put parsed information * @return field name parsed in definition */ static public String parseField(String def, FieldType fieldType) { Matcher match = fieldPattern.matcher(def); if (match.matches()) { fieldType.setType(WikittyTypes.parse(match.group(1))); String name = match.group(2); String lower = match.group(3); if (lower != null) { fieldType.setLowerBound(Integer.parseInt(lower)); } String upper = match.group(4); if (upper != null) { fieldType.setUpperBound(Integer.parseInt(upper)); } String noupper = match.group(5); if (noupper != null) { fieldType.setUpperBound(FieldType.NOLIMIT); } // parse group 8 before String tagValues = match.group(8); Map tagValuesMap = tagValuesToMap(tagValues); // legacy field definition : unique String uniqueString = match.group(6); if (uniqueString != null) { tagValuesMap.put(FieldType.TAG_UNIQUE, "true"); if (log.isWarnEnabled()) { log.warn("Old field constraints definition detected \"unique\" ; prefer use of \"unique=true\""); } } // legacy field definition : not null String notNullString = match.group(7); if (notNullString != null) { tagValuesMap.put(FieldType.TAG_NOT_NULL, "true"); log.warn("Old field constraints definition detected \"non null\" ; prefer use of \"notNull=true\""); } fieldType.setTagValues(tagValuesMap); return name; } else { throw new WikittyException(String.format( "Bad FieldType definition '%s'", def)); } } /** * Serialize tagValues to string * * @param tagValues tagValues as map * @return string represent tagValues */ public static String tagValuesToString(Map tagValues) { String result = WikittyTransformerUtil.tagValuesToString(tagValues); return result; } /** * Deserialize tagValues to map * * @param tagValues tagValues as string * @return map represent tagValues */ public static Map tagValuesToMap(String tagValues) { Map result = new HashMap(); if (tagValues != null) { Matcher matchTagValues = tagValuesPattern.matcher(tagValues); while (matchTagValues.find()) { String tag = matchTagValues.group(1); String value = matchTagValues.group(2); if (value.startsWith("\"") && value.endsWith("\"")) { // delete start and end " value = value.substring(1, value.length() - 1); // if value is between ", then inners " are quoted value = StringEscapeUtils.unescapeJava(value); } result.put(tag, value); } } return result; } /** * Create map from string representation. * * ex: "String name", "Wikitty attachment[0-*]" * * @param definitions extension definition * @return extensions map */ public static LinkedHashMap buildFieldMapExtension( String... definitions) { LinkedHashMap result = new LinkedHashMap(); for (String def : definitions) { FieldType fieldType = new FieldType(); String name = WikittyUtil.parseField(def, fieldType); if (log.isDebugEnabled()) { log.debug("parse " + def + " => " + fieldType.toDefinition(name)); } result.put(name, fieldType); } return result; } /** * if version if null return 0 else version If version is not in format * ., ".0" is added to the version * * @param version version * @return the normalized version */ public static String normalizeVersion(String version) { if (version == null || "".equals(version)) { version = "0"; } if (version.indexOf(".") == -1) { version += ".0"; } return version; } /** * Return true if v1 and v2 are equals. * * 1.2.0 et 1.2 ne sont pas egaux * * @param v1 version * @param v2 version * * @return {@code true} if v1 == v2 */ public static boolean versionEquals(String v1, String v2) { if (v1 == null || v2 == null) { return false; } return normalizeVersion(v1).equals(normalizeVersion(v2)); } /** * Return true if v1 greater than v2. * * @param v1 version * @param v2 version * @return {@code true} if v1 > v2 */ public static boolean versionGreaterThan(String v1, String v2) { if (v1 != null && v2 == null) { return true; } if (v1 == null) { return false; } String[] v1s = normalizeVersion(v1).split("\\."); String[] v2s = normalizeVersion(v2).split("\\."); int minlen = Math.min(v1s.length, v2s.length); for (int i = 0; i < minlen; i++) { if (!v1s[i].equals(v2s[i])) { return Integer.parseInt(v1s[i]) > Integer.parseInt(v2s[i]); } } // si on est ici c que tout les nombres sont v1[i] = v2[i] return v1s.length > v2s.length; } /** * Increment minor version. * * @param v version as 3.1 where 1 is minor and 3 major * @return incremented minor number (3.1 -> 3.2) */ static public String incrementMinorRevision(String v) { String result; if (v == null || "".equals(v)) { result = "0.1"; } else { v = v.trim(); String[] mm = v.split("\\."); if (mm.length == 1) { result = v + ".1"; } else { int i = Integer.parseInt(mm[1]) + 1; result = mm[0] + "." + i; } } return result; } /** * increment major version. * * @param v version as 3.2 where 2 is minor and 3 major * @return incremented major number and reset minor number (3.2 -> 4.0) */ static public String incrementMajorRevision(String v) { String result; if (v == null || "".equals(v)) { result = "1.0"; } else { v = v.trim(); String[] mm = v.split("\\."); int i = Integer.parseInt(mm[0]) + 1; result = i + ".0"; } return result; } /** Pattern de recherche des field dans les chaines de formatage * @see {@link Formatter#formatSpecifier} */ static protected Pattern formatMatcher = Pattern.compile("%([^0-9][^|$]*)(?:\\|(.*?))?(\\$(:?[-#+ 0,(\\<]*)?(:?\\d+)?(:?\\.\\d+)?[tT]?[a-zA-Z])"); /** * Format wikitty for string representation. * exemple: *
  • "%Person.lastName$s %Person.firstName$s: %Person.birthday$tm %Person.birthday$te,%Person.birthday$tY" *
  • "Hello %Person.firstName|unknown$s" if firstName field doesn't exist, unknow is used *
  • "My company %Employee.company,Company.name|unknown$s" if employee has company field and this company has name field * * @param format format as {@link http://download.oracle.com/javase/6/docs/api/java/util/Formatter.html#syntax} * except that position is replace with fq field name. * @param w wikitty to format * @return String that represent the wikitty */ static public String format(String formatWikitty, Wikitty w) { List> fields = new ArrayList>(); StringBuffer formatBuffer = new StringBuffer(); int i = 0; // on collect tous les champs demande et leur valeur par defaut // et en meme temps on cree la chaine formatBuffer qui substitue les // champs par des numeros Matcher matcher = formatMatcher.matcher(formatWikitty); while(matcher.find()) { String fieldAsked = matcher.group(1); String defaultValue = matcher.group(2); fields.add(new ImmutablePair(fieldAsked, defaultValue)); // i is incremented before replace, because String.format start at 1 not 0 matcher.appendReplacement(formatBuffer, "%"+(++i)+"$3"); } matcher.appendTail(formatBuffer); // la vrai chaine de formatage pour String.format String format = formatBuffer.toString(); List values = new ArrayList(fields.size()); // on recherche la valeur de chaque champs demande for (Pair pair : fields) { String fieldAsked = pair.getKey(); String defaultValue = pair.getValue(); Object value = getValue(w, fieldAsked); Object defaultValueObject = getValue(w, defaultValue); // on ajoute dans la liste la valeur du champs values.add(ObjectUtils.defaultIfNull(value, defaultValueObject)); } if (log.isDebugEnabled()) { log.debug(String.format("%s -> %s (with %s from %s)", formatWikitty, format, values, fields)); } // use standard String.format String result = String.format(format, values.toArray()); return result; } /** * Recupere la valeur du champs pointer par fieldAsked. Si fieldAsked contient * des ',' alors on parcours les differents objets pour arrive a satisfaire la demande * Si fieldAsked ne represente pas un champs alors on retourne fieldAsked * @param w * @param fieldAsked * @return */ static private Object getValue(Wikitty w, String fieldAsked) { String initialFieldAsked = fieldAsked; Wikitty wtmp = w; // recherche de l'objet reel sur lequel prendre la valeur du champs if (StringUtils.contains(fieldAsked, ",")) { String path = StringUtils.substringBeforeLast(fieldAsked, ","); fieldAsked = StringUtils.substringAfterLast(fieldAsked, ","); for (String field : StringUtils.split(path, ",")) { if (wtmp.hasField(field)) { String extName = WikittyExtension.extractExtensionName(field); String fieldName = WikittyExtension.extractFieldName(field); wtmp = wtmp.getFieldAsWikitty(extName, fieldName, false); } else { wtmp = null; } if (wtmp == null) { break; } } } Object value = null; if(wtmp != null) { // recuperation de la valeur du champs if (wtmp.hasField(fieldAsked)) { String extName = WikittyExtension.extractExtensionName(fieldAsked); String fieldName = WikittyExtension.extractFieldName(fieldAsked); // on essai toujours de recuperer l'objet plutot que l'id si // possible en 1er value = wtmp.getFieldAsWikitty(extName, fieldName, false); if (value == null) { // pas un wikitty ou pas pre-charge, on demande simplement le champs value = wtmp.getFqField(fieldAsked); } } else { // on a pas trouver le champs, on retourne la chaine car ce n'etait pas un champs value = initialFieldAsked; } } return value; } /** * Get value as Binary. * * @param value null and empty return empty byte[] * * @return value as byte[] */ static public byte[] toBinary(Object value) { byte[] result = null; if (value == null || "".equals(value)) { result = new byte[0]; // default to 0 // poussin 20120305 non, il ne faut pas convertir automatiquement les // chaine en base64. Si on le souhaite, il faut le faire explicitement // par exemple pour l'export csv/xml // } else if (value instanceof String) { // try { // result = Base64.decode((String) value); // } catch (IOException eee) { // throw new WikittyException("Bad Base64 format", eee); // } } else if (value instanceof byte[]) { result = (byte[]) value; } else if (value instanceof File) { try { result = FileUtils.readFileToByteArray((File) value); } catch (IOException eee) { throw new WikittyException("Unable to read the file " + value, eee); } } else { result = value.toString().getBytes(); } return result; } /** * Get value as BigDecimal. * * If value is String, mathematical evaluation is done. * ex: 2+2*2 create BigDecimal(6) as result * * @param value null and empty string are casted to '0' value. * @throws WikittyException on NumberFormatException or if value object can't be casted to number. * * @return value as BigDecimal */ static public BigDecimal toBigDecimal(Object value) { BigDecimal result = null; if (value == null || "".equals(value)) { result = new BigDecimal(0); // default to 0 } else if (value instanceof BigDecimal) { result = (BigDecimal) value; } else { String all = value.toString(); try { double d = new ExpressionBuilder(all).build().evaluate(); result = new BigDecimal(d); } catch (Exception eee) { String s = all; // suppression de tous les blancs pour un parsing plus sur s = StringUtils.deleteWhitespace(s); s = StringUtils.remove(s, nbsp); try { // on commence par essayer par la methode la plus simple result = new BigDecimal(s); } catch (NumberFormatException yyy) { // on essaie avec un parse, en dernier ressort // si jamais le nombre etait localise (ex: 99,987.76) try { DecimalFormat parser = new DecimalFormat(); // on veut des BigDecimal en resultat et pas un Double parser.setParseBigDecimal(true); Number n = parser.parse(s); // meme si on demande au parser un BigDecimal, il retourne // certaine fois un Double (NaN, Infinit, ...). // mais dans ce cas la, ca revient a une erreur de parsing // qui explosera avec le cast result = (BigDecimal)n; } catch (Exception zzz) { // on fait suivre eee et non pas yyy ou zzz car l'erreur initial // est bien eee, yyy et zzz sont juste le fallback, et certain fois // on aurait un ClassCastException qui n'a rien a voir, // mais on log tout de meme zzz log.debug(String.format( "Try one, can't convert value '%s(%s)' to numeric, this exception is not throw but just logged", value, getClass(value)), yyy); log.debug(String.format( "Try two, can't convert value '%s(%s)' to numeric, this exception is not throw but just logged", value, getClass(value)), zzz); throw new WikittyException( String.format("Can't convert value '%s(%s)' to numeric", value, getClass(value)), eee); } } } } return result.stripTrailingZeros(); } /** * Convert object to boolean: *
      *
    • - null => false - 0 => false - numeric => true *
    • - object.toString() == false => false - other => true *
    * * @param value value * @return value as boolean */ static public boolean toBoolean(Object value) { boolean result = false; if (value != null) { if (value instanceof Boolean) { result = (Boolean) value; } else if (value instanceof Number) { result = !((Number) value).equals(0); } else { // try to convert to Boolean result = !"false".equalsIgnoreCase(value.toString()); } } return result; } /** * Convert Object to String representation if value is not null * Wikitty is converted to id, and Date to SolrDateFormat * * @param value value to convert * @return String representation or null */ static public String toString(Object value) { String result = null; if (value != null) { if (value instanceof String) { result = (String) value; } else if (value instanceof WikittyImpl) { result = ((Wikitty) value).getWikittyId(); } else if (value instanceof BusinessEntity) { result = ((BusinessEntity) value).getWikittyId(); } else if (value instanceof Date) { result = solrDateFormat.format((Date) value); } else if (value instanceof Calendar) { result = solrDateFormat.format((Calendar)value); } else if (value instanceof BigDecimal) { result = ((BigDecimal)value).stripTrailingZeros().toString(); } else if (value instanceof byte[]) { // poussin 20120305 il faut etre coherent avec le toBinary qui fait un String.toByte // result = Base64.encodeBytes((byte[]) value); result = new String((byte[]) value); } else { // try to convert to String result = value.toString(); } } return result; } /** * Converti un objet en une date. * Date et Calendar sont directement supporte, tous les autres types sont * transformer en String et parser pour construire la Date. * *
  • Si la chaine est 'NOW', la date courante est utilisee avec l'heure courant *
  • Si la chaine est 'TODAY', la date courante est utilisee avec l'heure a 0 * * L'implantation de cette methode n'est pas satisfaisante, il faudrait * trouver un meilleur algo. Le but est de parser la date suivant different * pattern, puis derrière cette date il peut y avoir des demandes de modification * (math date) par exemple +3MONTHS. Pour qu'une date soit valide, il faut * que le parsing de la date fonctionne et que le parsing de la partie math * fonctionne. Mais le découpage des deux parties n'est pas simple a trouver * vu que la date peut-etre dans de tres nombreux format et que la partie * math peut-etre elle aussi complexe :( * * @param value * @return */ static public Date toDate(Object value) { Date result = null; // poussin 20140730 pour null ou chaine vide on laisse a null // c'est util pour les formulaires web qui sont soumis avec des champs sans valeurs if (value != null && !"".equals(value)) { if (value instanceof Date) { result = (Date) value; } else if (value instanceof Calendar) { result = ((Calendar)value).getTime(); } else { // try to convert to Date String v = String.valueOf(value); if (StringUtils.startsWithIgnoreCase(v, DATE_NOW)) { try { Date tryDate = new Date(); v = StringUtils.substringAfter(v, DATE_NOW); result = dateModifier(tryDate, v); } catch (ParseException eee) { if (log.isDebugEnabled()) { log.debug(String.format( "Can't convert value '%s' of type '%s' to Date because math date is wrong", value, getClass(value)), eee); } } } else if (StringUtils.startsWithIgnoreCase(v, DATE_TODAY)) { try { Date tryDate = new Date(); tryDate = DateUtil.setMinTimeOfDay(tryDate); v = StringUtils.substringAfter(v, DATE_TODAY); result = dateModifier(tryDate, v); } catch (ParseException eee) { if (log.isDebugEnabled()) { log.debug(String.format( "Can't convert value '%s' of type '%s' to Date because math date is wrong", value, getClass(value)), eee); } } } else { for (String pattern : DATE_FORMAT_ALLOWED) { // remove ' from pattern because 'T' is 3 char in patten and 1 in value if (StringUtils.length(v) < StringUtils.length(StringUtils.remove(pattern, "'"))) { // if pattern longer than v then parse is impossble continue; } String tmp = StringUtils.substring(v, 0, pattern.length()); try { Date tryDate = DateUtils.parseDate(tmp, pattern); // parse success String ajust = StringUtils.substring(v, pattern.length()); // try to interpret and of date (ex: +3Years) result = dateModifier(tryDate, ajust); break; } catch (ParseException eee) { if (log.isDebugEnabled()) { log.debug(String.format( "Can't convert value '%s' of type '%s' to Date because math date is wrong", value, getClass(value)), eee); } } catch (Exception eee) { if (log.isDebugEnabled()) { log.debug(String.format("Can't parse date '%s'", tmp), eee); } } } } if (result == null) { throw new WikittyException(String.format( "Can't convert value '%s' of type '%s' to Date", value, getClass(value))); } } } return result; } static private Date dateModifier(Date date, String modifier) throws ParseException { Date result = date; // try to interpret and of date (ex: +3Years) if (StringUtils.length(modifier) > 0) { DateMathParser parser = new DateMathParser(TimeZone.getDefault(), Locale.getDefault()); parser.setNow(result); result = parser.parseMath(modifier); } return result; } /** * Return wikitty id and not wikitty objet because this method can be call * on server or client side and it's better to keep conversion between id * and objet to the caller * * @param value * @return id of wikitty object or null */ static public String toWikitty(Object value) { String result = null; if (value != null) { if (value instanceof String) { result = (String) value; } else if (value instanceof Wikitty) { result = ((Wikitty) value).getWikittyId(); } else if (value instanceof BusinessEntity) { result = ((BusinessEntity) value).getWikittyId(); } else { // try to convert to String result = value.toString(); } } if (StringUtils.isBlank(result)) { // id never can be empty or blank. If result is blank then result must be null result = null; } return result; } /** * Convert value to list. * * @param elements type * @param value value to convert * @param clazz element class * @return unmodifiable list */ @SuppressWarnings({"unchecked"}) static public List toList(Object value, Class clazz) { try { List result = (List) value; if (result != null) { result = Collections.unmodifiableList(result); } return result; } catch (Exception eee) { throw new WikittyException(String.format( "Can't convert value '%s' to list", getClass(value)), eee); } } /** * Converti un BigDecimal en un nombre * * @param target la class du nombre * @param v * @return */ static public Number toNumber(Class target, BigDecimal v) { Number result = v; if (BigDecimal.class.isAssignableFrom(target)) { result = v; } else if (Byte.TYPE.isAssignableFrom(target) || Byte.class.isAssignableFrom(target)) { result = v.byteValue(); } else if (Double.TYPE.isAssignableFrom(target) || Double.class.isAssignableFrom(target)) { result = v.doubleValue(); } else if (Float.TYPE.isAssignableFrom(target) || Float.class.isAssignableFrom(target)) { result = v.floatValue(); } else if (Integer.TYPE.isAssignableFrom(target) || Integer.class.isAssignableFrom(target)) { result = v.intValue(); } else if (Long.TYPE.isAssignableFrom(target) || Long.class.isAssignableFrom(target)) { result = v.longValue(); } else if (Short.TYPE.isAssignableFrom(target) || Short.class.isAssignableFrom(target)) { result = v.shortValue(); } else if (BigInteger.class.isAssignableFrom(target)) { result = v.toBigInteger(); } return result; } /** * Convert object o for export CSV/XML. * * @param field field description * @param o field value * @return solr representation */ static public String toStringForExport(FieldType field, Object o) { String result = null; if (o != null) { if (o instanceof String) { result = (String) o; } else { switch (field.getType()) { case BINARY: result = Base64.encodeBytes((byte[]) o); break; case DATE: // Date date = (Date)o; result = WikittyUtil.solrDateFormat.format((Date) o); break; default: result = WikittyUtil.toString(o); break; } } } return result; } /** * Convert object o for export CSV/XML. * * @param field field description * @param o field value * @return solr representation */ static public Object fromStringForExport(FieldType field, String s) { Object result = null; switch (field.getType()) { case BINARY: try { result = Base64.decode(s); } catch (IOException eee) { throw new WikittyException("Can't decode string", eee); } break; default: // pour les autres conversion, les conversions auto du wikitty // suffise result = s; break; } return result; } /** * Convert object o for indexation * * @param field field description * @param o field value * @return solr representation */ static public String toStringForSearchEngine(FieldType field, Object o) { String result = null; if (o != null) { switch (field.getType()) { case BINARY: // don't index binary result = ""; break; case DATE: // Date date = (Date)o; result = (o instanceof String) ? (String) o : WikittyUtil.solrDateFormat.format((Date) o); break; default: result = WikittyUtil.toString(o); break; } } return result; } /** * Convert string field representation to correct value type. * * @param field field description * @param s string value * @return object in type of field */ static public Object fromString(FieldType field, String s) { Object result = null; switch (field.getType()) { case BINARY: result = WikittyUtil.toBinary(s); break; case BOOLEAN: result = WikittyUtil.toBoolean(s); break; case DATE: result = WikittyUtil.toDate(s); break; case NUMERIC: result = WikittyUtil.toBigDecimal(s); break; default: result = s; break; } return result; } /** * Return class of argument, if argument is null, return null. * * @param value * @return class of value or null */ static public Class getClass(Object value) { Class result = null; if (value != null) { result = value.getClass(); } return result; } /** * Create new instance of WikittyDto without Wikitty object passed in * argument. If arguement is Interface try to add 'Impl' to find * instanciable class. *

    * clazz parameter must be child of WikittyDto or business interface * * @param element type * * @param clazz class of the new instance * @return new instance of clazz */ static public E newInstance(Class clazz) { try { Class clazzInstanciable = clazz; if (clazzInstanciable.isInterface()) { log.debug(String.format("Argument '%s' is interface looking for implementation", clazzInstanciable.getName())); // looking for implementation of this interface if (interfaceToClass.containsKey(clazz)) { clazzInstanciable = interfaceToClass.get(clazz); } else { // default use xxxImpl.class clazzInstanciable = Class.forName(clazz.getName() + "Impl"); } } if (!BusinessEntityImpl.class .isAssignableFrom(clazzInstanciable)) { throw new WikittyException(String.format( "Your class '%s' don't extends BusinessEntityImpl", clazz .getName())); } E result = (E)clazzInstanciable.newInstance(); return result; } catch (Exception eee) { throw new WikittyException(String.format( "Can't create new instance of %s", clazz), eee); } } /** * Create new Business Entity with specified Wikitty * @param target Business Entity class * @param w wikitty to used * @return new instance of object wanted or null if w is null */ static public E newInstance(Class target, Wikitty w) { E result = null; if (w != null) { result = newInstance(target); BusinessEntityImpl bean = (BusinessEntityImpl) result; bean.setWikitty(w); } return result; } /** * Cast Business object to another Business Object * If source don't have target extension, this extension is added * * @param source business entity source * @param target business entity class wanted * @return new instance of object wanted or null if source is null */ public E newInstance(Class target, BusinessEntityImpl source) { E result = null; if (source != null) { result = newInstance(target, source.getWikitty()); } return result; } /** * Create new Business Entity List from wikitties * @param target Business Entity class * @param wikitties list of wikitties * @return new list of Business Entity or null if wikitties is null */ static public List newInstance(Class target, List wikitties) { List result = null; if (wikitties != null) { result = new ArrayList(wikitties.size()); for (Wikitty w : wikitties) { if (w == null) { result.add(null); } else { result.add(newInstance(target, w)); } } } return result; } /** * Create new Business Entity Set from wikitties * @param target Business Entity class * @param wikitties set of wikitties * @return new set of Business Entity or null if wikitties is null */ static public Set newInstance(Class target, Set wikitties) { Set result = null; if (wikitties != null) { result = new LinkedHashSet(wikitties.size()); for (Wikitty w : wikitties) { if (w == null) { result.add(null); } else { result.add(newInstance(target, w)); } } } return result; } /** * Create new instance of BusinessEntity from Wikitty object passed in argument. * If argument is Interface try to add 'Impl' to find instanciable class. *

    * clazz parameter must be child of Business interface * * * @param entity type * @param wikittyService wikitty service * @param clazz class of the new instance * @param w wikitty object to use internaly for in new instance * @return new instance * * @deprecated since 3.3 il n'est pas coherent d'acceder au serveur lorsqu'on * instancie un objet. La verification de la securite de toute facon ne * se fait qu'au moment de la sauvegarde. */ @Deprecated static public E newInstance(String securityToken, WikittyService wikittyService, Class clazz, Wikitty w) { try { Class clazzInstanciable = clazz; if (clazzInstanciable.isInterface()) { log.debug(String.format("Argument '%s' is interface looking for implementation", clazzInstanciable.getName())); // looking for implementation of this interface if (interfaceToClass.containsKey(clazz)) { clazzInstanciable = interfaceToClass.get(clazz); } else { // default use xxxImpl.class clazzInstanciable = Class.forName(clazz.getName() + "Impl"); } } if (!BusinessEntityImpl.class .isAssignableFrom(clazzInstanciable)) { throw new WikittyException(String.format( "Your class '%s' don't extends BusinessEntityImpl", clazz .getName())); } E result = null; if (w != null) { try { // try to find constructor with wikitty argument Constructor cons = clazzInstanciable .getConstructor(Wikitty.class); Object[] parms = { null }; result = (E) cons.newInstance(parms); BusinessEntityImpl bean = (BusinessEntityImpl) result; // FIXME poussin 20111229 on ne devrait pas avoir besoin // d'acceder au serveur ici :(. Voir si le check est vraiment // util checkExtensionVersion(securityToken, wikittyService, w, bean); bean.setWikitty(w); } catch (NoSuchMethodException noerror) { if (log.isErrorEnabled()) { log.error(String.format( "Can't find constructor with wikitty arguement in '%s'," + "we try with setWikitty method", clazzInstanciable.getName()), noerror); } } } return result; } catch (Exception eee) { throw new WikittyException(String.format( "Can't create new instance of %s", clazz), eee); } } /** * Check extension default, i.e. if bean contain a extension with a great * version as in wikitty. In this case the extension is stored in last * version and wikitty it is restored again. The upgrade data is during the * restoration. * * @param wikittyService * @param wikitty * @param entity * @return */ static public Wikitty checkExtensionVersion( String securityToken, WikittyService wikittyService, Wikitty wikitty, BusinessEntityImpl entity) { Wikitty result = wikitty; boolean upgradeData = false; Collection extensions = entity.getStaticExtensions(); for (WikittyExtension ext : extensions) { String extName = ext.getName(); if (wikitty.hasExtension(extName)) { WikittyExtension oldExt = wikitty.getExtension(extName); String newVersion = ext.getVersion(); String oldVersion = oldExt.getVersion(); if (WikittyUtil.versionGreaterThan(newVersion, oldVersion)) { wikittyService.storeExtension( securityToken, Arrays.asList(ext)); upgradeData = true; } } } if (upgradeData) { String wikittyId = wikitty.getWikittyId(); result = WikittyServiceEnhanced.restore( wikittyService, securityToken, wikittyId); } return result; } /** * Try to cast obj to class passed in argument. * * @param element type * @param obj object to cast * @param clazz new type of object * @return the same object but casted to class wanted, except for primitive * where is new object if obj BigDecimal */ public static E cast(Object obj, Class clazz) { E result = null; if (obj != null) { if (clazz.isAssignableFrom(obj.getClass())) { result = clazz.cast(obj); } else if (obj instanceof BigDecimal) { BigDecimal bd = (BigDecimal) obj; if (clazz == int.class || clazz == Integer.class) { result = clazz.cast(bd.intValue()); } else if (clazz == float.class || clazz == Float.class) { result = clazz.cast(bd.floatValue()); } } if (result == null) { throw new WikittyException("Unable to cast from '" + obj.getClass().getName() + "' to " + clazz.getName()); } } return result; } /** * Clone wikitty with new id if {@code genId} is true * * @param wikittyToClone concerned * @param genId true to generate new id * @return cloned wikitty * @throws CloneNotSupportedException if exception is thrown */ public static Wikitty clone(Wikitty wikittyToClone, boolean genId) throws CloneNotSupportedException { if (genId) { Wikitty w = new WikittyImpl(); w.replaceWith(wikittyToClone, true); return w; } return wikittyToClone.clone(); } /** * SecurityToken is used like wikitty id and must begin with UUID_ * * @return SecurityToken that can be used like wikitty id */ static public String genSecurityTokenId() { String result = "_" + Math.abs(Math.random()); result = result.replace(".", ""); // on supprime le '.' dans le nombre aleatoire result = genUID() + result; return result; } // private static BASE64Encoder enc = new BASE64Encoder(); public static String genUID() { return UUID.randomUUID().toString(); /* * we can gain 10 chars per ID on applying a base64 on the UID. long * mostSignificant = uid.getMostSignificantBits(); long leastSignificant * = uid.getLeastSignificantBits(); long current = mostSignificant; * byte[] b = new byte[16]; for ( int i = 0; i < 16; i++ ) { b[i] = * (byte) (current & 0xff); current = current >> 8; if ( i == 7 ) * current = leastSignificant; } return enc.encode(b); */ } /** * given a fully qualified field name, return the name of the extension * TODO poussin 20101208 redondant code with {@link WikittyExtension#extractExtensionName(java.lang.String)} */ public static String getExtensionNameFromFQFieldName(String fqFieldName) { String[] fqFieldElements = fqFieldName.split(FQ_FIELD_NAME_SEPARATOR_REGEX); return fqFieldElements[0]; } /** * given a fully qualified field name, return the name of the field * TODO poussin 20101208 redondant code with {@link WikittyExtension#extractFieldName(java.lang.String)} */ public static String getFieldNameFromFQFieldName(String fqFieldName) { try { String[] fqFieldElements = fqFieldName.split(FQ_FIELD_NAME_SEPARATOR_REGEX); return fqFieldElements[1]; } catch(ArrayIndexOutOfBoundsException eee) { throw new WikittyException("Field is not fully qualified field:" + fqFieldName, eee); } } /** given names of extension and field, return a fully qualified field name */ public static String getFQFieldName(String extensionName, String fieldName) { String fqFieldName = extensionName + FQ_FIELD_NAME_SEPARATOR + fieldName; return fqFieldName; } /** given a fully qualified meta-extension name, return the name of the meta-extension. * @return null if fqFieldName doesn't contains a meta extension */ public static String getMetaExtensionNameFromFQMetaExtensionName(String fqFieldName) { String metaExtensionName = null; if (fqFieldName.indexOf(FQ_META_EXTENSION_SEPARATOR) != -1) { String[] fqElements = fqFieldName.split(FQ_META_EXTENSION_SEPARATOR_REGEX); metaExtensionName = fqElements[1]; } return metaExtensionName; } /** given a fully qualified meta-extension name, return the name of the extension */ public static String getExtensionNameFromFQMetaExtensionName(String fqFieldName) { String[] fqElements = fqFieldName.split(FQ_META_EXTENSION_SEPARATOR_REGEX); return fqElements[0]; } /** given names of meta-extension and extension, return a fully qualified meta-extension name */ public static String getFQMetaExtensionName(String metaExtensionName, String extensionName) { String fqFieldName = extensionName + FQ_META_EXTENSION_SEPARATOR + metaExtensionName; return fqFieldName; } /** * Get the FQN of a metaExtension field. The FQN may depend of an extension * getMetaFieldName(metaExt, ext, field) returns "ext:metaExt.field" * getMetaFieldName(metaExt, null, field) returns "metaExt.field" */ public static String getMetaFieldName(String metaExtensionName, String extensionName, String fieldName) { String actualExtensionName = metaExtensionName; if (extensionName != null) { actualExtensionName = getFQMetaExtensionName(metaExtensionName, extensionName); } String metaFieldName = getFQFieldName(actualExtensionName, fieldName); return metaFieldName; } /* * For BusinessEntities */ /** * Extract all id for beans * * @param entities to extract ids * @return ids of entities */ public static List getIds(Iterable entities) { List ids = new ArrayList(); if (entities != null) { for (BusinessEntity bean : entities) { if (bean != null) { ids.add(bean.getWikittyId()); } } } return ids; } /** * Extract field value corresponding of fqField in entity * * @param fqField fqField concerned * @param entity entity concerned * @param return type * @return value of field */ @SuppressWarnings({"unchecked"}) public static E getFieldValueFromFQFieldName(String fqField, BusinessEntity entity) { return (E) entity.getFieldAsObject(WikittyUtil.getExtensionNameFromFQFieldName(fqField), WikittyUtil.getFieldNameFromFQFieldName(fqField)); } /** * Extract all field values corresponding of fqField in list of entities * * @param fqField fqField concerned * @param entities entities concerned * @param return type * @return value of field */ public static List getFieldValuesFromFQFieldName(String fqField, Iterable entities) { List fieldValues = new ArrayList(); if (entities != null) { for (BusinessEntity entity : entities) { if (entity != null) { // Get field for specified fqField E field = getFieldValueFromFQFieldName(fqField, entity); fieldValues.add(field); } } } return fieldValues; } /** * Recherche le meilleur nom a utiliser comme pseudo pour cette machine. * Un UUID est toujours ajouter en debut, pour potentiellement lancer * plusieurs application en meme temps sur la meme machine et etre sur que * le pseudo soit bien unique. * * Le pseudo, n'est pas seulement un UUID, pour pouvoir facilement faire * du debug en entrant dans le channel et voir les ip des machiens connectees * * @return */ static public String getUniqueLoginName() { String result = UUID.randomUUID().toString(); try { String ipv4 = null; String ipv6 = null; for (Enumeration e = NetworkInterface.getNetworkInterfaces(); e.hasMoreElements();) { NetworkInterface netint = e.nextElement(); for (Enumeration a = netint.getInetAddresses(); a.hasMoreElements();) { InetAddress ip = a.nextElement(); if (ip instanceof Inet4Address) { if ((ipv4 == null || "127.0.0.1".equals(ipv4))) { ipv4 = ip.getHostAddress(); } } else if (ip instanceof Inet6Address) { if (ipv6 == null) { ipv6 = ip.getHostAddress(); } } else { log.error("Can't get ip from no ipv4 and no ipv6: " + ip); } } } if (ipv4 != null) { result = ipv4 + "=" + result; } else if (ipv6 != null) { result = ipv6 + "=" + result; } } catch (Exception eee) { log.error("Can't compute unique name from network interface", eee); } return result; } /** * Try to convert object to wikitty, this is possible only if object is * Wikitty or BusinessEntityImpl. If convertion is not possible return null. * @param o object to convert * @return null is convertion is impossible Wikitty otherwize. */ static public Wikitty getWikitty(Object o) { Wikitty result = null; if (o instanceof Wikitty) { // W, rien a faire result = (Wikitty)o; } else if (o instanceof BusinessEntityImpl) { // BusinessEntityImpl, il faut recuperer les wikitty result = ((BusinessEntityImpl)o).getWikitty(); } return result; } /** * * @param service * @param securityToken * @param entity * @return * @deprecated since 3.3 use {@link WikittyClient#getWikitty(org.nuiton.wikitty.entities.BusinessEntity)} */ @Deprecated static public Wikitty getWikitty(WikittyService service, String securityToken, BusinessEntity entity) { Wikitty result; if (entity instanceof BusinessEntityImpl) { result = ((BusinessEntityImpl) entity).getWikitty(); } else { String id = entity.getWikittyId(); result = WikittyServiceEnhanced.restore(service, securityToken, id); //try settings all fields except version try { //get all fields Class entityClass = entity.getClass(); Field[] fields = entityClass.getDeclaredFields(); for(Field field:fields){ //for each field that got WikittyField annotation if (field.isAnnotationPresent(WikittyField.class)){ //get the attribute's wikitty fqn WikittyField annotation = field.getAnnotation(WikittyField.class); String fieldFQN = annotation.fqn(); //set the value Method m = entityClass.getMethod("get" + StringUtils.capitalize(field.getName())); Object value = m.invoke(entity); result.setFqField(fieldFQN, value); } } } catch (Exception eee) { throw new WikittyException("Could not transform entity to Wikitty", eee); } //manually set version result.setWikittyVersion(entity.getWikittyVersion()); } return result; } /** * redefinition du DateConverter car par defaut il ne support pas la valeur * null :(. * * Ceci est un copier coller de DateConverter + AbstractConverter * (et plus de copie/coller qu'il ne faut a cause de methode et de champs * avec de mauvaise visibilite :() */ static private class WikittyDateConverter extends DateTimeConverter { /** to use log facility, just put in your code: log.info(\"...\"); */ static private Log log = LogFactory.getLog(WikittyDateConverter.class); private static final String PACKAGE = "org.apache.commons.beanutils.converters."; /** * Construct a java.util.Date Converter that throws * a ConversionException if an error occurs. */ public WikittyDateConverter() { super(); } /** * Construct a java.util.Date Converter that returns * a default value if an error occurs. * * @param defaultValue The default value to be returned * if the value to be converted is missing or an error * occurs converting the value. */ public WikittyDateConverter(Object defaultValue) { super(defaultValue); } /** * Return the default type this Converter handles. * * @return The default type this Converter handles. */ @Override protected Class getDefaultType() { return Date.class; } /** * Convert the input object into an output object of the * specified type. * * @param type Data type to which this value should be converted * @param value The input value to be converted * @return The converted value. * successfully and no default is specified. */ @Override public Object convert(Class type, Object value) { Class sourceType = value == null ? null : value.getClass(); Class targetType = primitive(type == null ? getDefaultType() : type); if (log.isDebugEnabled()) { log.debug("Converting" + (value == null ? "" : " '" + toString(sourceType) + "'") + " value '" + value + "' to type '" + toString(targetType) + "'"); } value = convertArray(value); // Fixed poussin 20101208 le bout de code original qui pose probleme // pour la conversion null. This is only modification // Missing Value if (value == null) { return null; } sourceType = value.getClass(); try { // Convert --> String if (targetType.equals(String.class)) { return convertToString(value); // No conversion necessary } else if (targetType.equals(sourceType)) { if (log.isDebugEnabled()) { log.debug(" No conversion required, value is already a " + toString(targetType)); } return value; // Convert --> Type } else { Object result = convertToType(targetType, value); if (log.isDebugEnabled()) { log.debug(" Converted to " + toString(targetType) + " value '" + result + "'"); } return result; } } catch (Throwable t) { return handleError(targetType, value, t); } } /** * Change primitve Class types to the associated wrapper class. * @param type The class type to check. * @return The converted type. */ Class primitive(Class type) { if (type == null || !type.isPrimitive()) { return type; } if (type == Integer.TYPE) { return Integer.class; } else if (type == Double.TYPE) { return Double.class; } else if (type == Long.TYPE) { return Long.class; } else if (type == Boolean.TYPE) { return Boolean.class; } else if (type == Float.TYPE) { return Float.class; } else if (type == Short.TYPE) { return Short.class; } else if (type == Byte.TYPE) { return Byte.class; } else if (type == Character.TYPE) { return Character.class; } else { return type; } } /** * Provide a String representation of a java.lang.Class. * @param type The java.lang.Class. * @return The String representation. */ String toString(Class type) { String typeName = null; if (type == null) { typeName = "null"; } else if (type.isArray()) { Class elementType = type.getComponentType(); int count = 1; while (elementType.isArray()) { elementType = elementType.getComponentType(); count++; } typeName = elementType.getName(); for (int i = 0; i < count; i++) { typeName += "[]"; } } else { typeName = type.getName(); } if (typeName.startsWith("java.lang.") || typeName.startsWith("java.util.") || typeName.startsWith("java.math.")) { typeName = typeName.substring("java.lang.".length()); } else if (typeName.startsWith(PACKAGE)) { typeName = typeName.substring(PACKAGE.length()); } return typeName; } } static public WikittyDateConverter dateConverter = new WikittyDateConverter(); /** * Met a jout les donnees d'un wikitty via les informations d'un BusinessEntity * @param w le wikitty a mettre a jour (peut-etre null) * @param be le business entity utilise pour mettre a jour le wikitty */ static public void updateWikitty(Wikitty w, BusinessEntity be) { // le wikitty peut etre null, par exemple a cause de la security if (w == null) { return; } // on copie les champs des entities dans les wikitties recuperes // try settings all fields except version try { Class entityClass = be.getClass(); //get all fields Field[] fields = entityClass.getDeclaredFields(); for(Field field:fields){ //for each field that got WikittyField annotation if (field.isAnnotationPresent(WikittyField.class)){ //get the attribute's wikitty fqn WikittyField annotation = field.getAnnotation(WikittyField.class); String fieldFQN = annotation.fqn(); //set the value Method m = entityClass.getMethod("get" + StringUtils.capitalize(field.getName())); Object value = m.invoke(be); w.setFqField(fieldFQN, value); } } //manually set version w.setWikittyVersion(be.getWikittyVersion()); } catch (Exception eee) { throw new WikittyException("Could not transform entity to Wikitty", eee); } } /** * Copy all properties (get/set) from source to destination, * except wikitty property * * @param source * @param dest * @throws Exception */ static public void copyBean(Object source, Object dest) throws Exception { BeanUtilsBean bu = BeanUtilsBean.getInstance(); bu.getConvertUtils().register(dateConverter, Date.class); PropertyDescriptor[] origDescriptors = bu.getPropertyUtils().getPropertyDescriptors(source); PropertyDescriptor versionDescriptor = null; for (int i = 0; i < origDescriptors.length; i++) { String name = origDescriptors[i].getName(); if ("wikittyVersion".equals(name)) { versionDescriptor = origDescriptors[i]; continue; } if (log.isDebugEnabled()) { log.debug("work on prop :" + name); } if ("class".equals(name)) { continue; // No point in trying to set an object's class } if ("wikitty".equals(name)) { continue; // No point in trying to set an wikitty } if (bu.getPropertyUtils().isReadable(source, name) && bu.getPropertyUtils().isWriteable(dest, name)) { if (log.isInfoEnabled()) { log.info("prop is copiable:" + name); } try { Object value = bu.getPropertyUtils().getSimpleProperty(source, name); bu.copyProperty(dest, name, value); } catch (NoSuchMethodException e) { // Should not happen } } } //XXX ymartel 2014/02/14 : how to make it cleaner ? Must force the wikittyVersion be the last to set (to avoid all upgrade caused by fields modification) if (versionDescriptor != null) { String name = versionDescriptor.getName(); try { Object value = bu.getPropertyUtils().getSimpleProperty(source, name); bu.copyProperty(dest, name, value); } catch (NoSuchMethodException e) { // Should not happen } } } static public byte[] crypt(String algo, String password, byte[] value) { try { byte[] result; if (StringUtils.isBlank(password)) { // on ne crypt pas s'il n'y a pas de mot de passe result = value; } else { byte[] passwordInBytes = password.getBytes(); Key clef = new SecretKeySpec(passwordInBytes, algo); Cipher cipher = Cipher.getInstance(algo); cipher.init(Cipher.ENCRYPT_MODE, clef); result = cipher.doFinal(value); } return result; } catch (Exception eee) { throw new WikittyException("Can't crypt data", eee); } } static public byte[] decrypt(String algo, String password, byte[] value) { try { byte[] result; if (StringUtils.isBlank(password)) { // on ne decrypt pas s'il n'y a pas de mot de passe result = value; } else { byte[] passwordInBytes = password.getBytes(); Key clef = new SecretKeySpec(passwordInBytes, algo); Cipher cipher = Cipher.getInstance(algo); cipher.init(Cipher.DECRYPT_MODE, clef); result = cipher.doFinal(value); } return result; } catch (Exception eee) { throw new WikittyException("Can't decrypt data", eee); } } /** * Creation d'une map contenant une seule valeur. On utilise pas * {@link Collections#singletonMap} car on ne peut plus changer la valeur * alors qu'on en a besoin dans Wikitty, lorsqu'on converti des donnees * * @param k la cle * @param v la valeur * @return une nouvelle map avec 1 seul element et un load factor a 1 */ static public Map singletonMap(Object k, Object v) { HashMap result = new HashMap(1, 1); result.put(k, v); return result; } /** * Creation d'une list contenant une seule valeur. On utilise pas * {@link Collections#singletonList} car on ne peut plus changer la valeur * alors qu'on en a besoin dans Wikitty, lorsqu'on converti des donnees * * @param o la valeur * @return une nouvelle list avec 1 seul element et une taille initiale de 1 */ static public List singletonList(Object o) { List result = new ArrayList(1); result.add(o); return result; } }