Package org.msgpack.template

Source Code of org.msgpack.template.FieldEntryReader

//
// 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.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

import org.msgpack.annotation.Ignore;
import org.msgpack.annotation.Index;
import org.msgpack.annotation.MessagePackMessage;
import org.msgpack.annotation.Nullable;
import org.msgpack.annotation.Optional;
import org.msgpack.annotation.Required;

public class FieldEntryReader implements IFieldEntryReader{


  public IFieldEntry[] convertFieldEntries(Class<?> targetClass, FieldList flist) throws NoSuchFieldException {
    List<FieldList.Entry> src = flist.getList();
    FieldEntry[] result = new FieldEntry[src.size()];
    for(int i=0; i < src.size(); i++) {
      FieldList.Entry s = src.get(i);
      if(s.isAvailable()) {
        result[i] = new FieldEntry(targetClass.getDeclaredField(s.getName()), s.getOption());
      } else {
        result[i] = new FieldEntry();
      }
    }
    return result;
  }
 
  @Override
  public IFieldEntry[] readFieldEntries(Class<?> targetClass,
      FieldOption implicitOption) {
    Field[] allFields = readAllFields(targetClass);

    /* index:
     *   @Index(0) int field_a;   // 0
     *             int field_b;   // 1
     *   @Index(3) int field_c;   // 3
     *             int field_d;   // 4
     *   @Index(2) int field_e;   // 2
     *             int field_f;   // 5
     */
    List<FieldEntry> indexed = new ArrayList<FieldEntry>();
    int maxIndex = -1;
    for(Field f : allFields) {
      FieldOption opt = readFieldOption(f, implicitOption);
      if(opt == FieldOption.IGNORE) {
        // skip
        continue;
      }

      int index = readFieldIndex(f, maxIndex);

      if(indexed.size() > index && indexed.get(index) != null) {
        throw new TemplateBuildException("duplicated index: "+index);
      }
      if(index < 0) {
        throw new TemplateBuildException("invalid index: "+index);
      }

      while(indexed.size() <= index) {
        indexed.add(null);
      }
      indexed.set(index, new FieldEntry(f, opt));

      if(maxIndex < index) {
        maxIndex = index;
      }
    }

    FieldEntry[] result = new FieldEntry[maxIndex+1];
    for(int i=0; i < indexed.size(); i++) {
      FieldEntry e = indexed.get(i);
      if(e == null) {
        result[i] = new FieldEntry();
      } else {
        result[i] = e;
      }
    }

    return result;
  }

  public FieldOption readImplicitFieldOption(Class<?> targetClass) {
    MessagePackMessage a = targetClass.getAnnotation(MessagePackMessage.class);
    if(a == null) {
      return FieldOption.DEFAULT;
    }
    return a.value();
  }
 
  private Field[] readAllFields(Class<?> targetClass) {
    // order: [fields of super class, ..., fields of this class]
    List<Field[]> succ = new ArrayList<Field[]>();
    int total = 0;
    for(Class<?> c = targetClass; c != Object.class; c = c.getSuperclass()) {
      Field[] fields = c.getDeclaredFields();
      total += fields.length;
      succ.add(fields);
    }
    Field[] result = new Field[total];
    int off = 0;
    for(int i=succ.size()-1; i >= 0; i--) {
      Field[] fields = succ.get(i);
      System.arraycopy(fields, 0, result, off, fields.length);
      off += fields.length;
    }
    return result;
  }

  private static FieldOption readFieldOption(Field field, FieldOption implicitOption) {
    int mod = field.getModifiers();
    if(Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
      return FieldOption.IGNORE;
    }

    if(isAnnotated(field, Ignore.class)) {
      return FieldOption.IGNORE;
    } else if(isAnnotated(field, Required.class)) {
      return FieldOption.REQUIRED;
    } else if(isAnnotated(field, Optional.class)) {
      return FieldOption.OPTIONAL;
    } else if(isAnnotated(field, Nullable.class)) {
      if(field.getDeclaringClass().isPrimitive()) {
        return FieldOption.REQUIRED;
      } else {
        return FieldOption.NULLABLE;
      }
    }

    if(implicitOption != FieldOption.DEFAULT) {
      return implicitOption;
    }

    // default mode:
    //   transient : Ignore
    //   public    : Required
    //   others    : Ignore
    if(Modifier.isTransient(mod)) {
      return FieldOption.IGNORE;
    } else if(Modifier.isPublic(mod)) {
      return FieldOption.REQUIRED;
    } else {
      return FieldOption.IGNORE;
    }
  }

  private static int readFieldIndex(Field field, int maxIndex) {
    Index a = field.getAnnotation(Index.class);
    if(a == null) {
      return maxIndex + 1;
    } else {
      return a.value();
    }
  }

  private static boolean isAnnotated(AccessibleObject ao, Class<? extends Annotation> with) {
    return ao.getAnnotation(with) != null;
  }
 
}
TOP

Related Classes of org.msgpack.template.FieldEntryReader

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.