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

org.beangle.serializer.text.marshal.DefaultMarshallerRegistry.scala Maven / Gradle / Ivy

The newest version!
/*
 * Beangle, Agile Development Scaffold and Toolkits.
 *
 * Copyright © 2005, The Beangle Software.
 *
 * 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 */
package org.beangle.serializer.text.marshal

import org.beangle.commons.collection.IdentityCache
import org.beangle.commons.lang.reflect.Reflections
import org.beangle.serializer.text.SerializeException
import org.beangle.serializer.text.mapper.Mapper

import scala.collection.mutable
import scala.language.existentials

class DefaultMarshallerRegistry(mapper: Mapper) extends MarshallerRegistry {

  private val cache = new IdentityCache[Class[_], Marshaller[_]]
  /**
    * [Object,List(BeanMarshaller,PrimitiveMarshaller)]
    */
  private val converterMap = new mutable.HashMap[Class[_], Set[Marshaller[_]]]

  registerBuildin()

  override def lookup[T](clazz: Class[T]): Marshaller[T] = {
    var converter = cache.get(clazz)
    if (null == converter) {
      converter = searchMarshaller(clazz)
      if (null == converter) throw new SerializeException("No converter specified for " + clazz, null)
      else cache.put(clazz, converter)
    }
    converter.asInstanceOf[Marshaller[T]]
  }

  override def register[T](converter: Marshaller[T]): Unit = {
    val clazz = Reflections.getGenericParamType(converter.getClass, classOf[Marshaller[_]])("T")
    converterMap.get(clazz) match {
      case Some(converters) =>
        converters.find(_.getClass == converter.getClass) match {
          case Some(c) => converterMap.put(clazz, converters - c + converter)
          case None => converterMap.put(clazz, converters + converter)
        }
      case None => converterMap.put(clazz, Set(converter))
    }
  }

  private def registerBuildin(): Unit = {
    register(new CollectionMarshaller(mapper))
    register(new IterableMarshaller(mapper))
    register(new MapMarshaller(mapper))
    register(new JavaMapMarshaller(mapper))
    register(new JavaMapEntryMarshaller(mapper))
    register(new BeanMarshaller(mapper))
    register(new ArrayMarshaller(mapper))
    register(new TupleMarshaller(mapper))
    register(new PropertiesMarshaller(mapper))
    register(new PageMarshaller(mapper))
    register(new JsonObjectMarshaller(mapper))
    register(new NumberMarshaller)
    register(new BooleanMarshaller)
    register(new DateMarshaller)
    register(new SqlDateMarshaller)
    register(new CalendarMarshaller)
    register(new TimestampMarshaller)
    register(new TimeMarshaller)
    register(new EnumMarshaller)
  }

  private def searchMarshaller(sourceType: Class[_]): Marshaller[_] = {
    val interfaces = new mutable.LinkedHashSet[Class[_]]
    val classQueue = new mutable.Queue[Class[_]]
    classQueue += sourceType
    while (classQueue.nonEmpty) {
      val currentClass = classQueue.dequeue()
      val converter = searchSupport(sourceType, converterMap.get(currentClass))
      if (converter != null) return converter
      val superClass = currentClass.getSuperclass
      if (superClass != null && superClass != classOf[AnyRef]) classQueue += superClass
      for (interfaceType <- currentClass.getInterfaces) addInterfaces(interfaceType, interfaces)
    }
    val iter = interfaces.iterator
    while (iter.hasNext) {
      val interface = iter.next()
      val converter = searchSupport(sourceType, converterMap.get(interface))
      if (converter != null) return converter
    }

    val converter = searchSupport(sourceType, converterMap.get(classOf[AnyRef]))
    if (converter != null) converter
    else {
      if (sourceType.isArray) new ArrayMarshaller(mapper)
      else ObjectMarshaller
    }
  }

  private def searchSupport(clazz: Class[_], converterSet: Option[Set[Marshaller[_]]]): Marshaller[_] = {
    converterSet match {
      case Some(converters) =>
        val iter = converters.iterator
        while (iter.hasNext) {
          val converter = iter.next()
          if (converter.support(clazz)) return converter
        }
        null
      case None => null
    }
  }

  private def addInterfaces(interfaceType: Class[_], interfaces: mutable.Set[Class[_]]): Unit = {
    interfaces.add(interfaceType)
    for (inheritedInterface <- interfaceType.getInterfaces) addInterfaces(inheritedInterface, interfaces)
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy