Package org.codehaus.enunciate.contract.jaxb.adapters

Source Code of org.codehaus.enunciate.contract.jaxb.adapters.AdapterUtil

/*
* Copyright 2006-2008 Web Cohesion
*
* 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.codehaus.enunciate.contract.jaxb.adapters;

import com.sun.mirror.apt.AnnotationProcessorEnvironment;
import com.sun.mirror.declaration.Declaration;
import com.sun.mirror.declaration.MethodDeclaration;
import com.sun.mirror.declaration.PackageDeclaration;
import com.sun.mirror.declaration.TypeDeclaration;
import com.sun.mirror.type.*;
import net.sf.jelly.apt.Context;
import org.codehaus.enunciate.contract.jaxb.Accessor;
import static org.codehaus.enunciate.contract.jaxb.util.JAXBUtil.unwrapComponentType;
import org.codehaus.enunciate.contract.jaxws.WebParam;
import org.codehaus.enunciate.contract.validation.ValidationException;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
* Logic for the XML adapter stuff according to the JAXB specification.
*
* @author Ryan Heaton
*/
public class AdapterUtil {

  private static final HashMap<String, HashMap<String, XmlJavaTypeAdapter>> ADAPTERS_BY_PACKAGE = new HashMap<String, HashMap<String, XmlJavaTypeAdapter>>();

  /**
   * Finds the adapter type for the specified declaration, if any.
   *
   * @param declaration The declaration for which to find that adapter type.
   * @return The adapter type, or null if none was specified.
   */
  public static AdapterType findAdapterType(Declaration declaration) {
    if (declaration instanceof Accessor) {
      //jaxb accessor can be adapted.
      Accessor accessor = ((Accessor) declaration);
      return findAdapterType(accessor.getAccessorType(), accessor, accessor.getDeclaringType().getPackage());
    }
    else if (declaration instanceof MethodDeclaration) {
      //assume the return type of the method is adaptable (e.g. web results, fault bean getters).
      MethodDeclaration method = ((MethodDeclaration) declaration);
      return findAdapterType(method.getReturnType(), method, method.getDeclaringType().getPackage());
    }
    else if (declaration instanceof WebParam) {
      WebParam parameter = ((WebParam) declaration);
      return findAdapterType(parameter.getType(), parameter, parameter.getWebMethod().getDeclaringEndpointInterface().getPackage());
    }
    else if (declaration instanceof TypeDeclaration) {
      TypeDeclaration typeDeclaration = (TypeDeclaration) declaration;
     
      // Context usage is not thread-safe!!
      AnnotationProcessorEnvironment ape = Context.getCurrentEnvironment();
      typeDeclaration = ape.getTypeDeclaration(typeDeclaration.getQualifiedName()); //unwrap the decorated stuff as necessary...
      DeclaredType declaredType = ape.getTypeUtils().getDeclaredType(typeDeclaration);
      return findAdapterType(declaredType, null, null);
    }
    else {
      throw new IllegalArgumentException("A " + declaration.getClass().getSimpleName() + " is not an adaptable declaration according to the JAXB spec.");
    }
  }

  /**
   * Finds the adapter type of the specified type, given the referer and the package of the referer.
   *
   * @param unwrappedAdaptedType The type for which to find the adapter.
   * @param referer The referer.
   * @param pckg The package of the referer.
   * @return The adapter type, or null if none was found.
   */
  private static AdapterType findAdapterType(TypeMirror unwrappedAdaptedType, Declaration referer, PackageDeclaration pckg) {
    TypeMirror adaptedType = unwrapComponentType(unwrappedAdaptedType);
    XmlJavaTypeAdapter typeAdapterInfo = referer != null ? referer.getAnnotation(XmlJavaTypeAdapter.class) : null;
    if (adaptedType instanceof DeclaredType) {
      if (typeAdapterInfo == null) {
        TypeDeclaration typeDeclaration = ((DeclaredType) adaptedType).getDeclaration();
        if (typeDeclaration == null) {
          throw new IllegalStateException("Class not found: " + adaptedType);
        }
        typeAdapterInfo = typeDeclaration.getAnnotation(XmlJavaTypeAdapter.class);
      }

      if ((typeAdapterInfo == null) && (pckg != null)) {
        TypeDeclaration typeDeclaration = ((DeclaredType) adaptedType).getDeclaration();
        if (typeDeclaration == null) {
          throw new IllegalStateException("Class not found: " + adaptedType);
        }
        typeAdapterInfo = getAdaptersOfPackage(pckg).get(typeDeclaration.getQualifiedName());
      }
    }

    if (typeAdapterInfo != null) {
      ClassType adapterTypeMirror;

      try {
        Class adaptedClass = typeAdapterInfo.value();
        AnnotationProcessorEnvironment ape = Context.getCurrentEnvironment();
        adapterTypeMirror = (ClassType) ape.getTypeUtils().getDeclaredType(ape.getTypeDeclaration(adaptedClass.getName()));
      }
      catch (MirroredTypeException e) {
        adapterTypeMirror = (ClassType) e.getTypeMirror();
      }

      AdapterType adapterType = new AdapterType(adapterTypeMirror);
      if ((adaptedType instanceof DeclaredType && adapterType.canAdapt((DeclaredType)adaptedType)) ||
          (unwrappedAdaptedType != adaptedType && unwrappedAdaptedType instanceof ReferenceType && adapterType.canAdapt((ReferenceType) unwrappedAdaptedType))) {
        return adapterType;
      }

      throw new ValidationException(referer.getPosition(), referer.getSimpleName() + ": adapter " + adapterTypeMirror.getDeclaration().getQualifiedName() + " does not adapt " + unwrappedAdaptedType);
    }

    return null;

  }

  /**
   * Gets the adapters of the specified package.
   *
   * @param pckg the package for which to get the adapters.
   * @return The adapters for the package.
   */
  private static Map<String, XmlJavaTypeAdapter> getAdaptersOfPackage(PackageDeclaration pckg) {
    HashMap<String, XmlJavaTypeAdapter> adaptersOfPackage = ADAPTERS_BY_PACKAGE.get(pckg.getQualifiedName());

    if (adaptersOfPackage == null) {
      adaptersOfPackage = new HashMap<String, XmlJavaTypeAdapter>();
      ADAPTERS_BY_PACKAGE.put(pckg.getQualifiedName(), adaptersOfPackage);

      XmlJavaTypeAdapter javaType = pckg.getAnnotation(XmlJavaTypeAdapter.class);
      XmlJavaTypeAdapters javaTypes = pckg.getAnnotation(XmlJavaTypeAdapters.class);

      if ((javaType != null) || (javaTypes != null)) {
        ArrayList<XmlJavaTypeAdapter> allAdaptedTypes = new ArrayList<XmlJavaTypeAdapter>();
        if (javaType != null) {
          allAdaptedTypes.add(javaType);
        }

        if (javaTypes != null) {
          allAdaptedTypes.addAll(Arrays.asList(javaTypes.value()));
        }

        for (XmlJavaTypeAdapter adaptedTypeInfo : allAdaptedTypes) {
          String typeFqn;

          try {
            Class adaptedClass = adaptedTypeInfo.type();
            if (adaptedClass == XmlJavaTypeAdapter.DEFAULT.class) {
              throw new ValidationException(pckg.getPosition(), "Package " + pckg.getSimpleName() + ": a type must be specified in " + XmlJavaTypeAdapter.class.getName() + " at the package-level.");
            }
            typeFqn = adaptedClass.getName();

          }
          catch (MirroredTypeException e) {
            TypeMirror adaptedType = e.getTypeMirror();
            if (!(adaptedType instanceof DeclaredType)) {
              throw new ValidationException(pckg.getPosition(), "Package " + pckg.getSimpleName() + ": unadaptable type: " + adaptedType);
            }
            TypeDeclaration typeDeclaration = ((DeclaredType) adaptedType).getDeclaration();
            if (typeDeclaration == null) {
              throw new IllegalStateException("Class not found: " + adaptedType);
            }
            typeFqn = typeDeclaration.getQualifiedName();
          }

          adaptersOfPackage.put(typeFqn, adaptedTypeInfo);
        }
      }
    }

    return adaptersOfPackage;
  }

}
TOP

Related Classes of org.codehaus.enunciate.contract.jaxb.adapters.AdapterUtil

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.