Package com.google.code.facebookapi.apt

Source Code of com.google.code.facebookapi.apt.FacebookReturnTypeProcessor5

package com.google.code.facebookapi.apt;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Map;

import com.sun.mirror.apt.AnnotationProcessor;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;
import com.sun.mirror.declaration.AnnotationMirror;
import com.sun.mirror.declaration.AnnotationTypeDeclaration;
import com.sun.mirror.declaration.AnnotationTypeElementDeclaration;
import com.sun.mirror.declaration.AnnotationValue;
import com.sun.mirror.declaration.ClassDeclaration;
import com.sun.mirror.declaration.ConstructorDeclaration;
import com.sun.mirror.declaration.Declaration;
import com.sun.mirror.declaration.MethodDeclaration;
import com.sun.mirror.declaration.Modifier;
import com.sun.mirror.declaration.ParameterDeclaration;
import com.sun.mirror.type.ReferenceType;
import com.sun.mirror.type.TypeMirror;
import com.sun.mirror.util.SimpleDeclarationVisitor;

@SuppressWarnings("restriction")
public class FacebookReturnTypeProcessor5 implements AnnotationProcessor {

  private AnnotationProcessorEnvironment processingEnv;

  public FacebookReturnTypeProcessor5( AnnotationProcessorEnvironment processingEnv ) {
    this.processingEnv = processingEnv;
  }



  public static class CopyConstructorVisitor extends SimpleDeclarationVisitor {

    private String clientType;
    private PrintWriter out;

    public CopyConstructorVisitor( String clientType, PrintWriter out ) {
      this.clientType = clientType;
      this.out = out;
    }

    @Override
    public void visitConstructorDeclaration( ConstructorDeclaration e ) {
      out.print( "    " );
      out.print( modifiers( e ) );
      out.print( " " );
      out.print( "Facebook" );
      out.print( clientType );
      out.print( "RestClient" );
      out.print( "( " );
      out.print( parametersIncludingTypes( e ) );
      out.print( " ) " );
      out.print( throwClause( e ) );
      out.println( " {" );
      out.print( "        super( " );
      out.print( parametersExcludingTypes( e ) );
      out.println( " );" );
      out.println( "    }" );
      out.println();
    }

  }

  private static CharSequence modifiers( ConstructorDeclaration e ) {
    StringBuilder modifiers = new StringBuilder();
    Collection<Modifier> modifierSet = e.getModifiers();
    boolean isFirstModifier = true;
    for ( Modifier m : modifierSet ) {
      if ( !isFirstModifier ) {
        modifiers.append( " " );
      }
      modifiers.append( m.toString() );
    }

    return modifiers;
  }

  private static CharSequence throwClause( ConstructorDeclaration e ) {
    StringBuilder throwClause = new StringBuilder();
    Collection<ReferenceType> thrownTypes = e.getThrownTypes();
    boolean isFirstThrows = true;
    for ( TypeMirror t : thrownTypes ) {
      if ( isFirstThrows ) {
        throwClause.append( "throws " );
      } else {
        throwClause.append( ", " );
      }
      throwClause.append( t.toString() );
    }

    return throwClause;
  }

  private static CharSequence throwClause( MethodDeclaration e ) {
    StringBuilder throwClause = new StringBuilder();
    Collection<ReferenceType> thrownTypes = e.getThrownTypes();
    boolean isFirstThrows = true;
    for ( TypeMirror t : thrownTypes ) {
      if ( isFirstThrows ) {
        throwClause.append( "throws " );
      } else {
        throwClause.append( ", " );
      }
      throwClause.append( t.toString() );
    }

    return throwClause;
  }

  private static CharSequence parametersIncludingTypes( ConstructorDeclaration e ) {
    StringBuilder methodCode = new StringBuilder();

    boolean isFirstParam = true;
    Collection<ParameterDeclaration> parameters = e.getParameters();
    for ( ParameterDeclaration param : parameters ) {
      if ( !isFirstParam ) {
        methodCode.append( ", " );
      }
      TypeMirror paramType = param.getType();

      methodCode.append( paramType.toString() );
      methodCode.append( " " );
      String paramName = param.toString();
      // For some reason, the name is "int myVar" if it's a primative type
      // Get rid of the "int" bit.
      if ( paramName.contains( " " ) ) {
        paramName = paramName.substring( paramName.indexOf( ' ' ) + 1 );
      }
      methodCode.append( paramName );

      isFirstParam = false;
    }

    return methodCode;
  }

  private static CharSequence parametersIncludingTypes( MethodDeclaration e ) {
    StringBuilder methodCode = new StringBuilder();

    boolean isFirstParam = true;
    Collection<ParameterDeclaration> parameters = e.getParameters();
    for ( ParameterDeclaration param : parameters ) {
      if ( !isFirstParam ) {
        methodCode.append( ", " );
      }
      TypeMirror paramType = param.getType();

      methodCode.append( paramType.toString() );
      methodCode.append( " " );
      String paramName = param.toString();
      // For some reason, the name is "int myVar" if it's a primative type
      // Get rid of the "int" bit.
      if ( paramName.contains( " " ) ) {
        paramName = paramName.substring( paramName.indexOf( ' ' ) + 1 );
      }
      methodCode.append( paramName );

      isFirstParam = false;
    }

    return methodCode;
  }

  private static CharSequence parametersExcludingTypes( ConstructorDeclaration e ) {
    StringBuilder paramListCode = new StringBuilder();

    boolean isFirstParam = true;
    Collection<ParameterDeclaration> parameters = e.getParameters();
    for ( ParameterDeclaration param : parameters ) {
      if ( !isFirstParam ) {
        paramListCode.append( ", " );
      }

      String paramName = param.toString();
      // For some reason, the name is "int myVar" if it's a primative type
      // Get rid of the "int" bit.
      if ( paramName.contains( " " ) ) {
        paramName = paramName.substring( paramName.indexOf( ' ' ) + 1 );
      }
      paramListCode.append( paramName );

      isFirstParam = false;
    }

    return paramListCode;
  }

  private static CharSequence parametersExcludingTypes( MethodDeclaration e ) {
    StringBuilder paramListCode = new StringBuilder();

    boolean isFirstParam = true;
    Collection<ParameterDeclaration> parameters = e.getParameters();
    for ( ParameterDeclaration param : parameters ) {
      if ( !isFirstParam ) {
        paramListCode.append( ", " );
      }

      String paramName = param.toString();
      // For some reason, the name is "int myVar" if it's a primative type
      // Get rid of the "int" bit.
      if ( paramName.contains( " " ) ) {
        paramName = paramName.substring( paramName.indexOf( ' ' ) + 1 );
      }
      paramListCode.append( paramName );

      isFirstParam = false;
    }

    return paramListCode;
  }

  public void process() {
    PrintWriter outJAXB = openClassFile( "Jaxb" );
    PrintWriter outJSON = openClassFile( "Json" );
    PrintWriter outXML = openClassFile( "Xml" );

    if ( outJAXB == null && outJSON == null && outXML == null ) {
      return;
    }

    final AnnotationTypeDeclaration annotationType = (AnnotationTypeDeclaration) processingEnv.getTypeDeclaration( "com.google.code.facebookapi.FacebookReturnType" );
    Collection<Declaration> elements = processingEnv.getDeclarationsAnnotatedWith( annotationType );

    AnnotationVisitor visitor = new AnnotationVisitor( outJAXB, outJSON, outXML );
    for ( Declaration element : elements ) {
      element.accept( visitor );
    }

    closeClassFile( outJAXB );
    closeClassFile( outJSON );
    closeClassFile( outXML );
  }

  private PrintWriter openClassFile( String type ) {
    final String codepackage = "com.google.code.facebookapi";
    final String mainClassName = "Facebook" + type + "RestClient";
    final String baseClassName = mainClassName + "Base";
    final String mainClass = codepackage + "." + mainClassName;
    final String baseClass = codepackage + "." + baseClassName;
    try {
      PrintWriter out = processingEnv.getFiler().createSourceFile( mainClass );
      out.println( String.format( "package %s;", codepackage ) );
      out.println();
      if ( type.equals( "Jaxb" ) ) {
        out.println( "@SuppressWarnings(\"unchecked\")" );
      }
      out.println( String.format( "public class %s extends %s {", mainClassName, baseClassName ) );
      out.println();
      CopyConstructorVisitor copyConstructors = new CopyConstructorVisitor( type, out );
      ClassDeclaration clientBase = (ClassDeclaration) processingEnv.getTypeDeclaration( baseClass );
      for ( ConstructorDeclaration cd : clientBase.getConstructors() ) {
        cd.accept( copyConstructors );
      }
      return out;
    }
    catch ( IOException ex ) {
      System.err.println( "Ignoring IOException during: " + type + "; " + ex );
      return null;
    }
  }

  private void closeClassFile( PrintWriter out ) {
    if ( out == null ) {
      return;
    }
    out.println( "}" );
    out.flush();
    out.close();
  }



  public static class AnnotationVisitor extends SimpleDeclarationVisitor {

    private PrintWriter outJAXB;
    private PrintWriter outJSON;
    private PrintWriter outXML;

    public AnnotationVisitor( PrintWriter outJAXB, PrintWriter outJSON, PrintWriter outXML ) {
      this.outJAXB = outJAXB;
      this.outJSON = outJSON;
      this.outXML = outXML;
    }

    /**
     * These two lines are required to ensure that the object tree actually bothers to parse the method parameters. Otherwise they're empty for every method!
     */
    private static void shakeEnclosingElementMethods( MethodDeclaration e ) {
      e.getDeclaringType().getMethods();
    }

    @Override
    public void visitMethodDeclaration( MethodDeclaration e ) {
      shakeEnclosingElementMethods( e );

      // Get JAXB and JSON return types - default to Object
      String jaxbReturnType = "Object";
      String jsonReturnType = "Object";
      String xmlReturnType = "org.w3c.dom.Document";

      Collection<AnnotationMirror> annotations = e.getAnnotationMirrors();
      AnnotationMirror firstAnnotation = annotations.iterator().next();
      Map<AnnotationTypeElementDeclaration,AnnotationValue> annotationParams = firstAnnotation.getElementValues();
      boolean jaxbAlreadySet = false;
      for ( AnnotationTypeElementDeclaration key : annotationParams.keySet() ) {
        String name = key.getSimpleName();
        String val = annotationParams.get( key ).toString();
        if ( name.contentEquals( "JAXBList" ) ) {
          if ( annotationParams.get( key ) != null ) {
            jaxbReturnType = "java.util.List<" + stripDotClass( val ) + ">";
            jaxbAlreadySet = true;
          }
        } else if ( !jaxbAlreadySet && name.contentEquals( "JAXB" ) ) {
          if ( annotationParams.get( key ) != null ) {
            jaxbReturnType = stripDotClass( val );
          }
        } else if ( name.contentEquals( "JSON" ) ) {
          if ( annotationParams.get( key ) != null ) {
            jsonReturnType = stripDotClass( val );
          }
        }
      }

      boolean deprecated = e.getAnnotation( Deprecated.class ) != null;

      String methName = e.getSimpleName();

      String methSig = "    public %s %s( %s ) %s {";
      methSig = String.format( methSig, "%RETURNTYPE%", methName, parametersIncludingTypes( e ), throwClause( e ) );

      String methCall = "        Object rawResponse = client.%s( %s );";
      methCall = String.format( methCall, methName, parametersExcludingTypes( e ) );

      String methRet = "        return (%s)parseCallResult( rawResponse );";
      methRet = String.format( methRet, "%RETURNTYPE%" );

      String methRet2 = "        return parseCallResult( %s.class, rawResponse );";
      methRet2 = String.format( methRet2, "%RETURNTYPE%" );

      printMethod( outJAXB, jaxbReturnType, deprecated, methSig, methCall, methRet );
      printMethod( outJSON, jsonReturnType, deprecated, methSig, methCall, methRet2 );
      printMethod( outXML, xmlReturnType, deprecated, methSig, methCall, methRet );
    }

    public static void printMethod( PrintWriter out, String returnType, boolean deprecated, String methSig, String methCall, String methRet ) {
      if ( out == null ) {
        return;
      }
      if ( deprecated ) {
        out.println( "    @Deprecated" );
      }
      out.println( methSig.replace( "%RETURNTYPE%", returnType ) );
      out.println( methCall );
      out.println( methRet.replace( "%RETURNTYPE%", returnType ) );
      out.println( "    }" );
      out.println();
    }

    public static String stripDotClass( String input ) {
      if ( !input.endsWith( ".class" ) ) {
        return input;
      } else {
        return input.substring( 0, input.length() - 6 );
      }
    }

  }

}
TOP

Related Classes of com.google.code.facebookapi.apt.FacebookReturnTypeProcessor5

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.