From: Matt B. <gud...@ya...> - 2008-01-07 16:33:02
|
--- Matt Sgarlata <mat...@sp...> wrote: > I have been thinking more about this approach, and > it's really starting to > grow on me. I do have one concern though, can this > approach be extended to > Copiers? For example, a Map -> Object copy could > probably be considered an > imprecise transformation because the Map may have > more keys than the Object > has properties. > > In addition to your approach, I also like the idea > of cleaning up the > internal implementation in Morph so that ordering of > source and destination > classes is preserved for the following reasons: > 1) for at least some portion of users, setting the > order of source and > destination classes will make sense as an indication > of the transformer's > preferences for performing transformations (so for > this class of users, > creating new transformers that play nicely with the > ChainedTransformerTestCase will be simpler) > 2) I think a general change from using HashSets to > ordered sets in Morph's > implementation will mean transformations happen more > consistently across > JVMs and across time on the same JVM, leading to a > more stable platform > > So, what I did is I basically went through the Morph > codebase and replaced > HashSets with ordered sets (preference order is: JDK > 1.4 LinkedHashSet, > Commons-collections ListOrderedSet, copy of > ListOrderedSet in > net.sf.morph.util). I was never able to modify the > ChainedTransformerTestCase so that it consistently > threw an error. However, > after working on the test case long enough, > eventually something changed in > my environment so that the test started to fail. I > did my change of > HashSets to ordered sets, and that was able to fix > the broken test. I seem to be missing a ClassUtils.isCommonsCollectionsPresent() method after syncing. I'll create my own for now, but it does seem to be missing. Thanks! -Matt B > > I checked in my changes for you to take a look at... > > Matt S > > On Jan 6, 2008 12:59 PM, Matt Benson > <gud...@ya...> wrote: > > > Here's what I've got. > > > > -Matt B > > > > > > > > > ____________________________________________________________________________________ > > Be a better friend, newshound, and > > know-it-all with Yahoo! Mobile. Try it now. > > > http://mobile.yahoo.com/;_ylt=Ahu06i62sR8HDtDypao8Wcj9tAcJ > > > > Index: > > > src/core/net/sf/morph/transform/transformers/SimpleDelegatingTransformer.java > > > =================================================================== > > --- > > > src/core/net/sf/morph/transform/transformers/SimpleDelegatingTransformer.java > > (revision 357) > > +++ > > > src/core/net/sf/morph/transform/transformers/SimpleDelegatingTransformer.java > > (working copy) > > @@ -1,5 +1,5 @@ > > /* > > - * Copyright 2004-2005, 2007 the original author > or authors. > > + * Copyright 2004-2005, 2007-2008 the original > author or authors. > > * > > * Licensed under the Apache License, Version 2.0 > (the "License"); you may > > not > > * use this file except in compliance with the > License. You may obtain a > > copy of > > @@ -35,6 +35,7 @@ > > import net.sf.morph.transform.DecoratedConverter; > > import net.sf.morph.transform.DecoratedCopier; > > import > net.sf.morph.transform.ExplicitTransformer; > > +import net.sf.morph.transform.ImpreciseConverter; > > import net.sf.morph.transform.NodeCopier; > > import > net.sf.morph.transform.TransformationException; > > import net.sf.morph.transform.Transformer; > > @@ -93,11 +94,11 @@ > > * @since Dec 12, 2004 > > */ > > public class SimpleDelegatingTransformer extends > BaseCompositeTransformer > > implements > > - SpecializableComposite, > ExplicitTransformer, Transformer, > > DecoratedCopier, DecoratedConverter, Cloneable { > > + SpecializableComposite, > ExplicitTransformer, Transformer, > > DecoratedCopier, > > + DecoratedConverter, Cloneable, > ImpreciseConverter { > > > > //TODO extract BaseDelegatingTransformer > with pluggable delegate > > selection > > > > - > > private static class MapThreadLocal extends > ThreadLocal { > > protected Object initialValue() { > > return new HashMap(); > > @@ -138,6 +139,7 @@ > > } > > > > private Specializer specializer; > > + private boolean preferPreciseTransformers; > > > > private transient ThreadLocal > > visitedSourceToDestinationMapThreadLocal = new > MapThreadLocal(); > > private transient ThreadLocal > stackDepthThreadLocal = new > > StackDepthThreadLocal(); > > @@ -225,6 +227,14 @@ > > > > /** > > * {@inheritDoc} > > + */ > > + protected boolean > isImpreciseConversionImpl(Class > > destinationClass, Class sourceClass) { > > + return > TransformerUtils.isImpreciseConversion > > (getTransformer(destinationClass, > > + sourceClass), > destinationClass, > > sourceClass); > > + } > > + > > + /** > > + * {@inheritDoc} > > * @see > > > net.sf.morph.transform.transformers.BaseTransformer#getSourceClassesImpl() > > */ > > protected Class[] getSourceClassesImpl() > throws Exception { > > @@ -477,6 +487,7 @@ > > * if no suitable transformer > could be found > > */ > > private Transformer getTransformer(Class > transformerType, Class > > destinationClass, Class sourceClass) throws > TransformationException { > > + Transformer candidate = null; > > for (int i = 0; i < > components.length; i++) { > > // if the transformer is > the correct type > > Transformer transformer = > (Transformer) > > components[i]; > > @@ -484,6 +495,13 @@ > > // if the > transformer is capable of > > performing the transformation > > if > (TransformerUtils.isTransformable( > > > transformer, > > destinationClass, sourceClass)) { > > + if > (isPreferPreciseTransformers() > > + > && candidate == > > null > > + > && > > > TransformerUtils.isImpreciseConversion(transformer, > > + > > destinationClass, sourceClass)) { > > + > candidate = transformer; > > + > continue; > > + } > > if > (getLog().isTraceEnabled()) { > > > getLog().trace("Using " > > > + > > > ClassUtils.getUnqualifiedClassName(transformerType) > > @@ -496,7 +514,9 @@ > > return > transformer; > > } > > } > > - > > + if (candidate != null) { > > + return candidate; > > + } > > } > > throw new TransformationException( > > "Could not find a > transformer that can transform > > objects of " > > @@ -612,4 +632,20 @@ > > source); > > } > > > > + /** > > + * Get the preferPreciseTransformers. > > + * @return boolean > > + */ > > + public boolean > isPreferPreciseTransformers() { > > + return preferPreciseTransformers; > > + } > > + > > + /** > > + * Set the preferPreciseTransformers. > Default false. > > + * @param preferPreciseTransformers the > boolean to set > > + */ > > + public void > setPreferPreciseTransformers(boolean > > preferPreciseTransformers) { > > + this.preferPreciseTransformers = > > preferPreciseTransformers; > > + } > > + > > } > > \ No newline at end of file > > Index: > src/core/net/sf/morph/transform/transformers/BaseTransformer.java > > > =================================================================== > > --- > src/core/net/sf/morph/transform/transformers/BaseTransformer.java > > (revision 358) > > +++ > src/core/net/sf/morph/transform/transformers/BaseTransformer.java > > (working copy) > > @@ -570,6 +570,35 @@ > > } > > } > > > > + /** > > + * Implementation of isImpreciseConversion > > + * @param destinationClass > > + * @param sourceClass > > + * @return > > + */ > > + protected boolean > isImpreciseConversionImpl(Class > > destinationClass, Class sourceClass) { > > + return destinationClass == null && > sourceClass != null; > > + } > > + > > + /** > > + * Learn whether the specified conversion > yields an imprecise > > result. > > + * @param destinationClass > > + * @param sourceClass > > + * @return boolean > > + */ > > + public final boolean > isImpreciseConversion(Class destinationClass, > > Class sourceClass) { > > + try { > > + return > isImpreciseConversionImpl(destinationClass, > > sourceClass); > > + } catch (Exception e) { > > + if (e instanceof > RuntimeException && > > !isWrappingRuntimeExceptions()) { > > + throw > (RuntimeException) e; > > + } > > + throw new > TransformationException("Could not > > determine if conversion of " > > + + > sourceClass + " to " + > > destinationClass > > + + " > results in a loss of > > precision", e); > > + } > > + } > > + > > // property getters and setters > > > > /** > > Index: > > > src/core/net/sf/morph/transform/transformers/ChainedTransformer.java > > > =================================================================== > > --- > src/core/net/sf/morph/transform/transformers/ChainedTransformer.java > > (revision 357) > > +++ > src/core/net/sf/morph/transform/transformers/ChainedTransformer.java > > (working copy) > > @@ -1,5 +1,5 @@ > > /* > > - * Copyright 2004-2005, 2007 the original author > or authors. > > + * Copyright 2004-2005, 2007-2008 the original > author or authors. > > * > > * Licensed under the Apache License, Version 2.0 > (the "License"); you may > > not > > * use this file except in compliance with the > License. You may obtain a > > copy of > > @@ -16,6 +16,7 @@ > > package net.sf.morph.transform.transformers; > > > > import java.util.ArrayList; > > +import java.util.Iterator; > > import java.util.List; > > import java.util.Locale; > > > > @@ -25,6 +26,7 @@ > > import net.sf.morph.transform.DecoratedConverter; > > import net.sf.morph.transform.DecoratedCopier; > > import > net.sf.morph.transform.ExplicitTransformer; > > +import net.sf.morph.transform.ImpreciseConverter; > > import > net.sf.morph.transform.TransformationException; > > import net.sf.morph.transform.Transformer; > > import > net.sf.morph.transform.copiers.CopierDecorator; > > @@ -40,7 +42,7 @@ > > * @since Nov 24, 2004 > > */ > > public class ChainedTransformer extends > BaseCompositeTransformer > > implements > > - DecoratedConverter, > DecoratedCopier, ExplicitTransformer { > > + DecoratedConverter, > DecoratedCopier, ExplicitTransformer, > > ImpreciseConverter { > > > > private Converter copyConverter; > > > > @@ -67,6 +69,14 @@ > > } > > > > /** > > + * {@inheritDoc} > > + */ > > + protected boolean > isImpreciseConversionImpl(Class > > destinationClass, Class sourceClass) { > > + List conversionPath = > getConversionPath(destinationClass, > > sourceClass); > > + return !isPrecise(conversionPath, > sourceClass, 0); > > + } > > + > > + /** > > * Get the converter used when using a > ChainedTransformer as a > > Copier. > > * @return > > */ > > @@ -113,6 +123,7 @@ > > throw new > TransformationException(destinationClass, > > sourceType, null, > > "Chained > conversion path could not > > be determined"); > > } > > + log.debug("Using chained > conversion path " + > > conversionPath); > > Object o = source; > > for (int i = 0; i < > conversionPath.size(); i++) { > > o = > getConverter(chain[i]).convert((Class) > > conversionPath.get(i), o, locale); > > @@ -144,6 +155,7 @@ > > throw new > TransformationException(destinationClass, > > source, null, > > "Chained > conversion path could not > > be determined"); > > } > > + log.debug("Using chained > conversion path " + > > conversionPath); > > Object last = > getCopyConverter().convert((Class) > > conversionPath.get(chain.length - 2), source, > locale); > > ((Copier) copier).copy(destination, > last, locale); > > } > > @@ -192,13 +204,7 @@ > > * @return List > > */ > > protected List getConversionPath(Class > destinationType, Class > > sourceType) { > > - if (sourceType != null) { > > - List withoutNull = > > getConversionPath(destinationType, sourceType, 0, > false); > > - if (withoutNull != null) { > > - return > withoutNull; > > - } > > - } > > - return > getConversionPath(destinationType, sourceType, 0, > > true); > > + return > getConversionPath(destinationType, sourceType, 0); > > } > > > > /** > > @@ -210,7 +216,7 @@ > > * @param allowNull > > * @return List > > */ > > - private List getConversionPath(Class > destinationType, Class > > sourceType, int index, boolean allowNull) { > > + private List getConversionPath(Class > destinationType, Class > > sourceType, int index) { > > Transformer[] chain = getChain(); > > Transformer c = chain[index]; > > if (index + 1 == chain.length) { > > @@ -221,22 +227,38 @@ > > } > > return null; > > } > > + List possibleResult = null; > > Class[] available = > c.getDestinationClasses(); > > for (int i = 0; i < > available.length; i++) { > > - if (available[i] == null > && !allowNull) { > > - continue; > > - } > > if > (TransformerUtils.isTransformable(c, > > available[i], sourceType)) { > > - List tail = > > getConversionPath(destinationType, available[i], > index + 1, allowNull); > > + List tail = > > getConversionPath(destinationType, available[i], > index + 1); > > if (tail != null) { > > tail.add(0, > available[i]); > > - return > tail; > > + if > (isPrecise(tail, sourceType, > > index)) { > > + > return tail; > > + } > > + > possibleResult = tail; > > } > > } > > } > > - return null; > > + return possibleResult; > > } > > > > + private boolean isPrecise(List > conversionPath, Class sourceType, > > int index) { > > + Transformer[] chain = getChain(); > > + Class currentSource = sourceType; > > + int i = 0; > > + for (Iterator iter = > conversionPath.iterator(); > > iter.hasNext(); i++) { > > + Class currentDest = > (Class) iter.next(); > > + if > (TransformerUtils.isImpreciseConversion(chain[index > > + i], currentDest, > > + > currentSource)) { > > + return false; > > + } > > + currentSource = > currentDest; > > + } > > + return true; > > + } > > + > > /** > > * Get the components array narrowed to a > Transformer[]. > > * @return Transformer[] > > Index: > src/core/net/sf/morph/transform/ImpreciseConverter.java > > > =================================================================== > > --- > src/core/net/sf/morph/transform/ImpreciseConverter.java > (revision > > 0) > > +++ > src/core/net/sf/morph/transform/ImpreciseConverter.java > (revision > > 0) > > @@ -0,0 +1,32 @@ > > +/* > > + * Copyright 2008 the original author or authors. > > + * > > + * Licensed under the Apache License, Version 2.0 > (the "License"); you > > may not > > + * use this file except in compliance with the > License. You may obtain a > > copy of > > + * the License at > > + * > > + * http://www.apache.org/licenses/LICENSE-2.0 > > + * > > + * Unless required by applicable law or agreed to > in writing, software > > + * distributed under the License is distributed > on an "AS IS" BASIS, > > WITHOUT > > + * WARRANTIES OR CONDITIONS OF ANY KIND, either > express or implied. See > > the > > + * License for the specific language governing > permissions and > > limitations under > > + * the License. > > + */ > > +package net.sf.morph.transform; > > + > > +/** > > + * Defines a converter whose operation may result > in a loss of data > > precision. > > + * > > + * @author mbenson > > + * @since Morph 1.0.2 > > + */ > > +public interface ImpreciseConverter extends > Converter { > > + /** > > + * Learn whether the specified conversion > might yield an imprecise > > result. > > + * @param destinationClass > > + * @param sourceClass > > + * @return boolean > > + */ > > + boolean isImpreciseConversion(Class > destinationClass, Class > > sourceClass); > > +} > > > > Property changes on: > > > src/core/net/sf/morph/transform/ImpreciseConverter.java > > > ___________________________________________________________________ > > Name: svn:eol-style > > + native > > > > Index: > > > src/core/net/sf/morph/transform/converters/ObjectToTextConverter.java > > > =================================================================== > > --- > src/core/net/sf/morph/transform/converters/ObjectToTextConverter.java > > (revision 362) > > +++ > src/core/net/sf/morph/transform/converters/ObjectToTextConverter.java > > (working copy) > > @@ -20,7 +20,9 @@ > > import net.sf.morph.Defaults; > > import net.sf.morph.transform.Converter; > > import net.sf.morph.transform.DecoratedConverter; > > +import net.sf.morph.transform.ImpreciseConverter; > > import > net.sf.morph.transform.transformers.BaseTransformer; > > +import net.sf.morph.util.TransformerUtils; > > > > /** > > * Converts an object to a textual representation > by calling the object's > > @@ -32,7 +34,7 @@ > > * @author Matt Sgarlata > > * @since Dec 24, 2004 > > */ > > -public class ObjectToTextConverter extends > BaseTransformer implements > > DecoratedConverter { > > +public class ObjectToTextConverter extends > BaseTransformer implements > > DecoratedConverter, ImpreciseConverter { > > > > private Converter textConverter; > > > > @@ -52,6 +54,13 @@ > > /** > > * {@inheritDoc} > > */ > > + protected boolean > isImpreciseConversionImpl(Class > > destinationClass, Class sourceClass) { > > + return > TransformerUtils.isImpreciseConversion(getTextConverter(), > > destinationClass, String.class); > > + } > > + > > + /** > > + * {@inheritDoc} > > + */ > > protected boolean > isWrappingRuntimeExceptions() { > > return true; > > } > > Index: > > > src/core/net/sf/morph/transform/converters/TextToNumberConverter.java > > > =================================================================== > > --- > src/core/net/sf/morph/transform/converters/TextToNumberConverter.java > > (revision 361) > > +++ > src/core/net/sf/morph/transform/converters/TextToNumberConverter.java > > (working copy) > > @@ -32,7 +32,7 @@ > > import org.apache.commons.logging.LogFactory; > > > > /** > > - * Converts basic text types into primtive > numbers or {@link > > java.lang.Number} > > + * Converts basic text types into primitive > numbers or {@link > > java.lang.Number} > > * objects. > > * > > * @author Matt Sgarlata > > Index: > > > src/core/net/sf/morph/transform/converters/NumberToTextConverter.java > > > =================================================================== > > --- > src/core/net/sf/morph/transform/converters/NumberToTextConverter.java > > (revision 363) > > +++ > src/core/net/sf/morph/transform/converters/NumberToTextConverter.java > > (working copy) > > @@ -21,7 +21,9 @@ > > import net.sf.morph.Defaults; > > import net.sf.morph.transform.Converter; > > import net.sf.morph.transform.DecoratedConverter; > > +import net.sf.morph.transform.ImpreciseConverter; > > import > net.sf.morph.transform.transformers.BaseTransformer; > > +import net.sf.morph.util.TransformerUtils; > > > > /** > > * Converts {@link java.lang.Number}s into basic > text types ({@link > > java.lang.String}, > > @@ -30,7 +32,8 @@ > > * @author Matt Sgarlata > > * @since Jan 26, 2006 > > */ > > -public class NumberToTextConverter extends > BaseTransformer implements > > DecoratedConverter { > > +public class NumberToTextConverter extends > BaseTransformer implements > > DecoratedConverter, > > + ImpreciseConverter { > > > > private Converter textConverter; > > private Converter numberConverter; > > @@ -58,6 +61,13 @@ > > } > > > > /** > > + * {@inheritDoc} > > + */ > > + protected boolean > isImpreciseConversionImpl(Class > > destinationClass, Class sourceClass) { > > + return > TransformerUtils.isImpreciseConversion(getTextConverter(), > > destinationClass, String.class); > > + } > > + > > + /** > > * Get the number converter used by this > NumberToTextConverter. > > * @return Converter > > */ > > Index: > src/core/net/sf/morph/transform/converters/TimeToTextConverter.java > > > =================================================================== > > --- > src/core/net/sf/morph/transform/converters/TimeToTextConverter.java > > (revision 360) > > +++ > src/core/net/sf/morph/transform/converters/TimeToTextConverter.java > > (working copy) > > @@ -22,7 +22,9 @@ > > import net.sf.morph.Defaults; > > import net.sf.morph.transform.Converter; > > import net.sf.morph.transform.DecoratedConverter; > > +import net.sf.morph.transform.ImpreciseConverter; > > import > net.sf.morph.transform.transformers.BaseTransformer; > > +import net.sf.morph.util.TransformerUtils; > > > > /** > > * Converts the basic time types ({@link > java.util.Date} and > > @@ -33,7 +35,8 @@ > > * @author Matt Sgarlata > > * @since Dec 31, 2004 > > */ > > -public class TimeToTextConverter extends > BaseTransformer implements > > DecoratedConverter { > > +public class TimeToTextConverter extends > BaseTransformer implements > > DecoratedConverter, > > + ImpreciseConverter { > > > > private DateFormat dateFormat; > > private Converter timeConverter; > > @@ -55,6 +58,13 @@ > > /** > > * {@inheritDoc} > > */ > > + protected boolean > isImpreciseConversionImpl(Class > > destinationClass, Class sourceClass) { > > + return > TransformerUtils.isImpreciseConversion(getTextConverter(), > > destinationClass, String.class); > > + } > > + > > + /** > > + * {@inheritDoc} > > + */ > > protected boolean > isWrappingRuntimeExceptions() { > > return true; > > } > > Index: > src/core/net/sf/morph/transform/converters/TextConverter.java > > > =================================================================== > > --- > src/core/net/sf/morph/transform/converters/TextConverter.java > > (revision 357) > > +++ > src/core/net/sf/morph/transform/converters/TextConverter.java > > (working copy) > > @@ -22,6 +22,7 @@ > > > > import net.sf.morph.transform.DecoratedConverter; > > import > net.sf.morph.transform.ExplicitTransformer; > > +import net.sf.morph.transform.ImpreciseConverter; > > import > net.sf.morph.transform.TransformationException; > > import > net.sf.morph.transform.transformers.BaseTransformer; > > import net.sf.morph.util.ClassUtils; > > @@ -43,7 +44,7 @@ > > * @since Jan 2, 2005 > > */ > > public class TextConverter extends > BaseTransformer implements > > DecoratedConverter, > > - ExplicitTransformer { > > + ExplicitTransformer, > ImpreciseConverter { > > > > private static final Class CHAR_SEQUENCE = > > ClassUtils.isJdk14OrHigherPresent() ? ClassUtils > > > .convertToClass("java.lang.CharSequence") > > @@ -62,14 +63,7 @@ > > s.add(Character.class); > > s.add(char.class); > > s.add(null); > > - if (CHAR_SEQUENCE != null) { > > - s.add(CHAR_SEQUENCE); > > - try { > > - > CONSTRUCTOR_CACHE.put(CHAR_SEQUENCE, > > StringBuffer.class.getConstructor(new Class[] { > String.class })); > > - } catch (Exception e) { > > - //nope > > - } > > - } > > + s.add(CHAR_SEQUENCE); > > SOURCE_AND_DESTINATION_TYPES = > (Class[]) s.toArray(new > > Class[s.size()]); > > } > > > > @@ -106,7 +100,8 @@ > > } > > return new > Character(string.charAt(0)); > > } > > - if (destinationClass == > String.class) { > > + if (destinationClass == > String.class > > + || > (destinationClass == CHAR_SEQUENCE && > > CHAR_SEQUENCE != null)) { > > return string; > > } > > if (destinationClass == > byte[].class) { > > @@ -152,6 +147,16 @@ > > /** > > * {@inheritDoc} > > */ > > + protected boolean > isImpreciseConversionImpl(Class > > destinationClass, Class sourceClass) { > > + if > (super.isImpreciseConversionImpl(destinationClass, > > sourceClass)) { > > + return true; > > + } > > + return isChar(destinationClass) && > !isChar(sourceClass); > > + } > > + > > + /** > > + * {@inheritDoc} > > + */ > > protected boolean > isAutomaticallyHandlingNulls() { > > return !isEmptyNull(); > > } > > Index: > > > src/core/net/sf/morph/transform/converters/BooleanToTextConverter.java > > > =================================================================== > > --- > src/core/net/sf/morph/transform/converters/BooleanToTextConverter.java > > (revision 362) > > +++ > src/core/net/sf/morph/transform/converters/BooleanToTextConverter.java > > (working copy) > > @@ -20,8 +20,10 @@ > > import net.sf.morph.Defaults; > > import net.sf.morph.transform.Converter; > > import net.sf.morph.transform.DecoratedConverter; > > +import net.sf.morph.transform.ImpreciseConverter; > > import > net.sf.morph.transform.TransformationException; > > import > net.sf.morph.transform.transformers.BaseTransformer; > > +import net.sf.morph.util.TransformerUtils; > > > > /** > > * Converts boolean values to text values. > Subclasses can build in > > support for > > @@ -32,10 +34,10 @@ > > * @author Matt Sgarlata > > * @since Jan 9, 2005 > > */ > > -public class BooleanToTextConverter extends > BaseTransformer implements > > DecoratedConverter { > > - > > +public class BooleanToTextConverter extends > BaseTransformer implements > > DecoratedConverter, ImpreciseConverter { > > + > > private static final Class[] SOURCE_TYPES = > { Boolean.class, > > boolean.class }; > > - > > + > > private Converter textConverter; > > > > /** > > @@ -93,9 +95,16 @@ > > /** > > * {@inheritDoc} > > */ > > + protected boolean > isImpreciseConversionImpl(Class > > destinationClass, Class sourceClass) { > > + return > TransformerUtils.isImpreciseConversion(getTextConverter(), > > destinationClass, String.class); > > + } > > + > > + /** > > + * {@inheritDoc} > > + */ > > protected boolean > isWrappingRuntimeExceptions() { > > return true; > > - } > > + } > > > > /** > > * Get the text converter used by this > BaseToPrettyTextConverter. > > Index: > src/core/net/sf/morph/transform/converters/NumberConverter.java > > > =================================================================== > > --- > src/core/net/sf/morph/transform/converters/NumberConverter.java > > (revision 363) > > +++ > src/core/net/sf/morph/transform/converters/NumberConverter.java > > (working copy) > > @@ -19,6 +19,7 @@ > > import java.util.Locale; > > > > import net.sf.morph.transform.DecoratedConverter; > > +import net.sf.morph.transform.ImpreciseConverter; > > import > net.sf.morph.transform.TransformationException; > > import > net.sf.morph.transform.support.NumberRounder; > > import > net.sf.morph.transform.transformers.BaseTransformer; > > @@ -31,8 +32,8 @@ > > * @author Matt Sgarlata > > * @since Dec 14, 2004 > > */ > > -public class NumberConverter extends > BaseTransformer implements > > DecoratedConverter { > > - > > +public class NumberConverter extends > BaseTransformer implements > > DecoratedConverter, ImpreciseConverter { > > + > > private static final Class[] > SOURCE_AND_DESTINATION_TYPES = { > > Number.class, byte.class, > short.class, int.class, > > long.class, > > float.class, double.class, null > > @@ -116,9 +117,20 @@ > > /** > > * {@inheritDoc} > > */ > > + protected boolean > isImpreciseConversionImpl(Class > > destinationClass, Class sourceClass) { > > + return > super.isImpreciseConversionImpl(destinationClass, > > sourceClass) > > + || > > > NumberUtils.NARROWNESS_COMPARATOR.compare(destinationClass, > > + > sourceClass) < 0; > > + } > > + > > + /** > > + * {@inheritDoc} > > + */ > > protected Object convertImpl(Class > destinationClass, Object source, > > Locale locale) throws Exception { > > - > > + if (destinationClass == null) { > > + return null; > > + } > > if (destinationClass.isPrimitive() > && source == null) { > > throw new > TransformationException(destinationClass, > > source); > > } > > Index: > > > src/core/net/sf/morph/transform/converters/BaseToPrettyTextConverter.java > > > =================================================================== > > --- > > > src/core/net/sf/morph/transform/converters/BaseToPrettyTextConverter.java > > (revision 362) > > +++ > > > src/core/net/sf/morph/transform/converters/BaseToPrettyTextConverter.java > > (working copy) > > @@ -18,7 +18,9 @@ > > import net.sf.morph.Defaults; > > import net.sf.morph.transform.Converter; > > import net.sf.morph.transform.DecoratedConverter; > > +import net.sf.morph.transform.ImpreciseConverter; > > import > net.sf.morph.transform.transformers.BaseReflectorTransformer; > > +import net.sf.morph.util.TransformerUtils; > > > > /** > > * Base class for converts that convert objects to > a pretty > > programmer-friendly > > @@ -27,7 +29,8 @@ > > * @author Matt Sgarlata > > * @since Feb 15, 2005 > > */ > > -public abstract class BaseToPrettyTextConverter > extends > > BaseReflectorTransformer implements > DecoratedConverter { > > +public abstract class BaseToPrettyTextConverter > extends > > BaseReflectorTransformer > > + implements DecoratedConverter, > ImpreciseConverter { > > > > private String prefix; > > private String suffix; > > @@ -161,4 +164,19 @@ > > public void setShowNullValues(boolean > showNullValues) { > > this.showNullValues = > showNullValues; > > } > > + > > + /** > > + * {@inheritDoc} > > + */ > > + protected boolean > isImpreciseConversionImpl(Class > > destinationClass, Class sourceClass) { > > + return > TransformerUtils.isImpreciseConversion(getTextConverter(), > > destinationClass, sourceClass); > > + } > > + > > + /** > > + * Get the intermediate class passed to > the text converter. > > + * @return > > + */ > > + protected Class getIntermediateClass() { > > + return StringBuffer.class; > > + } > > } > > Index: src/core/net/sf/morph/util/NumberUtils.java > > > =================================================================== > > --- src/core/net/sf/morph/util/NumberUtils.java > (revision 365) > > +++ src/core/net/sf/morph/util/NumberUtils.java > (working copy) > > @@ -19,6 +19,7 @@ > > import java.lang.reflect.Method; > > import java.math.BigDecimal; > > import java.math.BigInteger; > > +import java.util.Comparator; > > import java.util.HashMap; > > import java.util.HashSet; > > import java.util.Iterator; > > @@ -69,6 +70,31 @@ > > } > > } > > > > + private static class NarrownessComparator > implements Comparator { > > + /** > > + * {@inheritDoc} > > + */ > > + public int compare(Object arg0, > Object arg1) { > > + if (arg0 == arg1) { > > + return 0; > > + } > > + Class c0 = getType(arg0); > > + Class c1 = getType(arg1); > > + if (c0 == c1 || c0 == null > || c1 == null) { > > + return 0; > > + } > > + return > > > getMaximumForType(c0).compareTo(getMaximumForType(c1)); > > + } > > + > > + private Class getType(Object o) { > > + if > (MAXIMUMS_FOR_TYPES.containsKey(o)) { > > + return (Class) o; > > + } > > + Class test = > ClassUtils.getClass(o); > > + return > MAXIMUMS_FOR_TYPES.containsKey(test) ? test > > : null; > > + } > > + } > > + > > /** > > * A Map of BigDecimals keyed by Class that > indicate the maximum > > value that > > * the given (Number) Class may taken on. > > @@ -80,11 +106,16 @@ > > * the given (Number) Class may taken on. > > */ > > public static final Map MINIMUMS_FOR_TYPES; > > - > > - public static final Map > WRAPPERS_FOR_PRIMITIVE_TYPES; > > > > - public static final Map NUMBER_FACTORIES; > > + /** > > + * Comparator of class/object type > narrowness. > > + */ > > + public static final Comparator > NARROWNESS_COMPARATOR = new > > NarrownessComparator(); > > > > + private static final Map > WRAPPERS_FOR_PRIMITIVE_TYPES; > > + > > + private static final Map NUMBER_FACTORIES; > > + > > /** > > * Used by {@link > NumberUtils#isNumber(Class)}. > > */ > > Index: > src/core/net/sf/morph/util/TransformerUtils.java > > > =================================================================== > > --- > src/core/net/sf/morph/util/TransformerUtils.java > (revision 357) > > +++ > src/core/net/sf/morph/util/TransformerUtils.java > (working copy) > > @@ -1,5 +1,5 @@ > > /* > > - * Copyright 2004-2005, 2007 the original author > or authors. > > + * Copyright 2004-2005, 2007-2008 the original > author or authors. > > * > > * Licensed under the Apache License, Version 2.0 > (the "License"); you may > > not > > * use this file except in compliance with the > License. You may obtain a > > copy of > > @@ -26,6 +26,7 @@ > > import net.sf.morph.transform.Converter; > > import net.sf.morph.transform.Copier; > > import > net.sf.morph.transform.ExplicitTransformer; > > +import net.sf.morph.transform.ImpreciseConverter; > > import > net.sf.morph.transform.TransformationException; > > import net.sf.morph.transform.Transformer; > > > > @@ -90,6 +91,24 @@ > > } > > > > /** > > + * Learn whether > <code>transformer</code>'s conversion > > + * of <code>sourceClass</code> to > <code>destinationClass</code> > > might yield an imprecise result. > > + * @param transformer > > + * @param destinationClass > > + * @param sourceClass > > + * @return boolean > > + * @see ImpreciseConverter > > + */ > > + public static boolean > isImpreciseConversion(Transformer > > transformer, > > + Class destinationClass, > Class sourceClass) { > > + if (transformer instanceof > ImpreciseConverter) { > > + return > ((ImpreciseConverter) > > transformer).isImpreciseConversion( > > + > destinationClass, sourceClass); > > + } > > + return destinationClass == null && > sourceClass != null; > > + } > > + > > + /** > > * Performs a transformation of one object > graph into another > > object graph. > > * > > * @param destinationType > > > > > ------------------------------------------------------------------------- > > This SF.net email is sponsored by: Microsoft > > Defy all challenges. Microsoft(R) Visual Studio > 2005. > > > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > > _______________________________________________ > > morph-developer mailing list > > mor...@li... > > > https://lists.sourceforge.net/lists/listinfo/morph-developer > > > > > > > -- > This message is intended only for the named > recipient. If you are not the > intended recipient, you are notified that > disclosing, copying, distributing, > or taking any action in reliance on the contents of > this information is > strictly prohibited. > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio > 2005. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/> _______________________________________________ > morph-developer mailing list > mor...@li... > https://lists.sourceforge.net/lists/listinfo/morph-developer > ____________________________________________________________________________________ Never miss a thing. Make Yahoo your home page. http://www.yahoo.com/r/hs |