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

com.sun.jsftemplating.annotation.HandlerAP Maven / Gradle / Ivy

/*
 * The contents of this file are subject to the terms 
 * of the Common Development and Distribution License 
 * (the License).  You may not use this file except in
 * compliance with the License.
 * 
 * You can obtain a copy of the license at 
 * https://jsftemplating.dev.java.net/cddl1.html or
 * jsftemplating/cddl1.txt.
 * See the License for the specific language governing 
 * permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL 
 * Header Notice in each file and include the License file 
 * at jsftemplating/cddl1.txt.  
 * If applicable, add the following below the CDDL Header, 
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information: 
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 */
package com.sun.jsftemplating.annotation;

import java.io.PrintWriter;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

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.Declaration;
import com.sun.mirror.declaration.MemberDeclaration;
import com.sun.mirror.declaration.MethodDeclaration;
import com.sun.mirror.declaration.Modifier;
import com.sun.mirror.declaration.ParameterDeclaration;


/**
 *  

This is an AnnotationProcessor for * {@link Handler} annotations.

* * @author Ken Paulsen ([email protected]) */ public class HandlerAP implements AnnotationProcessor { /** *

This is the constructor for the {@link Handler} * AnnotationProcessor. It expects the annotation to * have a single value (called 'value', or have 'value' omitted) which * specifies the identifier used to locate the class containing the * annotation (the * {@link com.sun.jsftemplating.component.factory.ComponentFactory} * class).

* * @param env The AnnotationProcessorEnvironment. * @param writer The PrintWriter used for output. */ public HandlerAP(AnnotationProcessorEnvironment env, PrintWriter writer) { _writer = writer; _env = env; } /** *

This method will process the annotation. It produces a line using * the PrintWriter that contains the identifer and the * class name which holds the annotation:

* *

[identifer]=[class name]

*/ public void process() { // Temporary Variables String key; Object value; String id; List input; List output; // Get the supported annotation type (only 1) AnnotationTypeDeclaration decl = (AnnotationTypeDeclaration) _env.getTypeDeclaration(Handler.class.getName()); // Loop through the declarations that are annotated for (Declaration dec : _env.getDeclarationsAnnotatedWith(decl)) { // Loop through the annotations on the current declartion for (AnnotationMirror mirror : dec.getAnnotationMirrors()) { // Loop through the NVPs contained in the annotation id = null; input = null; output = null; for (Map.Entry entry : mirror.getElementValues().entrySet()) { // At this point I'm processing a "Handler" annotation // it may contain "id", "input", "output" key = entry.getKey().getSimpleName(); value = entry.getValue().getValue(); if (key.equals(Handler.ID)) { // Found 'id', save it id = value.toString(); } else if (key.equals(Handler.INPUT)) { // Found inputs input = (List) value; } else if (key.equals(Handler.OUTPUT)) { // Found outputs output = (List) value; } } // Sanity Check if (id == null) { _env.getMessager().printError( dec.getPosition(), "'id' not specified for annotation of method: '" + ((MemberDeclaration) dec).getDeclaringType(). getQualifiedName() + "." + dec.getSimpleName() + "'."); } // Check for duplicate handler definitions if (handlers.get(id) != null) { _env.getMessager().printWarning( dec.getPosition(), "Handler with 'id' of '" + id + "' is declared more than once!'"); } handlers.put(id, id); // Record class / method names (and javadoc comment) _writer.println(formatComment(dec.getDocComment())); _writer.println(id + ".class=" + ((MemberDeclaration) dec).getDeclaringType(). getQualifiedName()); _writer.println(id + ".method=" + dec.getSimpleName()); // Now record inputs for this handler... if (input != null) { writeIOProperties(id, "input", input); } // Now record outputs for this handler... if (output != null) { writeIOProperties(id, "output", output); } // Method signature checks... // Make sure method is accessible (public) if (!dec.getModifiers().contains(Modifier.PUBLIC)) { _env.getMessager().printError( dec.getPosition(), "Annotated method: '" + ((MemberDeclaration) dec).getDeclaringType(). getQualifiedName() + "." + dec.getSimpleName() + "' should be declared public."); } // Make sure correct args are specified Collection params = ((MethodDeclaration) dec).getParameters(); String pdec = params.iterator().next().getType().toString(); if ((params.size() != 1) || !pdec.equals( "com.sun.jsftemplating.layout.descriptors.handler.HandlerContext")) { _env.getMessager().printError( dec.getPosition(), "Annotated method: '" + ((MemberDeclaration) dec).getDeclaringType(). getQualifiedName() + "." + dec.getSimpleName() + "' must contain a single parameter of type 'com." + "sun.jsftemplating.layout.descriptors.handler." + "HandlerContext', instead type: '" + pdec + "' was found."); } // FIXME: Consider an alternate method declaration that annotates a pojo method // @Handler(id="foo") // public String method(String a, String b, String c) // annotates a handler "foo" with 3 inputs (a:String, b:String, c:String) and 1 output "result:String" // Will need a special way to invoke this. } } } /** *

This is a helper method that writes out property lines to represent * either a HandlerInput or a HandlerOutput. The type * that is passed in is expected to be either input or * output.

*/ private void writeIOProperties(String id, String type, List ioList) { int cnt = 0; for (AnnotationValue ioVal : ioList) { // Process each @HandlerInput annotation... for (Map.Entry prop : ((AnnotationMirror) ioVal.getValue()).getElementValues().entrySet()) { // Look at each "param": @Handlerput(param=) _writer.println(id + "." + type + "[" + cnt + "]." + prop.getKey().getSimpleName() + "=" + convertClassName(prop.getValue().getValue().toString())); } cnt++; } } /** *

This method attempts to convert the given clsName to * a valid class name. The issue is that arrays appear something like * "java.lang.String[]" where they should appear * "[Ljava.lang.String;".

*/ private String convertClassName(String str) { int idx = str.indexOf("[]"); if (idx == -1) { // For not only worry about Strings that contain array brackets return str; } // Count []'s int count = 0; while (idx != -1) { str = str.replaceFirst("\\[]", ""); idx = str.indexOf("[]"); count++; } // Generate new String String brackets = ""; for (idx = 0; idx This method strips off HTML tags, converts "<" and ">", * inserts '#' characters in front of each line, and ensures there * are no trailing returns.

*/ private String formatComment(String javadoc) { if (javadoc == null) { // No JavaDoc, return return ""; } // First trim off extra stuff int idx = javadoc.indexOf("@param"); if (idx > -1) { // Ignore @param stuff javadoc = javadoc.substring(0, idx); } javadoc = javadoc.trim(); // Now process the String StringBuffer buf = new StringBuffer("\n# "); int len = javadoc.length(); char ch; idx = 0; while (idx < len) { ch = javadoc.charAt(idx); switch (ch) { case '&': if ((idx + 3) < len) { if ((javadoc.charAt(idx + 2) == 't') && (javadoc.charAt(idx + 3) == ';')) { if (javadoc.charAt(idx + 1) == 'g') { buf.append('>'); idx += 3; } else if (javadoc.charAt(idx + 1) == 'l') { buf.append('<'); idx += 3; } } } break; case '<' : idx++; while ((idx < len) && (javadoc.charAt(idx) != '>')) { idx++; } break; case '>' : idx++; while ((idx < len) && (javadoc.charAt(idx) != '<')) { idx++; } break; case '\n': case '\r': if (((idx + 1) > len) && ((javadoc.charAt(idx + 1) == '\n') || (javadoc.charAt(idx + 1) == '\r'))) { idx++; } buf.append("\n# "); break; default: buf.append(ch); } idx++; } // Return the stripped javadoc return buf.toString(); } private PrintWriter _writer = null; private AnnotationProcessorEnvironment _env = null; private Map handlers = new HashMap(); }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy