Package org.apache.beehive.netui.compiler.genmodel

Source Code of org.apache.beehive.netui.compiler.genmodel.GenValidationModel

/*
* Copyright 2004 The Apache Software Foundation.
*
* 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.
*
* $Header:$
*/
package org.apache.beehive.netui.compiler.genmodel;

import org.apache.beehive.netui.compiler.CompilerUtils;
import org.apache.beehive.netui.compiler.JpfLanguageConstants;
import org.apache.beehive.netui.compiler.MergedControllerAnnotation;
import org.apache.beehive.netui.compiler.FatalCompileTimeException;
import org.apache.beehive.netui.compiler.model.FormBeanModel;
import org.apache.beehive.netui.compiler.model.XmlModelWriterException;
import org.apache.beehive.netui.compiler.model.validation.ValidationModel;
import org.apache.beehive.netui.compiler.model.validation.ValidatorConstants;
import org.apache.beehive.netui.compiler.model.validation.ValidatorRule;
import org.apache.beehive.netui.compiler.typesystem.declaration.AnnotationInstance;
import org.apache.beehive.netui.compiler.typesystem.declaration.AnnotationValue;
import org.apache.beehive.netui.compiler.typesystem.declaration.ClassDeclaration;
import org.apache.beehive.netui.compiler.typesystem.declaration.MethodDeclaration;
import org.apache.beehive.netui.compiler.typesystem.declaration.Modifier;
import org.apache.beehive.netui.compiler.typesystem.declaration.TypeDeclaration;
import org.apache.beehive.netui.compiler.typesystem.declaration.ParameterDeclaration;
import org.apache.beehive.netui.compiler.typesystem.type.DeclaredType;
import org.apache.beehive.netui.compiler.typesystem.type.TypeInstance;
import org.apache.beehive.netui.compiler.typesystem.type.ClassType;
import org.apache.beehive.netui.compiler.typesystem.env.AnnotationProcessorEnvironment;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ArrayList;

public class GenValidationModel
        extends ValidationModel
        implements JpfLanguageConstants, ValidatorConstants
{
    private static final String STRUTS_VALIDATION_PREFIX = "validation";
    private static final ValidatorRuleFactory VALIDATOR_RULE_FACTORY = new DefaultValidatorRuleFactory();
   
    private GenStrutsApp _strutsApp;
    private File _mergeFile;
    private AnnotationProcessorEnvironment _env;


    public GenValidationModel( ClassDeclaration jclass, GenStrutsApp strutsApp, AnnotationProcessorEnvironment env )
            throws FatalCompileTimeException
    {
        MergedControllerAnnotation mca = strutsApp.getFlowControllerInfo().getMergedControllerAnnotation();
        _strutsApp = strutsApp;
        setValidatorVersion( mca.getValidatorVersion() );
        addRulesFromBeans( jclass );
        addRulesFromActions( jclass, mca );
        addRulesFromClass( mca );
        String mergeFileName = mca.getValidatorMerge();
        _mergeFile = strutsApp.getMergeFile( mergeFileName );
        _env = env;
    }
   
    private void addRulesFromBeans( ClassDeclaration jclass )
    {
        //
        // Read validation rules from public static inner classes (beans).
        //
        Collection innerTypes = CompilerUtils.getClassNestedTypes( jclass );
       
        for ( Iterator ii = innerTypes.iterator(); ii.hasNext();
        {
            TypeDeclaration innerType = ( TypeDeclaration ) ii.next();
            if ( innerType instanceof ClassDeclaration
                 && innerType.hasModifier( Modifier.PUBLIC )
                 && innerType.hasModifier( Modifier.STATIC ) )
            {
                addRulesFromBeanClass( ( ClassDeclaration ) innerType );
            }
        }
    }
   
    private void addRulesFromBeanClass( ClassDeclaration beanClass )
    {
        Collection properties = CompilerUtils.getBeanProperties( beanClass, true );
       
        for ( Iterator ii = properties.iterator(); ii.hasNext();
        {
            CompilerUtils.BeanPropertyDeclaration property = ( CompilerUtils.BeanPropertyDeclaration ) ii.next();
            MethodDeclaration getter = property.getGetter();
            String propertyName = property.getPropertyName();
           
            if ( getter != null )
            {
                //
                // Parse validation annotations on each getter.
                //
                AnnotationInstance[] annotations = getter.getAnnotationInstances();
               
                if ( annotations != null )
                {
                    List formNames = getFormBeanNames( beanClass );
                   
                    for ( Iterator j = formNames.iterator(); j.hasNext(); )
                    {
                        String formName = ( String ) j.next();
                       
                        for ( int i = 0; i < annotations.length; i++ )
                        {
                            AnnotationInstance ann = annotations[i];
                           
                            if ( CompilerUtils.isJpfAnnotation( ann, VALIDATABLE_PROPERTY_TAG_NAME ) )
                            {
                                //
                                // Add field rules from the Jpf.ValidationLocaleRules annotation.
                                //
                                addRulesFromAnnotation( ann, formName, propertyName );
                            }
                        }
                    }
                }
            }
        }
    }
   
   
    private void addRulesFromAnnotation( AnnotationInstance validationFieldAnn, String entityName, String propertyName )
    {
        //
        // Add rules from the FieldValidationRules annotations in the "localeRules" member.
        //
        Collection localeRulesAnnotations =
                CompilerUtils.getAnnotationArray( validationFieldAnn, LOCALE_RULES_ATTR, false );
        String displayName = CompilerUtils.getString( validationFieldAnn, DISPLAY_NAME_ATTR, true );
        String displayNameKey = CompilerUtils.getString( validationFieldAnn, DISPLAY_NAME_KEY_ATTR, true );
        RuleInfo ruleInfo = new RuleInfo( entityName, propertyName, displayName, displayNameKey );
               
       
        for ( Iterator ii = localeRulesAnnotations.iterator(); ii.hasNext();
        {
            AnnotationInstance ann = ( AnnotationInstance ) ii.next();
            addFieldRules( ann, ruleInfo, false );
        }
       
        addFieldRules( validationFieldAnn, ruleInfo, true );
    }
   
    private void addRulesFromActions( ClassDeclaration jclass, MergedControllerAnnotation mca )
    {
        MethodDeclaration[] methods = CompilerUtils.getClassMethods( jclass, ACTION_TAG_NAME );
       
        for ( int i = 0; i < methods.length; i++ )
        {
            MethodDeclaration method = methods[i];
            AnnotationInstance actionAnnotation = CompilerUtils.getAnnotation( method, ACTION_TAG_NAME );
            assert actionAnnotation != null;
            addRulesFromActionAnnotation( actionAnnotation, method.getSimpleName() );
           
            ParameterDeclaration[] parameters = method.getParameters();
            if ( parameters.length > 0 )
            {
                TypeInstance type = parameters[0].getType();
               
                if ( type instanceof ClassType )
                {
                    ClassDeclaration classDecl = ( ( ClassType ) type ).getClassTypeDeclaration();
                    if ( classDecl.getDeclaringType() == null ) addRulesFromBeanClass( classDecl );
                }
            }
        }
       
       
        Collection simpleActions = mca.getSimpleActions();
       
        if ( simpleActions != null )
        {
            for ( Iterator ii = simpleActions.iterator(); ii.hasNext();
            {
                AnnotationInstance simpleAction = ( AnnotationInstance ) ii.next();
                String actionName = CompilerUtils.getString( simpleAction, NAME_ATTR, true );
                assert actionName != null//checker should enforce this.
                addRulesFromActionAnnotation( simpleAction, actionName );
            }
        }
    }
   
    private void addRulesFromActionAnnotation( AnnotationInstance actionAnnotation, String actionName )
    {
        Collection validatablePropertyAnnotations =
                CompilerUtils.getAnnotationArray( actionAnnotation, VALIDATABLE_PROPERTIES_ATTR, false );
       
        for ( Iterator ii = validatablePropertyAnnotations.iterator(); ii.hasNext();
        {
            AnnotationInstance validationFieldAnnotation = ( AnnotationInstance ) ii.next();
            String propertyName = CompilerUtils.getString( validationFieldAnnotation, PROPERTY_NAME_ATTR, true );
            assert propertyName != null;            // TODO: checker must enforce this
            assert ! propertyName.equals( "" );     // TODO: checker must enforce this
           
            //
            // Add the rules, and associate them with the action path ("/" + the action name).
            //
            String actionPath = '/' + actionName;   // Struts validator needs the slash in front
            addRulesFromAnnotation( validationFieldAnnotation, actionPath, propertyName );
        }
    }
   
    /**
     * Returns a list of String names.
     */
    private List getFormBeanNames( TypeDeclaration beanType )
    {
        String actualType = CompilerUtils.getLoadableName( beanType );
        List formBeans = _strutsApp.getFormBeansByActualType( actualType, null );
        ArrayList formBeanNames = new ArrayList();

        if ( formBeans == null )
        {
            String beanClassName = CompilerUtils.getFormClassName( beanType, _strutsApp.getEnv() );
            String formName = _strutsApp.getFormNameForType( actualType, false );
            FormBeanModel formBean = new FormBeanModel( formName, beanClassName, actualType, false, _strutsApp );
            _strutsApp.addFormBean( formBean );
            formBeanNames.add( formBean.getName() );
        }
        else
        {
            for ( Iterator i = formBeans.iterator(); i.hasNext(); )
            {
                FormBeanModel formBeanModel = ( FormBeanModel ) i.next();
                formBeanNames.add( formBeanModel.getName() );
            }
        }

        return formBeanNames;
    }
   
    private void addRulesFromClass( MergedControllerAnnotation mca )
    {
        Collection validationBeanAnnotations = mca.getValidatableBeans();
       
        for ( Iterator ii = validationBeanAnnotations.iterator(); ii.hasNext();
        {
            AnnotationInstance validationBeanAnnotation = ( AnnotationInstance ) ii.next();
            DeclaredType beanType = CompilerUtils.getDeclaredType( validationBeanAnnotation, TYPE_ATTR, true );
            assert beanType != null;    // checker should enforce this
           
            Collection validationFieldAnnotations =
                    CompilerUtils.getAnnotationArray( validationBeanAnnotation, VALIDATABLE_PROPERTIES_ATTR, false );
           
            for ( Iterator i2 = validationFieldAnnotations.iterator(); i2.hasNext();
            {
                AnnotationInstance validationFieldAnnotation = ( AnnotationInstance ) i2.next();
                String propName = CompilerUtils.getString( validationFieldAnnotation, PROPERTY_NAME_ATTR, true );
                assert propName != null;            // checker should enforce this
                assert ! propName.equals( "" );     // TODO: get checker to enforce this
               
                //
                // Add the rules.  If the bean is derived from ActionForm, associate the rules with the *name* of
                // the form; otherwise, associate them with the classname of the bean type.
                //
                List formNames = getFormBeanNames( CompilerUtils.getDeclaration( beanType ) );
               
                for ( Iterator j = formNames.iterator(); j.hasNext(); )
                {
                    String formName = ( String ) j.next();
                    addRulesFromAnnotation( validationFieldAnnotation, formName, propName );
                }
            }
        }
    }
   
    /**
     * Add field rules from either a Jpf.ValidationField or a Jpf.ValidationLocaleRules annotation.
     */
    private void addFieldRules( AnnotationInstance rulesContainerAnnotation, RuleInfo ruleInfo,
                                boolean applyToAllLocales )
    {
        //
        // First parse the locale from the wrapper annotation.  This will apply to all rules inside.
        //
        Locale locale = null;
       
        if ( ! applyToAllLocales )
        {
            String language = CompilerUtils.getString( rulesContainerAnnotation, LANGUAGE_ATTR, true );
           
            //
            // If there's no language specified, then this rule will only apply for the default ruleset
            // (i.e., if there are explicit rules for the requested locale, this rule will not be run).
            //
            if ( language != null )
            {
                String country = CompilerUtils.getString( rulesContainerAnnotation, COUNTRY_ATTR, true );
                String variant = CompilerUtils.getString( rulesContainerAnnotation, VARIANT_ATTR, true );
               
                language = language.trim();
                if ( country != null ) country = country.trim();
                if ( variant != null ) variant = variant.trim();

                if ( country != null && variant != null ) locale = new Locale( language, country, variant );
                else if ( country != null ) locale = new Locale( language, country );
                else locale = new Locale( language );
            }
        }
       
        Map valuesPresent = rulesContainerAnnotation.getElementValues();
       
        for ( Iterator ii = valuesPresent.entrySet().iterator(); ii.hasNext();
        {
            Map.Entry entry = ( Map.Entry ) ii.next();
            AnnotationValue value = ( AnnotationValue ) entry.getValue();
            Object val = value.getValue();
           
            if ( val instanceof AnnotationInstance )
            {
                addFieldRuleFromAnnotation( ruleInfo, ( AnnotationInstance ) val, locale, applyToAllLocales );
            }
            else if ( val instanceof List )
            {
                List annotations = CompilerUtils.getAnnotationArray( value );
               
                for ( Iterator i3 = annotations.iterator(); i3.hasNext();
                {
                    AnnotationInstance i = ( AnnotationInstance ) i3.next();
                    addFieldRuleFromAnnotation( ruleInfo, i, locale, applyToAllLocales );
                }
            }
        }
       
        setEmpty( false )// this ValidationModel is only "empty" if there are no rules.
    }
   
    private void addFieldRuleFromAnnotation( RuleInfo ruleInfo, AnnotationInstance annotation, Locale locale,
                                             boolean applyToAllLocales )
    {
       
        ValidatorRule rule = getFieldRule( ruleInfo.getEntityName(), ruleInfo.getFieldName(), annotation );
       
        if ( rule != null )
        {
            if ( applyToAllLocales )
            {
                addFieldRuleForAllLocales( ruleInfo, rule );
            }
            else
            {
                addFieldRule( ruleInfo, rule, locale );
            }
        }
    }
   
    private static ValidatorRule getFieldRule( String entityName, String propertyName, AnnotationInstance ruleAnnotation )
    {
        ValidatorRule rule = VALIDATOR_RULE_FACTORY.getFieldRule( entityName, propertyName, ruleAnnotation );
       
        if ( rule != null )
        {
            //
            // message/message-key
            //
            rule.setMessage( CompilerUtils.getString( ruleAnnotation, MESSAGE_ATTR, true ) );
            rule.setMessageKey( CompilerUtils.getString( ruleAnnotation, MESSAGE_KEY_ATTR, true ) );
            rule.setBundle( CompilerUtils.getString( ruleAnnotation, BUNDLE_NAME_ATTR, true ) );
            if ( rule.getMessage() != null ) assert rule.getMessageKey() == null;   // TODO: checker should enforce
           
            //
            // args
            //
            addMessageArgs( rule, ruleAnnotation );
        }
       
        return rule;
    }

    protected static void addMessageArgs( ValidatorRule rule, AnnotationInstance annotation )
    {
        List messageArgs =
                CompilerUtils.getAnnotationArray( annotation, MESSAGE_ARGS_ATTR, true );

        if ( messageArgs != null )
        {
            int inferredPosition = 0;
            for ( Iterator ii = messageArgs.iterator(); ii.hasNext();
            {
                AnnotationInstance ann = ( AnnotationInstance ) ii.next();
                String arg = CompilerUtils.getString( ann, ARG_ATTR, true );
                String bundle = CompilerUtils.getString( ann, BUNDLE_NAME_ATTR, true );
                Integer position = CompilerUtils.getInteger( ann, POSITION_ATTR, true );

                if ( position == null )
                {
                    position = new Integer( inferredPosition );
                }

                if ( arg != null )
                {
                    rule.setArg( arg, false, bundle, position );
                }
                else
                {
                    String argKey = CompilerUtils.getString( ann, ARG_KEY_ATTR, true );
                    if ( argKey != null ) rule.setArg( argKey, true, bundle, position );
                }

                inferredPosition++;
            }
        }
    }

    protected String getHeaderComment( File mergeFile )
            throws FatalCompileTimeException
    {
        return _strutsApp.getHeaderComment( mergeFile );
    }

    public void writeToFile()
        throws FileNotFoundException, IOException, FatalCompileTimeException, XmlModelWriterException
    {
        String outputFilePath = getOutputFileURI();
        File outputFile = new File( outputFilePath );
        PrintWriter writer = _env.getFiler().createTextFile( outputFile );
        try
        {
            writeXml( writer, _mergeFile );
        }
        finally
        {
            writer.close();
        }
    }

    public String getOutputFileURI()
    {
        return _strutsApp.getOutputFileURI( _strutsApp.getValidationFilePrefix() );
    }
}
TOP

Related Classes of org.apache.beehive.netui.compiler.genmodel.GenValidationModel

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.