/* * Copyright (c) 2002-2015, JIDE Software Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ package jidefx.utils.converter; import javafx.geometry.BoundingBox; import javafx.geometry.Dimension2D; import javafx.geometry.Insets; import javafx.geometry.Point2D; import javafx.geometry.Point3D; import javafx.geometry.Rectangle2D; import javafx.scene.Node; import javafx.scene.paint.Color; import javafx.scene.text.Font; import jidefx.utils.converter.javafx.BoundingBoxConverter; import jidefx.utils.converter.javafx.ColorConverter; import jidefx.utils.converter.javafx.Dimension2DConverter; import jidefx.utils.converter.javafx.FontConverter; import jidefx.utils.converter.javafx.HexColorConverter; import jidefx.utils.converter.javafx.InsetsConverter; import jidefx.utils.converter.javafx.Point2DConverter; import jidefx.utils.converter.javafx.Point3DConverter; import jidefx.utils.converter.javafx.Rectangle2DConverter; import jidefx.utils.converter.javafx.RgbColorConverter; import jidefx.utils.converter.javafx.WebColorConverter; import jidefx.utils.converter.time.LocalDateConverter; import jidefx.utils.converter.time.LocalDateTimeConverter; import jidefx.utils.converter.time.LocalTimeConverter; import java.io.File; import java.math.BigDecimal; import java.text.NumberFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.YearMonth; import java.util.Calendar; import java.util.Date; public class ObjectConverterManager { public static final String PROPERTY_OBJECT_CONVERTER_MANAGER = "ObjectConverterManager"; //NON-NLS /** * Multi Manager Support */ private static final ObjectConverterManager _instance = createInstance(); /** * Creates a new instance of the ObjectConverterManager. * * @return a new instance of the ObjectConverterManager. */ public static ObjectConverterManager createInstance() { return new ObjectConverterManager(); } /** * Gets the default instance of the ObjectConverterManager. * * @return the default instance of the ObjectConverterManager. */ public static ObjectConverterManager getInstance() { return _instance; } /** * Gets the ObjectConverterManager from the node if the node has an ObjectConverterManager defined on the * Properties. If not there, return the default instance. * * @param node the node * @return an ObjectConverterManager. */ public static ObjectConverterManager getInstance(Node node) { if (node != null && node.getProperties().get(PROPERTY_OBJECT_CONVERTER_MANAGER) instanceof ObjectConverterManager) { return (ObjectConverterManager) node.getProperties().get(PROPERTY_OBJECT_CONVERTER_MANAGER); } else { return getInstance(); } } /** * Instance individual */ private boolean _inited = false; private boolean _initing = false; private boolean _autoInit = true; private CacheMap<ObjectConverter, ConverterContext> _cache = new CacheMap<>(ConverterContext.CONTEXT_DEFAULT); private ObjectConverter _defaultConverter = new DefaultObjectConverter(); public void resetInit() { _inited = false; } public void clear() { resetInit(); _cache.clear(); } public void initDefaultConverters() { if (_inited) { return; } _initing = true; try { // Default String Converters registerConverter(String.class, new DefaultObjectConverter()); registerConverter(String.class, new MultilineStringConverter(), MultilineStringConverter.CONTEXT); // Default NUMBER Converters IntegerConverter integerConverter = new IntegerConverter(); registerConverter(int.class, integerConverter); registerConverter(Integer.class, integerConverter); NaturalNumberConverter naturalNumberConverter = new NaturalNumberConverter(); registerConverter(int.class, naturalNumberConverter, NaturalNumberConverter.CONTEXT); registerConverter(Integer.class, naturalNumberConverter, NaturalNumberConverter.CONTEXT); ShortConverter shortConverter = new ShortConverter(); registerConverter(Short.class, shortConverter); registerConverter(short.class, shortConverter); LongConverter longConverter = new LongConverter(); registerConverter(Long.class, longConverter); registerConverter(long.class, longConverter); DoubleConverter doubleConverter = new DoubleConverter(); registerConverter(Double.class, doubleConverter); registerConverter(double.class, doubleConverter); NumberFormat format1DigitInstance = NumberFormat.getNumberInstance(); format1DigitInstance.setMinimumFractionDigits(1); format1DigitInstance.setMaximumFractionDigits(1); DoubleConverter fraction1DigitConverter = new DoubleConverter(format1DigitInstance); registerConverter(Number.class, fraction1DigitConverter, AbstractNumberConverter.CONTEXT_FIXED_1_DIGIT_FRACTION); NumberFormat format2Digit = NumberFormat.getNumberInstance(); format2Digit.setMinimumFractionDigits(2); format2Digit.setMaximumFractionDigits(2); DoubleConverter fraction2DigitConverter = new DoubleConverter(format2Digit); registerConverter(Number.class, fraction2DigitConverter, AbstractNumberConverter.CONTEXT_FIXED_2_DIGIT_FRACTION); NumberFormat format4Digit = NumberFormat.getNumberInstance(); format4Digit.setMinimumFractionDigits(4); format4Digit.setMaximumFractionDigits(4); DoubleConverter fraction4DigitConverter = new DoubleConverter(format4Digit); registerConverter(Number.class, fraction4DigitConverter, AbstractNumberConverter.CONTEXT_FIXED_4_DIGIT_FRACTION); FloatConverter floatConverter = new FloatConverter(); registerConverter(Float.class, floatConverter); registerConverter(float.class, floatConverter); registerConverter(BigDecimal.class, new BigDecimalConverter()); ByteConverter byteConverter = new ByteConverter(); registerConverter(Byte.class, byteConverter); registerConverter(byte.class, byteConverter); BooleanConverter booleanConverter = new BooleanConverter(); registerConverter(Boolean.class, booleanConverter); registerConverter(boolean.class, booleanConverter); registerConverter(File.class, new FileConverter()); QuarterNameConverter quarterNameConverter = new QuarterNameConverter(); registerConverter(int.class, quarterNameConverter, QuarterNameConverter.CONTEXT); registerConverter(Integer.class, quarterNameConverter, QuarterNameConverter.CONTEXT); CurrencyConverter currencyConverter = new CurrencyConverter(); registerConverter(Float.class, currencyConverter, CurrencyConverter.CONTEXT); registerConverter(float.class, currencyConverter, CurrencyConverter.CONTEXT); registerConverter(Double.class, currencyConverter, CurrencyConverter.CONTEXT); registerConverter(double.class, currencyConverter, CurrencyConverter.CONTEXT); PercentConverter percentConverter = new PercentConverter(); registerConverter(Float.class, percentConverter, PercentConverter.CONTEXT); registerConverter(float.class, percentConverter, PercentConverter.CONTEXT); registerConverter(Double.class, percentConverter, PercentConverter.CONTEXT); registerConverter(double.class, percentConverter, PercentConverter.CONTEXT); DateConverter dateConverter = new DateConverter(); registerConverter(Date.class, dateConverter); registerConverter(Date.class, dateConverter, DateConverter.CONTEXT_DATETIME); registerConverter(Date.class, dateConverter, DateConverter.CONTEXT_TIME); CalendarConverter calendarConverter = new CalendarConverter(); registerConverter(Calendar.class, calendarConverter); registerConverter(Calendar.class, calendarConverter, DateConverter.CONTEXT_DATETIME); registerConverter(Calendar.class, calendarConverter, DateConverter.CONTEXT_TIME); registerConverter(Calendar.class, new YearMonthConverter(), YearMonthConverter.CONTEXT_YEAR_MONTH); // For java.time package available on JDK8 registerConverter(LocalDate.class, new LocalDateConverter()); registerConverter(LocalDateTime.class, new LocalDateTimeConverter()); registerConverter(LocalTime.class, new LocalTimeConverter()); registerConverter(YearMonth.class, new YearMonthConverter()); MonthNameConverter monthNameConverter = new MonthNameConverter(); registerConverter(Integer.class, monthNameConverter, MonthNameConverter.CONTEXT); registerConverter(int.class, monthNameConverter, MonthNameConverter.CONTEXT); registerConverter(Color.class, new RgbColorConverter()); registerConverter(Color.class, new HexColorConverter(), ColorConverter.CONTEXT_HEX); registerConverter(Color.class, new RgbColorConverter(true), ColorConverter.CONTEXT_RGBA); registerConverter(Color.class, new HexColorConverter(true), ColorConverter.CONTEXT_HEX_WITH_ALPHA); registerConverter(Color.class, new WebColorConverter(), ColorConverter.CONTEXT_WEB); registerConverter(Point2D.class, new Point2DConverter()); registerConverter(Point3D.class, new Point3DConverter()); registerConverter(Rectangle2D.class, new Rectangle2DConverter()); registerConverter(Dimension2D.class, new Dimension2DConverter()); registerConverter(Insets.class, new InsetsConverter()); registerConverter(BoundingBox.class, new BoundingBoxConverter()); registerConverter(Font.class, new FontConverter()); // enums registerConverter(Enum.class, new EnumConverter()); // Default Array Converters registerConverter(String[].class, new StringArrayConverter()); registerConverter(int[].class, new DefaultValuesConverter<Integer>("; ", int.class)); registerConverter(float[].class, new DefaultValuesConverter<Float>("; ", float.class)); registerConverter(double[].class, new DefaultValuesConverter<Double>("; ", double.class)); registerConverter(long[].class, new DefaultValuesConverter<Long>("; ", long.class)); registerConverter(short[].class, new DefaultValuesConverter<Short>("; ", short.class)); registerConverter(Object[].class, new DefaultValuesConverter<>("; ", Object.class)); registerConverter(String[].class, new DefaultValuesConverter<String>("; ", String.class)); registerConverter(Date[].class, new DefaultValuesConverter<Date>("; ", Date.class)); registerConverter(Calendar[].class, new DefaultValuesConverter<Calendar>("; ", Calendar.class)); registerConverter(Number[].class, new DefaultValuesConverter<Number>("; ", Number.class)); registerConverter(Integer[].class, new DefaultValuesConverter<Integer>("; ", Integer.class)); registerConverter(Float[].class, new DefaultValuesConverter<Float>("; ", Float.class)); registerConverter(Double[].class, new DefaultValuesConverter<Double>("; ", Double.class)); registerConverter(Long[].class, new DefaultValuesConverter<Long>("; ", Long.class)); registerConverter(Short[].class, new DefaultValuesConverter<Short>("; ", Short.class)); } finally { _initing = false; _inited = true; } } public void registerConverter(Class<?> clazz, ObjectConverter converter, ConverterContext context) { if (clazz == null) { throw new IllegalArgumentException("Parameter class cannot be null"); } if (context == null) { context = ConverterContext.CONTEXT_DEFAULT; } if (isAutoInit() && !_inited && !_initing) { initDefaultConverters(); } _cache.register(clazz, converter, context); } public void registerConverter(Class<?> clazz, ObjectConverter converter) { registerConverter(clazz, converter, ConverterContext.CONTEXT_DEFAULT); } public void unregisterConverter(Class<?> clazz, ConverterContext context) { if (context == null) { context = ConverterContext.CONTEXT_DEFAULT; } if (isAutoInit() && !_inited && !_initing) { initDefaultConverters(); } _cache.unregister(clazz, context); } public void unregisterConverter(Class<?> clazz) { unregisterConverter(clazz, ConverterContext.CONTEXT_DEFAULT); } public void unregisterAllConverters(Class<?> clazz) { _cache.remove(clazz); } public void unregisterAllConverters() { _cache.clear(); } public <T> ObjectConverter<T> getConverter(Class<?> clazz) { return getConverter(clazz, ConverterContext.CONTEXT_DEFAULT); } public <T> ObjectConverter<T> getConverter(Class<?> clazz, ConverterContext context) { if (isAutoInit() && !_inited && !_initing) { initDefaultConverters(); } if (context == null) { context = ConverterContext.CONTEXT_DEFAULT; } ObjectConverter converter = _cache.getRegisteredObject(clazz, context); if (converter != null) { if (converter instanceof LazyInitializeConverter) { ((LazyInitializeConverter) converter).initialize(clazz, context); } return converter; } else { if (clazz != null && clazz.isArray()) { DefaultValuesConverter defaultArrayConverter = new DefaultValuesConverter("; ", clazz.getComponentType()); registerConverter(clazz, defaultArrayConverter); return defaultArrayConverter; } return _defaultConverter; } } public String toString(Object object) { if (object != null) { return toString(object, object.getClass(), ConverterContext.CONTEXT_DEFAULT); } else { return ""; } } public String toString(Object object, Class<?> clazz) { return toString(object, clazz, ConverterContext.CONTEXT_DEFAULT); } public String toString(Object object, Class<?> clazz, ConverterContext context) { ObjectConverter converter = getConverter(clazz, context); if (converter != null) { if (converter instanceof RequiringConverterManager) { context.getProperties().put(ConverterContext.PROPERTY_OBJECT_CONVERTER_MANAGER, this); } String s; try { s = converter.toString(object, context); } finally { if (converter instanceof RequiringConverterManager) { context.getProperties().remove(ConverterContext.PROPERTY_OBJECT_CONVERTER_MANAGER); } } return s; } else if (object == null) { return ""; } else { return object.toString(); } } public Object fromString(String string, Class<?> clazz) { return fromString(string, clazz, ConverterContext.CONTEXT_DEFAULT); } public Object fromString(String string, Class<?> clazz, ConverterContext context) { ObjectConverter converter = getConverter(clazz, context); if (converter != null) { Object value; try { if (converter instanceof RequiringConverterManager) { context.getProperties().put(ConverterContext.PROPERTY_OBJECT_CONVERTER_MANAGER, this); } value = converter.fromString(string, context); } finally { if (converter instanceof RequiringConverterManager) { context.getProperties().remove(ConverterContext.PROPERTY_OBJECT_CONVERTER_MANAGER); } } if (value != null && clazz != null && !clazz.isAssignableFrom(value.getClass())) { if (TypeUtils.isNumericType(clazz) && value instanceof Number) { clazz = TypeUtils.convertPrimitiveToWrapperType(clazz); if (clazz == Double.class) { return ((Number) value).doubleValue(); } if (clazz == Byte.class) { return ((Number) value).byteValue(); } if (clazz == Short.class) { return ((Number) value).shortValue(); } if (clazz == Integer.class) { return ((Number) value).intValue(); } if (clazz == Long.class) { return ((Number) value).longValue(); } if (clazz == Float.class) { return ((Number) value).floatValue(); } } } return value; } else { return null; } } public boolean isAutoInit() { return _autoInit; } public void setAutoInit(boolean autoInit) { _autoInit = autoInit; } public ConverterContext[] getConverterContexts(Class<?> clazz) { return _cache.getKeys(clazz, new ConverterContext[0]); } }