Package org.msgpack.template

Source Code of org.msgpack.template.TemplateRegistry

//
// MessagePack for Java
//
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
//
//    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 org.msgpack.template;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigInteger;
import java.nio.ByteBuffer;

import org.msgpack.MessagePackable;
import org.msgpack.MessageTypeException;
import org.msgpack.template.BigIntegerTemplate;
import org.msgpack.template.BooleanTemplate;
import org.msgpack.template.ByteArrayTemplate;
import org.msgpack.template.ByteTemplate;
import org.msgpack.template.DefaultTemplate;
import org.msgpack.template.DoubleArrayTemplate;
import org.msgpack.template.DoubleTemplate;
import org.msgpack.template.FieldList;
import org.msgpack.template.FloatArrayTemplate;
import org.msgpack.template.FloatTemplate;
import org.msgpack.template.GenericTemplate;
import org.msgpack.template.IntegerArrayTemplate;
import org.msgpack.template.IntegerTemplate;
import org.msgpack.template.LongArrayTemplate;
import org.msgpack.template.LongTemplate;
import org.msgpack.template.ShortArrayTemplate;
import org.msgpack.template.ShortTemplate;
import org.msgpack.template.StringTemplate;
import org.msgpack.template.Template;
import org.msgpack.template.ValueTemplate;
import org.msgpack.template.builder.TemplateBuilder;
import org.msgpack.template.builder.TemplateBuilderChain;
import org.msgpack.type.Value;


public class TemplateRegistry {

    private TemplateRegistry parent = null;

    private TemplateBuilderChain chain;

    private Map<Type, Template<Type>> cache;

    private Map<Type, GenericTemplate> genericCache;

    public TemplateRegistry() {
  this(null);
    }

    public TemplateRegistry(TemplateRegistry registry) {
  parent = registry;
  cache = new HashMap<Type, Template<Type>>();
  genericCache = new HashMap<Type, GenericTemplate>();
  if (parent == null) {
      registerTemplates();
      chain = new TemplateBuilderChain();
      chain.init(this);
  } else {
      chain = registry.chain;
  }
    }

    private void registerTemplates() {
        register(boolean.class, BooleanTemplate.getInstance());
        register(Boolean.class, BooleanTemplate.getInstance());
        register(byte.class, ByteTemplate.getInstance());
        register(Byte.class, ByteTemplate.getInstance());
        register(short.class, ShortTemplate.getInstance());
        register(Short.class, ShortTemplate.getInstance());
        register(int.class, IntegerTemplate.getInstance());
        register(Integer.class, IntegerTemplate.getInstance());
        register(long.class, LongTemplate.getInstance());
        register(Long.class, LongTemplate.getInstance());
        register(float.class, FloatTemplate.getInstance());
        register(Float.class, FloatTemplate.getInstance());
        register(double.class, DoubleTemplate.getInstance());
        register(Double.class, DoubleTemplate.getInstance());
        register(BigInteger.class, BigIntegerTemplate.getInstance());
        register(boolean[].class, BooleanArrayTemplate.getInstance());
        register(short[].class, ShortArrayTemplate.getInstance());
        register(int[].class, IntegerArrayTemplate.getInstance());
        register(long[].class, LongArrayTemplate.getInstance());
        register(float[].class, FloatArrayTemplate.getInstance());
        register(double[].class, DoubleArrayTemplate.getInstance());
        register(String.class, StringTemplate.getInstance());
        register(byte[].class, ByteArrayTemplate.getInstance());
        register(ByteBuffer.class, ByteBufferTemplate.getInstance());
        register(Value.class, ValueTemplate.getInstance());
        //register(Value.class, AnyTemplate.getInstance(this));
        register(List.class, new ListTemplate(AnyTemplate.getInstance(this)));
        register(Collection.class, new CollectionTemplate(AnyTemplate.getInstance(this)));
        register(Map.class, new MapTemplate(AnyTemplate.getInstance(this), AnyTemplate.getInstance(this)));

        registerGeneric(List.class, new GenericCollectionTemplate(this, ListTemplate.class));
        registerGeneric(Collection.class, new GenericCollectionTemplate(this, CollectionTemplate.class));
        registerGeneric(Map.class, new GenericMapTemplate(this, MapTemplate.class));
    }

    public void register(final Class<?> targetClass) {
  register(targetClass, chain.select(targetClass, false).buildTemplate(targetClass));
    }

    public void register(final Class<?> targetClass, final FieldList flist) {
  if (flist == null) {
      throw new NullPointerException("FieldList object is null");
  }
  register(targetClass, chain.select(targetClass, false).buildTemplate(targetClass, flist));
    }

    public synchronized void register(final Type targetType, final Template tmpl) {
        if (targetType instanceof ParameterizedType) {
            cache.put(((ParameterizedType) targetType).getRawType(), tmpl);
        } else {
            cache.put(targetType, tmpl);
        }
    }

    public synchronized void registerGeneric(final Type targetType, final GenericTemplate tmpl) {
  if(targetType instanceof ParameterizedType) {
      genericCache.put(((ParameterizedType) targetType).getRawType(), tmpl);
  } else {
      genericCache.put(targetType, tmpl);
  }
    }

    public synchronized boolean unregister(final Type targetType) {
  Template<Type> tmpl = cache.remove(targetType);
  return tmpl != null;
    }

    public synchronized void unregister() {
  cache.clear();
    }

    public synchronized Template lookup(Type targetType) {
        return lookupImpl(targetType, true, false, true);
    }

    public synchronized Template lookup(Type targetType, final boolean forceBuild) {
  return lookupImpl(targetType, true, forceBuild, true);
    }

    public synchronized Template lookup(Type targetType, final boolean forceLoad, final boolean forceBuild) {
  return lookupImpl(targetType, forceLoad, forceBuild, true);
    }

    public synchronized Template tryLookup(Type targetType) {
  return lookupImpl(targetType, true, false, false);
    }

    public synchronized Template tryLookup(Type targetType, final boolean forceBuild) {
  return lookupImpl(targetType, true, forceBuild, false);
    }

    private synchronized Template lookupImpl(Type targetType,
      final boolean forceLoad, final boolean forceBuild, final boolean fallbackDefault) {
  Template tmpl;

  if (targetType instanceof ParameterizedType) {
      ParameterizedType pType = (ParameterizedType) targetType;
      // ParameterizedType is not a Class<?>?
      tmpl = lookupGenericImpl(pType);
      if (tmpl != null) {
    return tmpl;
      }
      try {
    tmpl = parent.lookupGenericImpl(pType);
    if (tmpl != null) {
        return tmpl;
    }
      } catch (NullPointerException e) { // ignore
      }
      targetType = pType.getRawType();
  }

  tmpl = cache.get(targetType);
  if (tmpl != null) {
      return tmpl;
  }
  try {
      tmpl = parent.cache.get(targetType);
      if (tmpl != null) {
    return tmpl;
      }
  } catch (NullPointerException e) { // ignore
  }

  Class<?> targetClass = (Class<?>) targetType;

  if (MessagePackable.class.isAssignableFrom(targetClass)) {
      tmpl = new MessagePackableTemplate(targetClass);
      register(targetClass, tmpl);
      return tmpl;
  }

  // find match TemplateBuilder
  TemplateBuilder builder = chain.select(targetClass, true);
  if (builder != null) {
      if (forceLoad) {
    tmpl = builder.loadTemplate(targetClass);
    if (tmpl != null) {
        register(targetClass, tmpl);
        return tmpl;
    }
      }

      tmpl = builder.buildTemplate(targetClass);
      if (tmpl != null) {
    register(targetClass, tmpl);
    return tmpl;
      }
  }

  // lookup template of interface type
  Class<?>[] infTypes = targetClass.getInterfaces();
  for (Class<?> infType : infTypes) {
      tmpl = cache.get(infType);
      if (tmpl != null) {
    register(targetClass, tmpl);
    return tmpl;
      } else {
    try {
        tmpl = parent.cache.get(infType);
        if (tmpl != null) {
      parent.register(targetClass, tmpl);
      return tmpl;
        }
    } catch (NullPointerException e) { // ignore
    }
      }
  }

  // lookup template of superclass type
  Class<?> superClass = targetClass.getSuperclass();
  if (superClass != null) {
      for (; superClass != Object.class; superClass = superClass.getSuperclass()) {
    tmpl = cache.get(superClass);
    if (tmpl != null) {
        register(targetClass, tmpl);
        return tmpl;
    } else {
        try {
      tmpl = parent.cache.get(superClass);
      if (tmpl != null) {
          register(targetClass, tmpl);
          return tmpl;
      }
        } catch (NullPointerException e) { // ignore
        }
    }
      }

      if (forceBuild) {
    tmpl = chain.select(targetClass, true).buildTemplate(targetClass);
    register(targetClass, tmpl);
    return tmpl;
      }
  }

  if (fallbackDefault) {
      tmpl = new DefaultTemplate(this, (Class<?>) targetClass);
      register(targetClass, tmpl);
      return tmpl;
  } else {
      throw new MessageTypeException(
        "Cannot find template for " + targetClass + " class. Try to add @Message annotation to the class or call MessagePack.register(Type).");
  }
    }

    public synchronized Template lookupGeneric(final Type targetType) {
  if (targetType instanceof ParameterizedType) {
      ParameterizedType parameterizedType = (ParameterizedType)targetType;
      Template tmpl = lookupGenericImpl(parameterizedType);
      if (tmpl != null) {
    return tmpl;
      }
      return new DefaultTemplate(this, (Class<?>) parameterizedType.getRawType(), parameterizedType);
  } else {
      throw new IllegalArgumentException("Actual types of the generic type are erased: "+targetType);
  }
    }

    private synchronized Template lookupGenericImpl(final ParameterizedType targetType) {
  Type rawType = targetType.getRawType();
  GenericTemplate tmpl = genericCache.get(rawType);
  if (tmpl == null) {
      return null;
  }

  Type[] types = targetType.getActualTypeArguments();
  Template[] tmpls = new Template[types.length];
  for (int i=0; i < types.length; ++i) {
      tmpls[i] = lookup(types[i]);
  }

  return tmpl.build(tmpls);
    }
}
TOP

Related Classes of org.msgpack.template.TemplateRegistry

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.