/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
// www.projectforge.org
//
// Copyright (C) 2001-2014 Kai Reinhard (k.reinhard@micromata.de)
//
// ProjectForge is dual-licensed.
//
// This community edition 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; version 3 of the License.
//
// This community edition 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/.
//
/////////////////////////////////////////////////////////////////////////////
package org.projectforge.xml.stream;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import org.projectforge.Version;
import org.projectforge.xml.stream.converter.BigDecimalConverter;
import org.projectforge.xml.stream.converter.BooleanConverter;
import org.projectforge.xml.stream.converter.ByteArrayConverter;
import org.projectforge.xml.stream.converter.ClassConverter;
import org.projectforge.xml.stream.converter.DateConverter;
import org.projectforge.xml.stream.converter.DoubleConverter;
import org.projectforge.xml.stream.converter.IConverter;
import org.projectforge.xml.stream.converter.IntConverter;
import org.projectforge.xml.stream.converter.LocaleConverter;
import org.projectforge.xml.stream.converter.LongConverter;
import org.projectforge.xml.stream.converter.ShortConverter;
import org.projectforge.xml.stream.converter.StringConverter;
import org.projectforge.xml.stream.converter.TimeZoneConverter;
import org.projectforge.xml.stream.converter.VersionConverter;
/**
* There is one singleton instance used for default mappings, aliases etc.
* @author Kai Reinhard (k.reinhard@micromata.de)
*
*/
public class XmlRegistry
{
private static final XmlRegistry baseRegistry;
private Map<Class< ? >, IConverter< ? >> converterRegistry;
// private Map<Field, IConverter< ? >> fieldConverterRegistry;
private Set<Class< ? >> asAttributeAsDefaultSet;
private AliasMap aliasMap;
static {
baseRegistry = new XmlRegistry();
baseRegistry.initializeDefaultRegistry();
}
/**
* Default xml registry.
*/
public static XmlRegistry baseRegistry()
{
return baseRegistry;
}
/**
* For customized xml registry.
*/
public XmlRegistry()
{
}
/**
* Only for the singleton instance.
*/
private void initializeDefaultRegistry()
{
internalRegisterTypeAsAttribute(BigDecimal.class);
internalRegisterTypeAsAttribute(Boolean.class);
internalRegisterTypeAsAttribute(boolean.class);
internalRegisterTypeAsAttribute(Date.class);
internalRegisterTypeAsAttribute(Double.class);
internalRegisterTypeAsAttribute(double.class);
internalRegisterTypeAsAttribute(Integer.class);
internalRegisterTypeAsAttribute(int.class);
internalRegisterTypeAsAttribute(Long.class);
internalRegisterTypeAsAttribute(long.class);
internalRegisterTypeAsAttribute(Short.class);
internalRegisterTypeAsAttribute(short.class);
internalRegisterTypeAsAttribute(TimeZone.class);
internalRegisterTypeAsAttribute(Locale.class);
internalRegisterTypeAsAttribute(Version.class);
internalRegisterAlias(BigDecimal.class, "decimal");
internalRegisterAlias(Boolean.class, "boolean");
internalRegisterAlias(boolean.class, "boolean");
internalRegisterAlias(Double.class, "double");
internalRegisterAlias(double.class, "double");
internalRegisterAlias(Integer.class, "int");
internalRegisterAlias(int.class, "int");
internalRegisterAlias(Long.class, "long");
internalRegisterAlias(long.class, "long");
internalRegisterAlias(Short.class, "short");
internalRegisterAlias(short.class, "short");
internalRegisterAlias(TimeZone.class, "timeZone");
internalRegisterAlias(Locale.class, "locale");
internalRegisterAlias(Version.class, "version");
IConverter< ? > conv = new BooleanConverter();
internalRegisterConverter(Boolean.class, conv);
internalRegisterConverter(boolean.class, conv);
conv = new DoubleConverter();
internalRegisterConverter(Double.class, conv);
internalRegisterConverter(double.class, conv);
conv = new IntConverter();
internalRegisterConverter(Integer.class, conv);
internalRegisterConverter(int.class, conv);
conv = new LongConverter();
internalRegisterConverter(Long.class, conv);
internalRegisterConverter(long.class, conv);
conv = new ShortConverter();
internalRegisterConverter(Short.class, conv);
internalRegisterConverter(short.class, conv);
internalRegisterConverter(byte[].class, new ByteArrayConverter());
internalRegisterConverter(BigDecimal.class, new BigDecimalConverter());
internalRegisterConverter(Class.class, new ClassConverter());
internalRegisterConverter(Date.class, new DateConverter());
internalRegisterConverter(String.class, new StringConverter());
internalRegisterConverter(TimeZone.class, new TimeZoneConverter());
internalRegisterConverter(Locale.class, new LocaleConverter());
internalRegisterConverter(Version.class, new VersionConverter());
}
public IConverter< ? > getConverter(final Class< ? > clazz)
{
if (converterRegistry != null) {
final IConverter< ? > converter = converterRegistry.get(clazz);
if (converter != null) {
return converter;
}
for (final Class< ? > cls : converterRegistry.keySet()) {
if (cls.isAssignableFrom(clazz) == true) {
final IConverter< ? > conv = converterRegistry.get(cls);
if (conv != null) {
// Register so every type must only be checked once.
internalRegisterConverter(clazz, conv);
return conv;
}
}
}
}
if (this == baseRegistry) {
return null;
}
return baseRegistry.getConverter(clazz);
}
public boolean asAttributeAsDefault(final Class< ? > type)
{
if (asAttributeAsDefaultSet != null) {
if (asAttributeAsDefaultSet.contains(type) == true) {
return true;
}
}
if (this == baseRegistry) {
return false;
}
return baseRegistry.asAttributeAsDefault(type);
}
public String getAliasForClass(final Class< ? > type)
{
if (aliasMap != null) {
final String alias = aliasMap.getAliasForClass(type);
if (alias != null) {
return alias;
}
}
if (this == baseRegistry) {
return null;
}
return baseRegistry.getAliasForClass(type);
}
public Class< ? > getClassForAlias(final String alias)
{
if (aliasMap != null) {
final Class< ? > clazz = aliasMap.getClassForAlias(alias);
if (clazz != null) {
return clazz;
}
}
if (this == baseRegistry) {
return null;
}
return baseRegistry.getClassForAlias(alias);
}
public XmlRegistry registerConverter(final Class< ? > type, final IConverter< ? > converter)
{
if (this == baseRegistry) {
throw new IllegalStateException("Couldn't register type as attribute for base registry (singleton). This registry is unmodifiable");
}
internalRegisterConverter(type, converter);
return this;
}
private void internalRegisterConverter(final Class< ? > type, final IConverter< ? > converter)
{
if (this.converterRegistry == null) {
this.converterRegistry = new HashMap<Class< ? >, IConverter< ? >>();
}
this.converterRegistry.put(type, converter);
}
public XmlRegistry registerAlias(final Class< ? > type, final String alias)
{
if (this == baseRegistry) {
throw new IllegalStateException("Couldn't register type as attribute for base registry (singleton). This registry is unmodifiable");
}
internalRegisterAlias(type, alias);
return this;
}
private void internalRegisterAlias(final Class< ? > type, final String alias)
{
if (this.aliasMap == null) {
this.aliasMap = new AliasMap();
}
this.aliasMap.put(type, alias);
}
public XmlRegistry registerTypeAsAttribute(final Class< ? > type)
{
if (this == baseRegistry) {
throw new IllegalStateException("Couldn't register type as attribute for base registry (singleton). This registry is unmodifiable");
}
internalRegisterTypeAsAttribute(type);
return this;
}
private void internalRegisterTypeAsAttribute(final Class< ? > type)
{
if (this.asAttributeAsDefaultSet == null) {
this.asAttributeAsDefaultSet = new HashSet<Class< ? >>();
}
this.asAttributeAsDefaultSet.add(type);
}
}