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

org.jboss.cache.aop.CachedType Maven / Gradle / Ivy

There is a newer version: 1.4.1.GA
Show newest version
package org.jboss.cache.aop;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;

/**  Represent a cached object type, e.g., whether it is primitive or not.
 *
 * @author Harald Gliebe
 * @author Ben Wang
 */

public class CachedType
{
   // Types that are considered "primitive".
   protected static Set immediates =
         new HashSet(Arrays.asList(new Object[]{
            String.class,
            Boolean.class,
            Double.class,
            Float.class,
            Integer.class,
            Long.class,
            Short.class,
            Character.class,
            Boolean.TYPE,
            Double.TYPE,
            Float.TYPE,
            Integer.TYPE,
            Long.TYPE,
            Short.TYPE,
            Character.TYPE,
            Class.class}));

   protected Class type;
   protected boolean immutable;
   protected boolean immediate;

   // Java Bean attributes (Get/Set)
   protected List attributes = new ArrayList();
   protected Map attributeMap = new HashMap(); // Method -> CachedAttribute

   // Java fields
   protected List fields = new ArrayList();
   protected Map fieldMap = new HashMap(); // Name -> CachedAttribute

   public CachedType()
   {
   }

   public CachedType(Class type)
   {
      this.type = type;
      analyze();
   }

   public Class getType()
   {
      return type;
   }

   // determines if the object should be stored in the Nodes map or as a subnode
   public boolean isImmediate()
   {
      return immediate;
   }

   public static boolean isImmediate(Class clazz)
   {
      return immediates.contains(clazz);
   }

   public boolean isImmutable()
   {
      return immutable;
   }

   public List getFields()
   {
      return fields;
   }

   public Field getField(String name)
   {
      return (Field) fieldMap.get(name);
   }

   /*
   public List getAttributes()
   {
      return attributes;
   }

   public CachedAttribute getAttribute(Method m)
   {
      return (CachedAttribute) attributeMap.get(m);
   }

   protected void setAttributes(List attributes)
   {
      this.attributes = attributes;

      attributeMap.clear();

      // TODO: is a class with no set methods immutable ?
      this.immutable = true;

      for (Iterator i = attributes.iterator(); i.hasNext();) {
         CachedAttribute attribute = (CachedAttribute) i.next();
         if (attribute.getGet() != null) {
            attributeMap.put(attribute.getGet(), attribute);
         }
         if (attribute.getSet() != null) {
            attributeMap.put(attribute.getSet(), attribute);
            immutable = false;
         }
      }
   }
   */

   public String toString()
   {
      StringBuffer sb = new StringBuffer();
      sb.append(type.getName()).append(" {\n");
      for (Iterator i = attributes.iterator(); i.hasNext();) {
         CachedAttribute attr = (CachedAttribute) i.next();
         sb
               .append("\t")
               .append(attr.getType().getName())
               .append(" ")
               .append(attr.getName())
               .append(" [")
               .append(attr.getGet() == null
               ? ""
               : attr.getGet().getName())
               .append(", ")
               .append(attr.getSet() == null
               ? ""
               : attr.getSet().getName())
               .append("]\n");
      }
      sb.append("}, immutable =" + immutable);
      return sb.toString();
   }

   /* ---------------------------------------- */

   private void analyze()
   {

      /*
      // We intercept all fields now (instead of setter methods) so there is no need to
      // track the individual fields.
      HashMap attributes = new HashMap();
      Method[] methods = type.getMethods();
      for (int i = 0; i < methods.length; i++) {
         Method method = methods[i];
         if (isGet(method)) {
            CachedAttribute attribute =
                  getAttribute(method, attributes, true);
            attribute.setGet(method);
            attribute.setType(method.getReturnType());
         } else if (isSet(method)) {
            CachedAttribute attribute =
                  getAttribute(method, attributes, true);
            attribute.setSet(method);
            attribute.setType(method.getParameterTypes()[0]);
         }
      }
      this.setAttributes(new ArrayList(attributes.values()));
      */
      analyzeFields(type);

      immediate = isImmediate(type);

   }

   void analyzeFields(Class clazz)
   {
      if (clazz == null)
         return;

      analyzeFields(clazz.getSuperclass());

      Field[] classFields = clazz.getDeclaredFields();
      for (int i = 0; i < classFields.length; i++) {
         Field f = classFields[i];
         if(isNonReplicatable(f)) continue;

         f.setAccessible(true);
         fields.add(f);
         fieldMap.put(f.getName(), f);
      }
   }

   public static boolean isNonReplicatable(Field f) {
      int mods = f.getModifiers();
      /**
       * The following modifiers are ignored in the cache, i.e., they will not be stored in the cache.
       * Whenever, user trying to access these fields, it will be accessed from the in-memory version.
       */
      if (Modifier.isStatic(mods)
            || Modifier.isTransient(mods)
            || Modifier.isFinal(mods)) {
         return true;
      }
      return false;
   }

   /*
    * converts a get/set method to an attribute name
    */
   protected String attributeName(String methodName)
   {
      return methodName.substring(3, 4).toLowerCase()
            + methodName.substring(4);
   }

   protected CachedAttribute getAttribute(Method method,
                                          Map map,
                                          boolean create)
   {
      String name = attributeName(method.getName());

      CachedAttribute attribute = (CachedAttribute) map.get(name);
      if (create && attribute == null) {
         attribute = new CachedAttribute(name);
         map.put(name, attribute);
      }
      return attribute;
   }

   protected boolean isGet(Method method)
   {
      return method.getName().startsWith("get")
            && method.getParameterTypes().length == 0
            && method.getReturnType() != Void.TYPE;
   }

   protected boolean isSet(Method method)
   {
      return method.getName().startsWith("set")
            && method.getParameterTypes().length == 1
            && method.getReturnType() == Void.TYPE;
   }

} // CachedType




© 2015 - 2024 Weber Informatics LLC | Privacy Policy