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

org.beangle.data.serialize.marshal.DefaultMarshallerRegistry.scala Maven / Gradle / Ivy

/*
 * Beangle, Agile Development Scaffold and Toolkit
 *
 * Copyright (c) 2005-2016, Beangle Software.
 *
 * Beangle 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.
 *
 * Beangle 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 Beangle.  If not, see .
 */
package org.beangle.data.serialize.marshal

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

import org.beangle.commons.collection.IdentityCache
import org.beangle.commons.lang.reflect.Reflections
import org.beangle.data.serialize.SerializeException
import org.beangle.data.serialize.mapper.Mapper

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]) {
    val clazz = Reflections.getGenericParamType(converter.getClass, classOf[Marshaller[_]])("T")
    converterMap.get(clazz) match {
      case Some(converters) =>
        converters.find { each =>
          each.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 TupleConvertor(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.isEmpty) {
      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)
    }
    var 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[_]]) {
    interfaces.add(interfaceType)
    for (inheritedInterface <- interfaceType.getInterfaces) addInterfaces(inheritedInterface, interfaces)
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy