Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you 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.apache.avro.reflect;
 
 import java.util.List;
 import java.util.Map;
 
 
Utilities to use existing Java classes and interfaces via reflection.
 
 public class ReflectData extends SpecificData {
  
  
ReflectData implementation that permits null field values. The schema generated for each field is a union of its declared type and null.
 
   public static class AllowNull extends ReflectData {
 
     private static final AllowNull INSTANCE = new AllowNull();

    
Return the singleton instance.
 
     public static AllowNull get() { return ; }
 
     protected Schema createFieldSchema(Field fieldMap<StringSchemanames) {
       Schema schema = super.createFieldSchema(fieldnames);
       return makeNullable(schema);
     }
   }
   
   private static final ReflectData INSTANCE = new ReflectData();
 
   protected ReflectData() {}
  
  
Return the singleton instance.
 
   public static ReflectData get() { return ; }
 
   @Override
   protected boolean isRecord(Object datum) {
     if (datum == nullreturn false;
     return getSchema(datum.getClass()).getType() == ..;
   }
 
   @Override
   protected boolean isArray(Object datum) {
     return (datum instanceof Collection) || datum.getClass().isArray();
   }
 
   @Override
   protected boolean isString(Object datum) {
     return datum instanceof String;
   }
 
   @Override
   protected boolean isBytes(Object datum) {
     if (datum == nullreturn false;
     Class c = datum.getClass();
     return c.isArray() && c.getComponentType() == .;
   }
 
   @Override
   protected Schema getRecordSchema(Object record) {
    return getSchema(record.getClass());
  }
  public boolean validate(Schema schemaObject datum) {
    switch (schema.getType()) {
    case :
      if (datum == nullreturn false;
      Class c = datum.getClass(); 
      for (Schema.Field f : schema.getFields()) {
        try {
          if (!validate(f.schema(),
                        getField(cf.name()).get(datum)))
          return false;
        } catch (IllegalAccessException e) {
          throw new AvroRuntimeException(e);
        }
      }
      return true;
    case :
      if (datum instanceof Collection) {          // collection
        for (Object element : (Collection)datum)
          if (!validate(schema.getElementType(), element))
            return false;
        return true;
      } else if (datum.getClass().isArray()) {    // array
        int length = java.lang.reflect.Array.getLength(datum);
        for (int i = 0; i < lengthi++)
          if (!validate(schema.getElementType(),
                        java.lang.reflect.Array.get(datumi)))
            return false;
        return true;
      }
      return false;
    default:
      return super.validate(schemadatum);
    }
  }
  private static final Map<Class,Map<String,Field>> FIELD_CACHE =
    new ConcurrentHashMap<Class,Map<String,Field>>();

  
Return the named field of the provided class. Implementation caches values, since this is used at runtime to get and set fields.
  protected static Field getField(Class cString name) {
    Map<String,Fieldfields = .get(c);
    if (fields == null) {
      fields = new ConcurrentHashMap<String,Field>();
      .put(cfields);
    }
    Field f = fields.get(name);
    if (f == null) {
      f = findField(cname);
      fields.put(namef);
    }
    return f;
  }
  private static Field findField(Class cString name) {
    do {
      try {
        Field f = c.getDeclaredField(name);
        f.setAccessible(true);
        return f;
      } catch (NoSuchFieldException e) {}
      c = c.getSuperclass();
    } while (c != null);
    throw new AvroRuntimeException("No field named "+name+" in: "+c);
  }
  static final String CLASS_PROP = "java-class";
  static final String ELEMENT_PROP = "java-element-class";
  static Class getClassProp(Schema schemaString prop) {
    String name = schema.getProp(prop);
    if (name == nullreturn null;
    try {
      return Class.forName(name);
    } catch (ClassNotFoundException e) {
      throw new AvroRuntimeException(e);
    }
  }
  private static final Class BYTES_CLASS = new byte[0].getClass();
  public Class getClass(Schema schema) {
    switch (schema.getType()) {
    case :
      Class collectionClass = getClassProp(schema);
      if (collectionClass != null)
        return collectionClass;
      return java.lang.reflect.Array.newInstance(getClass(schema.getElementType()),0).getClass();
    case :  return String.class;
    case :   return ;
    case :
      if (Short.class.getName().equals(schema.getProp()))
        return .;
    default:
      return super.getClass(schema);
    }
  }
  @SuppressWarnings(value="unchecked")
  protected Schema createSchema(Type typeMap<String,Schemanames) {
    if (type instanceof GenericArrayType) {                  // generic array
      Type component = ((GenericArrayType)type).getGenericComponentType();
      if (component == .)                            // byte array
        return Schema.create(..);           
      Schema result = Schema.createArray(createSchema(componentnames));
      setElement(resultcomponent);
      return result;
    } else if (type instanceof ParameterizedType) {
      ParameterizedType ptype = (ParameterizedType)type;
      Class raw = (Class)ptype.getRawType();
      Type[] params = ptype.getActualTypeArguments();
      if (Map.class.isAssignableFrom(raw)) {                 // Map
        Type key = params[0];
        Type value = params[1];
        if (!(key == String.class))
          throw new AvroTypeException("Map key class not String: "+key);
        return Schema.createMap(createSchema(valuenames));
      } else if (Collection.class.isAssignableFrom(raw)) {   // Collection
        if (params.length != 1)
          throw new AvroTypeException("No array type specified.");
        Schema schema = Schema.createArray(createSchema(params[0], names));
        schema.addProp(raw.getName());
        return schema;
      }
    } else if ((type == Short.class) || (type == .)) {
      Schema result = Schema.create(..);
      result.addProp(Short.class.getName());
      return result;
    } else if (type instanceof Class) {                      // Class
      Class<?> c = (Class<?>)type;
      if (c.isPrimitive() || Number.class.isAssignableFrom(c)
          || c == Void.class || c == Boolean.class)          // primitive
        return super.createSchema(typenames);
      if (c.isArray()) {                                     // array
        Class component = c.getComponentType();
        if (component == .)                          // byte array
          return Schema.create(..);
        Schema result = Schema.createArray(createSchema(componentnames));
        setElement(resultcomponent);
        return result;
      }
      if (c == String.class)                                 // String
        return Schema.create(..);
      String fullName = c.getName();
      Schema schema = names.get(fullName);
      if (schema == null) {
        String name = c.getSimpleName();
        String space = c.getPackage().getName();
        if (c.getEnclosingClass() != null)                   // nested class
          space = c.getEnclosingClass().getName() + "$";
        Union union = c.getAnnotation(Union.class);
        if (union != null) {                                 // union annotated
          return getAnnotatedUnion(unionnames);
        } else if (c.isAnnotationPresent(Stringable.class)){ // Stringable
          Schema result = Schema.create(..);
          result.addProp(c.getName());
          return result;
        } else if (c.isEnum()) {                             // Enum
          List<Stringsymbols = new ArrayList<String>();
          Enum[] constants = (Enum[])c.getEnumConstants();
          for (int i = 0; i < constants.lengthi++)
            symbols.add(constants[i].name());
          schema = Schema.createEnum(namenull /* doc */spacesymbols);
        } else if (GenericFixed.class.isAssignableFrom(c)) { // fixed
          int size = c.getAnnotation(FixedSize.class).value();
          schema = Schema.createFixed(namenull /* doc */spacesize);
        } else {                                             // record
          List<Schema.Fieldfields = new ArrayList<Schema.Field>();
          schema = Schema.createRecord(namenull /* doc */space
                                       Throwable.class.isAssignableFrom(c));
          names.put(c.getName(), schema);
          for (Field field : getFields(c))
            if ((field.getModifiers()&(.|.))==0){
              Schema fieldSchema = createFieldSchema(fieldnames);
              fields.add(new Schema.Field(field.getName(),
                  fieldSchemanull /* doc */null));
            }
          schema.setFields(fields);
        }
        names.put(fullNameschema);
      }
      return schema;
    }
    return super.createSchema(typenames);
  }
  // if array element type is a class with a union annotation, note it
  // this is required because we cannot set a property on the union itself 
  @SuppressWarnings(value="unchecked")
  private void setElement(Schema schemaType element) {
    if (!(element instanceof Class)) return;
    Class<?> c = (Class<?>)element;
    Union union = c.getAnnotation(Union.class);
    if (union != null)                          // element is annotated union
      schema.addProp(c.getName());
  }
  // construct a schema from a union annotation
  private Schema getAnnotatedUnion(Union unionMap<String,Schemanames) {
    List<Schemabranches = new ArrayList<Schema>();
    for (Class branch : union.value())
      branches.add(createSchema(branchnames));
    return Schema.createUnion(branches);
  }

  
Create and return a union of the null schema and the provided schema.
  public static Schema makeNullable(Schema schema) {
    return Schema.createUnion(Arrays.asList(Schema.create(..),
                                            schema));
  }
  // Return of this class and its superclasses to serialize.
  // Not cached, since this is only used to create schemas, which are cached.
  private Collection<FieldgetFields(Class recordClass) {
    Map<String,Fieldfields = new LinkedHashMap<String,Field>();
    Class c = recordClass;
    do {
      if (c.getPackage().getName().startsWith("java."))
        break;                                    // skip java built-in classes
      for (Field field : c.getDeclaredFields())
        if ((field.getModifiers() & (.|.)) == 0)
          if (fields.put(field.getName(), field) != null)
            throw new AvroTypeException(c+" contains two fields named: "+field);
      c = c.getSuperclass();
    } while (c != null);
    return fields.values();
  }

  
Create a schema for a field.
  protected Schema createFieldSchema(Field fieldMap<StringSchemanames) {
    Schema schema = createSchema(field.getGenericType(), names);
    if (field.isAnnotationPresent(Nullable.class))           // nullable
      schema = makeNullable(schema);
    return schema;
  }

  
Return the protocol for a Java interface.

Note that this requires that Paranamer is run over compiled interface declarations, since Java 6 reflection does not provide access to method parameter names. See Avro's build.xml for an example.

  public Protocol getProtocol(Class iface) {
    Protocol protocol =
      new Protocol(iface.getSimpleName(), iface.getPackage().getName()); 
    Map<String,Schemanames = new LinkedHashMap<String,Schema>();
    for (Method method : iface.getMethods())
      if ((method.getModifiers() & .) == 0)
        protocol.getMessages().put(method.getName(),
                                   getMessage(methodprotocolnames));
    // reverse types, since they were defined in reference order
    List<Schematypes = new ArrayList<Schema>();
    types.addAll(names.values());
    Collections.reverse(types);
    protocol.setTypes(types);
    return protocol;
  }
  private final Paranamer paranamer = new CachingParanamer();
  private Message getMessage(Method methodProtocol protocol,
                             Map<String,Schemanames) {
    List<Schema.Fieldfields = new ArrayList<Schema.Field>();
    String[] paramNames = .lookupParameterNames(method);
    Type[] paramTypes = method.getGenericParameterTypes();
    Annotation[][] annotations = method.getParameterAnnotations();
    for (int i = 0; i < paramTypes.lengthi++) {
      Schema paramSchema = getSchema(paramTypes[i], names);
      for (int j = 0; j < annotations[i].lengthj++)
        if (annotations[i][jinstanceof Union)
          paramSchema = getAnnotatedUnion(((Union)annotations[i][j]), names);
        else if (annotations[i][jinstanceof Nullable)
          paramSchema = makeNullable(paramSchema);
      String paramName =  paramNames.length == paramTypes.length
        ? paramNames[i]
        : paramSchema.getName()+i;
      fields.add(new Schema.Field(paramNameparamSchema,
        null /* doc */null));
    }
    Schema request = Schema.createRecord(fields);
    Union union = method.getAnnotation(Union.class);
    Schema response = union == null
      ? getSchema(method.getGenericReturnType(), names)
      : getAnnotatedUnion(unionnames);
    if (method.isAnnotationPresent(Nullable.class))          // nullable
      response = makeNullable(response);
    List<Schemaerrs = new ArrayList<Schema>();
    errs.add(.);              // every method can throw
    for (Type err : method.getGenericExceptionTypes())
      if (err != AvroRemoteException.class
        errs.add(getSchema(errnames));
    Schema errors = Schema.createUnion(errs);
    return protocol.createMessage(method.getName(), null /* doc */requestresponseerrors);
  }
  private Schema getSchema(Type typeMap<String,Schemanames) {
    try {
      return createSchema(typenames);
    } catch (AvroTypeException e) {               // friendly exception
      throw new AvroTypeException("Error getting schema for "+type+": "
                                  +e.getMessage(), e);
    }
  }
  public int compare(Object o1Object o2Schema s) {
    throw new UnsupportedOperationException();
  }
New to GrepCode? Check out our FAQ X