Package jodd.madvoc.component

Source Code of jodd.madvoc.component.ScopeDataResolver

// Copyright (c) 2003-2014, Jodd Team (jodd.org). All Rights Reserved.

package jodd.madvoc.component;

import jodd.introspector.FieldDescriptor;
import jodd.introspector.MethodDescriptor;
import jodd.madvoc.ScopeData;
import jodd.madvoc.ScopeType;
import jodd.madvoc.MadvocException;
import jodd.madvoc.meta.In;
import jodd.madvoc.meta.InOut;
import jodd.madvoc.meta.Out;
import jodd.util.ReflectUtil;
import jodd.introspector.ClassDescriptor;
import jodd.introspector.ClassIntrospector;

import java.util.List;
import java.util.ArrayList;
import java.lang.reflect.Method;
import java.lang.reflect.Field;

/**
* Resolver for {@link jodd.madvoc.ScopeData scope data} for certain types.
* It does not cache anything as Scope data is cached in {@link jodd.madvoc.ActionConfig}.
* Resolving only happens during the initialization, and it might be repeated for
* certain types (as there is no cache), but that is acceptable to reduce memory
* usage (no cache) and several lookups (for each interceptor) during every request.
*/
public class ScopeDataResolver {

  /**
   * Resolve scope data in given type for all scope types.
   * Returns <code>null</code> if no scope data exist.
   */
  public ScopeData[] resolveScopeData(Class type) {
    ScopeData[] scopeData = inspectScopeData(type);

    if (scopeData == null) {
      return null;
    }

    return scopeData;
  }

  // ---------------------------------------------------------------- common

  /**
   * Inspects and returns scope data for all available scopes.
   */
  protected ScopeData[] inspectScopeData(Object key) {
    final ScopeType[] allScopeTypes = ScopeType.values();

    ScopeData[] scopeData = new ScopeData[allScopeTypes.length];

    int count = 0;
    if (key instanceof Class) {
      for (ScopeType scopeType : allScopeTypes) {
        ScopeData sd = inspectClassScopeData((Class) key, scopeType);
        if (sd != null) {
          count++;
        }
        scopeData[scopeType.value()] = sd;
      }
    }

    /*else if (key instanceof Method) {
      for (ScopeType scopeType : allScopeTypes) {
        ScopeData sd = inspectMethodScopeData((Method) key, scopeType);
        if (sd != null) {
          count++;
        }
        scopeData[scopeType.value()] = sd;
      }
    } */
    else {
      throw new MadvocException("Invalid type: " + key);
    }
    if (count == 0) {
      return null;
    }

    return scopeData;
  }


  // ---------------------------------------------------------------- inspect method

  /**
   * Inspects all method parameters for scope data.
   */
/*  protected ScopeData inspectMethodScopeData(Method method, ScopeType scopeType) {

    String[] methodParameterNames = actionParameterNamesResolver.resolveActionParameterNames(method);

    Annotation[][] annotations = method.getParameterAnnotations();
    Class<?>[] types = method.getParameterTypes();

    int paramsCount = types.length;

    ScopeData sd = new ScopeData();
    sd.in = new ScopeData.In[paramsCount];
    sd.out = new ScopeData.Out[paramsCount];

    int incount = 0, outcount = 0;

    for (int i = 0; i < paramsCount; i++) {
      Annotation[] paramAnnotations = annotations[i];

      Class type = types[i];
      String name = methodParameterNames[i];

      for (Annotation annotation : paramAnnotations) {

        if (annotation instanceof In) {
          sd.in[i] = inspectIn((In) annotation, scopeType, name, type);
          if (sd.in[i] != null) {
            incount++;
          }
        } else if (annotation instanceof Out) {
          sd.out[i] = inspectOut((Out) annotation, scopeType, StringUtil.uncapitalize(type.getSimpleName()), type);
          if (sd.out[i] != null) {
            outcount++;
          }
        }
      }
    }

    if (incount == 0 && outcount == 0) {
      return null;
    }
    if (incount == 0) {
      sd.in = null;
    }
    if (outcount == 0) {
      sd.out = null;
    }
    return sd;
  }
*/

  // ---------------------------------------------------------------- inspect class

  /**
   * Fills value and property name.
   */
  protected void fillNameTarget(ScopeData.In ii, String value, String propertyName) {
    value = value.trim();
    if (value.length() > 0) {
      ii.name = value;
      ii.target = propertyName;
    } else {
      ii.name = propertyName;
      ii.target = null;
    }
  }

  /**
   * Fills value and property name.
   */
  protected void fillNameTarget(ScopeData.Out oi, String value, String propertyName) {
    value = value.trim();
    if (value.length() > 0) {
      oi.name = value;
      oi.target = propertyName;
    } else {
      oi.name = propertyName;
      oi.target = null;
    }
  }

  /**
   * Inspects single IN annotation for a property.
   */
  protected ScopeData.In inspectIn(In in, ScopeType scopeType, String propertyName, Class propertyType) {
    if (in == null) {
      return null;
    }
    ScopeType scope = in.scope();
    if (scope != scopeType) {
      return null;
    }
    ScopeData.In ii = new ScopeData.In();
    fillNameTarget(ii, in.value(), propertyName);
    ii.type = propertyType;
    return ii;
  }

  /**
   * Inspects single INOUT annotation as IN.
   * @see #inspectIn(jodd.madvoc.meta.In, jodd.madvoc.ScopeType, String, Class)
   */
  protected ScopeData.In inspectIn(InOut inOut, ScopeType scopeType, String propertyName, Class propertyType) {
    if (inOut == null) {
      return null;
    }
    ScopeType scope = inOut.scope();
    if (scope != scopeType) {
      return null;
    }
    ScopeData.In ii = new ScopeData.In();
    fillNameTarget(ii, inOut.value(), propertyName);
    ii.type = propertyType;
    return ii;
  }

  /**
   * Inspects single OUT annotation for a property.
   */
  protected ScopeData.Out inspectOut(Out out, ScopeType scopeType, String propertyName, Class propertyType) {
    if (out == null) {
      return null;
    }
    ScopeType scope = out.scope();
    if (scope != scopeType) {
      return null;
    }
    ScopeData.Out oi = new ScopeData.Out();
    fillNameTarget(oi, out.value(), propertyName);
    oi.type = propertyType;
    return oi;
  }

  /**
   * Inspects single INOUT annotation as OUT.
   * @see #inspectOut(jodd.madvoc.meta.Out, jodd.madvoc.ScopeType, String, Class)
   */
  protected ScopeData.Out inspectOut(InOut inOut, ScopeType scopeType, String propertyName, Class propertyType) {
    if (inOut == null) {
      return null;
    }
    ScopeType scope = inOut.scope();
    if (scope != scopeType) {
      return null;
    }
    ScopeData.Out oi = new ScopeData.Out();
    fillNameTarget(oi, inOut.value(), propertyName);
    oi.type = propertyType;
    return oi;
  }

  /**
   * Inspect action for all In/Out annotations.
   * Returns <code>null</code> if there are no In and Out data.
   */
  protected ScopeData inspectClassScopeData(Class actionClass, ScopeType scopeType) {
    ClassDescriptor cd = ClassIntrospector.lookup(actionClass);
    FieldDescriptor[] fields = cd.getAllFieldDescriptors();
    MethodDescriptor[] methods = cd.getAllMethodDescriptors();

    List<ScopeData.In> listIn = new ArrayList<ScopeData.In>(fields.length + methods.length);
    List<ScopeData.Out> listOut = new ArrayList<ScopeData.Out>(fields.length + methods.length);


    // fields
    for (FieldDescriptor fieldDescriptor : fields) {
      Field field = fieldDescriptor.getField();

      Class fieldType = ReflectUtil.getRawType(field.getGenericType(), actionClass);

      In in = field.getAnnotation(In.class);
      ScopeData.In ii = inspectIn(in, scopeType, field.getName(), fieldType);
      if (ii != null) {
        listIn.add(ii);
      }
      InOut inout = field.getAnnotation(InOut.class);
      if (inout != null) {
        if (in != null) {
          throw new MadvocException("@InOut can not be used with @In: " + field.getDeclaringClass() + '#' + field.getName());
        }
        ii = inspectIn(inout, scopeType, field.getName(), field.getType());
        if (ii != null) {
          listIn.add(ii);
        }
      }

      Out out = field.getAnnotation(Out.class);
      ScopeData.Out oi = inspectOut(out, scopeType, field.getName(), fieldType);
      if (oi != null) {
        listOut.add(oi);
      }
      inout = field.getAnnotation(InOut.class);
      if (inout != null) {
        if (out != null) {
          throw new MadvocException("@InOut can not be used with @Out: " + field.getDeclaringClass() + '#' + field.getName());
        }
        oi = inspectOut(inout, scopeType, field.getName(), field.getType());
        if (oi != null) {
          listOut.add(oi);
        }
      }
    }

    // methods
    for (MethodDescriptor methodDescriptor : methods) {
      Method method = methodDescriptor.getMethod();

      String propertyName = ReflectUtil.getBeanPropertySetterName(method);
      if (propertyName != null) {
        In in = method.getAnnotation(In.class);
        ScopeData.In ii = inspectIn(in, scopeType, propertyName, method.getParameterTypes()[0]);
        if (ii != null) {
          listIn.add(ii);
        }
        InOut inout = method.getAnnotation(InOut.class);
        if (inout != null) {
          if (in != null) {
            throw new MadvocException("@InOut can not be used with @In: " + method.getDeclaringClass() + '#' + method.getName());
          }
          ii = inspectIn(inout, scopeType, propertyName, method.getParameterTypes()[0]);
          if (ii != null) {
            listIn.add(ii);
          }
        }
      }

      propertyName = ReflectUtil.getBeanPropertyGetterName(method);
      if (propertyName != null) {
        Out out = method.getAnnotation(Out.class);
        ScopeData.Out oi = inspectOut(out, scopeType, propertyName, method.getReturnType());
        if (oi != null) {
          listOut.add(oi);
        }
        InOut inout = method.getAnnotation(InOut.class);
        if (inout != null) {
          if (out != null) {
            throw new MadvocException("@InOut can not be used with @Out: " + method.getDeclaringClass() + '#' + method.getName());
          }
          oi = inspectOut(inout, scopeType, propertyName, method.getReturnType());
          if (oi != null) {
            listOut.add(oi);
          }
        }

      }
    }

    if ((listIn.isEmpty()) && (listOut.isEmpty())) {
      return null;
    }

    ScopeData scopeData = new ScopeData();
    if (listIn.isEmpty() == false) {
      scopeData.in = listIn.toArray(new ScopeData.In[listIn.size()]);
    }
    if (listOut.isEmpty() == false) {
      scopeData.out = listOut.toArray(new ScopeData.Out[listOut.size()]);
    }
    return scopeData;
  }

}
TOP

Related Classes of jodd.madvoc.component.ScopeDataResolver

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.