r329 - trunk/tutti-service/src/main/java/fr/ifremer/tutti/service
Author: tchemit Date: 2013-02-05 10:15:28 +0100 (Tue, 05 Feb 2013) New Revision: 329 Url: http://forge.codelutin.com/projects/tutti/repository/revisions/329 Log: Improve decorator api Added: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/TuttiDecorator.java Modified: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/DecoratorService.java Modified: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/DecoratorService.java =================================================================== --- trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/DecoratorService.java 2013-02-05 09:14:56 UTC (rev 328) +++ trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/DecoratorService.java 2013-02-05 09:15:28 UTC (rev 329) @@ -39,10 +39,8 @@ import fr.ifremer.tutti.persistence.entities.referential.Species; import fr.ifremer.tutti.persistence.entities.referential.Vessel; import fr.ifremer.tutti.persistence.entities.referential.Zone; -import org.apache.commons.jxpath.JXPathContext; import org.nuiton.util.decorator.Decorator; import org.nuiton.util.decorator.DecoratorProvider; -import org.nuiton.util.decorator.MultiJXPathDecorator; import java.io.Serializable; @@ -110,26 +108,26 @@ @Override protected void loadDecorators() { - registerMultiJXPathDecorator(Program.class, "${name}$s", SEPARATOR, " - "); - registerMultiJXPathDecorator(Cruise.class, "${name}$s", SEPARATOR, " - "); - registerMultiJXPathDecorator(TuttiProtocol.class, "${name}$s", SEPARATOR, " - "); - registerMultiJXPathDecorator(FishingOperation.class, "${stationNumber}$s#${fishingOperationNumber}$s#${multirigAggregation}$s#${gearShootingStartDate}$td/%4$tm/%4$tY", SEPARATOR, " - "); - registerMultiJXPathDecorator(Zone.class, "${label}$s#${name}$s", SEPARATOR, " - "); + registerTuttiDecorator(Program.class, "${name}$s", SEPARATOR, " - "); + registerTuttiDecorator(Cruise.class, "${name}$s", SEPARATOR, " - "); + registerTuttiDecorator(TuttiProtocol.class, "${name}$s", SEPARATOR, " - "); + registerTuttiDecorator(FishingOperation.class, "${stationNumber}$s#${fishingOperationNumber}$s#${multirigAggregation}$s#${gearShootingStartDate}$td/%4$tm/%4$tY", SEPARATOR, " - "); + registerTuttiDecorator(Zone.class, "${label}$s#${name}$s", SEPARATOR, " - "); // registerMultiJXPathDecorator(Vessel.class, "${name}$s#${internalRegistrationCode}$s", SEPARATOR, " - "); - registerMultiJXPathDecorator(Country.class, "${label}$s#${name}$s", SEPARATOR, " - "); - registerMultiJXPathDecorator(Gear.class, "${label}$s#${name}$s", SEPARATOR, " - "); - registerMultiJXPathDecorator(Person.class, "${firstName}$s#${lastName}$s#${department}$s", SEPARATOR, " "); - registerMultiJXPathDecorator(FishingOperationLocation.class, "${label}$s#${name}$s", SEPARATOR, " - "); - registerMultiJXPathDecorator(Caracteristic.class, "${parameterName}$s#${matrixName}$s#${fractionName}$s#${methodName}$s", SEPARATOR, " - "); - registerMultiJXPathDecorator(Caracteristic.class, CARACTERISTIC_WITH_UNIT, "${parameterName}$s#${matrixName}$s#${fractionName}$s#${methodName}$s (${unit}$s)", SEPARATOR, " - "); - registerMultiJXPathDecorator(CaracteristicQualitativeValue.class, "${name}$s", SEPARATOR, " - "); - registerMultiJXPathDecorator(Species.class, "${refTaxCode}$s#${name}$s", SEPARATOR, " - "); + registerTuttiDecorator(Country.class, "${label}$s#${name}$s", SEPARATOR, " - "); + registerTuttiDecorator(Gear.class, "${label}$s#${name}$s", SEPARATOR, " - "); + registerTuttiDecorator(Person.class, "${firstName}$s#${lastName}$s#${department}$s", SEPARATOR, " "); + registerTuttiDecorator(FishingOperationLocation.class, "${label}$s#${name}$s", SEPARATOR, " - "); + registerTuttiDecorator(Caracteristic.class, "${parameterName}$s#${matrixName}$s#${fractionName}$s#${methodName}$s", SEPARATOR, " - "); +// registerMultiJXPathDecorator(Caracteristic.class, CARACTERISTIC_WITH_UNIT, "${parameterName}$s#${matrixName}$s#${fractionName}$s#${methodName}$s (${unit}$s)", SEPARATOR, " - "); + registerTuttiDecorator(CaracteristicQualitativeValue.class, "${name}$s", SEPARATOR, " - "); + registerTuttiDecorator(Species.class, "${refTaxCode}$s#${name}$s", SEPARATOR, " - "); // registerMultiJXPathDecorator(Species.class, SPECIES_BY_CRUISE_CODE, "${cruiseCode}$s#${refTaxCode}$s#${name}$s", SEPARATOR, " - "); - registerMultiJXPathDecorator(Species.class, SPECIES_BY_REF_TAX_CODE, "${refTaxCode}$s", SEPARATOR, " - "); - registerMultiJXPathDecorator(Species.class, SPECIES_BY_GENUS, "${name}$s", SEPARATOR, " - "); - registerMultiJXPathDecorator(SpeciesProtocol.class, "${speciesId}", SEPARATOR, " - "); - registerMultiJXPathDecorator(Attachment.class, "${name}$s", SEPARATOR, " - "); - registerMultiJXPathDecorator(LabelAware.class, "${label}$s", SEPARATOR, " - "); + registerTuttiDecorator(Species.class, SPECIES_BY_REF_TAX_CODE, "${refTaxCode}$s", SEPARATOR, " - "); + registerTuttiDecorator(Species.class, SPECIES_BY_GENUS, "${name}$s", SEPARATOR, " - "); + registerTuttiDecorator(SpeciesProtocol.class, "${speciesId}", SEPARATOR, " - "); + registerTuttiDecorator(Attachment.class, "${name}$s", SEPARATOR, " - "); + registerTuttiDecorator(LabelAware.class, "${label}$s", SEPARATOR, " - "); registerDecorator(new Decorator<Float>(Float.class) { private static final long serialVersionUID = 1L; @@ -138,13 +136,23 @@ return bean == null ? "" : String.valueOf(bean); } }); - registerDecorator(new VesselMultiJXPathDecorator()); + registerDecorator(new VesselDecorator()); - registerDecorator(SPECIES_BY_CRUISE_CODE, new SpeciesMultiJXPathDecorator()); + registerDecorator(SPECIES_BY_CRUISE_CODE, new SpeciesDecorator()); + registerTuttiDecorator(Caracteristic.class, CARACTERISTIC_WITH_UNIT, "${parameterName}$s#${matrixName}$s#${fractionName}$s#${methodName}$s (${unit}$s)", SEPARATOR, " - "); } + + public void registerTuttiDecorator(Class<?> klass, String expression, String separator, String separatorReplacement) { + super.registerDecorator(TuttiDecorator.newDecorator(klass, expression, separator, separatorReplacement)); + } + + public void registerTuttiDecorator(Class<?> klass, String name, String expression, String separator, String separatorReplacement) { + super.registerDecorator(name, TuttiDecorator.newDecorator(klass, expression, separator, separatorReplacement)); + } }; } + static { n_("tutti.property.protocol"); n_("tutti.property.label"); @@ -180,57 +188,42 @@ n_("tutti.property.caracteristic"); } - public static class SpeciesMultiJXPathDecorator extends MultiJXPathDecorator<Species> implements Cloneable { + public static class SpeciesDecorator extends TuttiDecorator<Species> implements Cloneable { private static final long serialVersionUID = 1L; - public SpeciesMultiJXPathDecorator() throws IllegalArgumentException, NullPointerException { + public SpeciesDecorator() throws IllegalArgumentException, NullPointerException { super(Species.class, "${cruiseCode}$s#${refTaxCode}$s#${name}$s", DecoratorService.SEPARATOR, " - "); } @Override - protected Comparable<Comparable<?>> getTokenValue(JXPathContext jxcontext, String token) { - Comparable result = super.getTokenValue(jxcontext, token); + protected Object onNullValue(Species bean, String token) { + Object result = null; if ("cruiseCode".equals(token)) { - if (result == null || "null".equals(result)) { - result = _("tutti.propety.no.species.cruiseCode"); - } + result = _("tutti.propety.no.species.cruiseCode"); } return result; } - - @Override - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } } - public static class VesselMultiJXPathDecorator extends MultiJXPathDecorator<Vessel> implements Cloneable { + public static class VesselDecorator extends TuttiDecorator<Vessel> implements Cloneable { private static final long serialVersionUID = 1L; - public VesselMultiJXPathDecorator() throws IllegalArgumentException, NullPointerException { + public VesselDecorator() throws IllegalArgumentException, NullPointerException { super(Vessel.class, "${name}$s#${internalRegistrationCode}$s", DecoratorService.SEPARATOR, " - "); } @Override - protected Comparable<Comparable<?>> getTokenValue(JXPathContext jxcontext, String token) { - Comparable result = super.getTokenValue(jxcontext, token); + protected Object onNullValue(Vessel bean, String token) { + Object result = null; if ("internalRegistrationCode".equals(token)) { - if (result == null || "null".equals(result)) { - result = _("tutti.propety.no.vessel.internalRegistrationCode"); - } + result = _("tutti.propety.no.vessel.internalRegistrationCode"); } else if ("name".equals(token)) { - if (result == null || "null".equals(result)) { - result = _("tutti.propety.no.vessel.name"); - } + result = _("tutti.propety.no.vessel.name"); } return result; } - - @Override - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } } + } Added: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/TuttiDecorator.java =================================================================== --- trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/TuttiDecorator.java (rev 0) +++ trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/TuttiDecorator.java 2013-02-05 09:15:28 UTC (rev 329) @@ -0,0 +1,222 @@ +package fr.ifremer.tutti.service; + +/* + * #%L + * Tutti :: Service + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2012 - 2013 Ifremer + * %% + * 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/gpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Preconditions; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.Maps; +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.decorator.JXPathDecorator; +import org.nuiton.util.decorator.MultiJXPathDecorator; + +import java.beans.PropertyDescriptor; +import java.io.Serializable; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +/** + * TODO + * + * @author tchemit <chemit@codelutin.com> + * @since TODO + */ +public class TuttiDecorator<O> extends MultiJXPathDecorator<O> implements Cloneable { + + private static final long serialVersionUID = 1L; + + /** Logger. */ + private static final Log log = LogFactory.getLog(TuttiDecorator.class); + + protected final Map<String, Method> tokenMethods; + + protected final LoadingCache<O, String> cache; + + protected boolean useCache; + + public static <O> TuttiDecorator<O> newDecorator(Class<O> internalClass, + String expression, + String separator, + String separatorReplacement) { + return new TuttiDecorator<O>(internalClass, expression, separator, separatorReplacement); + } + + protected TuttiDecorator(Class<O> internalClass, + String expression, + String separator, + String separatorReplacement) throws IllegalArgumentException, NullPointerException { + super(internalClass, + expression, + separator, + separatorReplacement); + tokenMethods = Maps.newHashMap(); + PropertyDescriptor[] descriptors = + PropertyUtils.getPropertyDescriptors(type); + + for (String token : getTokens()) { + Method m = null; + for (PropertyDescriptor propertyDescriptor : descriptors) { + if (propertyDescriptor.getName().equals(token)) { + m = propertyDescriptor.getReadMethod(); + break; + } + } + if (m == null) { + throw new IllegalArgumentException("could not find the property " + token + " in " + type); + } + tokenMethods.put(token, m); + } + + int i = 0; + for (Context<O> OContext : contexts) { + OContext.setComparator(new TuttiDecoratorComparator<O>(getProperty(i++))); + } + + this.cache = CacheBuilder.newBuilder().build(new CacheLoader<O, String>() { + @Override + public String load(O key) throws Exception { + String result; + if (key == null) { + result = ""; + } else { + result = TuttiDecorator.this.toString(key); + } + return result; + } + }); + } + + public boolean isUseCache() { + return useCache; + } + + public void setUseCache(boolean useCache) { + this.useCache = useCache; + cache.invalidateAll(); + } + + @Override + public String toString(Object bean) { + O bean1 = (O) bean; + String result = null; + + if (useCache) { + + // try first in cache + try { + result = cache.get(bean1); + } catch (ExecutionException e) { + if (log.isErrorEnabled()) { + log.error("Could not obtain from cache", e); + } + } + } + if (result == null) { + + if (bean != null) { + Object[] args = new Object[nbToken]; + + String[] tokens = getTokens(); + for (int i = 0; i < nbToken; i++) { + String token = tokens[i]; + Object value = getValue(bean1, token); + if (value == null) { + value = onNullValue(bean1, token); + } + args[i] = value; + } + + try { + result = String.format(getExpression(), args); + } catch (Exception eee) { + if (log.isErrorEnabled()) { + log.error("Could not format " + getExpression() + "" + + " with args : " + Arrays.toString(args), eee); + } + result = ""; + } + + if (useCache) { + cache.put(bean1, result); + } + } + } + + return result; + } + + protected Object getValue(O bean, String token) { + Method method = tokenMethods.get(token); + Preconditions.checkNotNull(method, + "Could not find method for token " + token); + Object result; + try { + result = method.invoke(bean); + } catch (Exception e) { + if (log.isErrorEnabled()) { + log.error("Could not obtain token [" + token + "] value", e); + } + result = ""; + } + return result; + } + + protected Object onNullValue(O bean, String token) { + return null; + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + public static class TuttiDecoratorComparator<O> extends JXPathComparator<O> implements Serializable { + + private static final long serialVersionUID = 1L; + + protected String expression; + + public TuttiDecoratorComparator(String expression) { + super(expression); + this.expression = expression; + } + + @Override + public void init(JXPathDecorator<O> decorator, List<O> datas) { + clear(); + TuttiDecorator<O> tuttDecorator = (TuttiDecorator<O>) decorator; + for (O data : datas) { + Comparable key = (Comparable) tuttDecorator.getValue(data, expression); + valueCache.put(data, key); + } + } + } +} Property changes on: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/TuttiDecorator.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native
participants (1)
-
tchemit@users.forge.codelutin.com