You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by mr...@apache.org on 2005/09/14 18:21:05 UTC

svn commit: r280879 [10/16] - in /struts/sandbox/trunk/ti: ./ jars/compiler-apt/ jars/compiler-apt/src/ jars/compiler-apt/src/java/ jars/compiler-apt/src/java/org/ jars/compiler-apt/src/java/org/apache/ jars/compiler-apt/src/java/org/apache/ti/ jars/co...

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/UniqueValueType.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/UniqueValueType.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/UniqueValueType.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/UniqueValueType.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,197 @@
+/*
+ * 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.ti.compiler.internal.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationGrammar;
+import org.apache.ti.compiler.internal.AnnotationMemberType;
+import org.apache.ti.compiler.internal.CompilerUtils;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationTypeElementDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationValue;
+import org.apache.ti.compiler.internal.typesystem.declaration.MemberDeclaration;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+
+public class UniqueValueType
+        extends AnnotationMemberType {
+
+    private boolean _allowEmptyString;
+    private boolean _checkDefaultValues;
+
+    /**
+     * the name of the attribute on the parent annotation that is the list of annotations to check for duplicates
+     */
+    private String _memberGroupName;
+
+
+    public UniqueValueType(String memberGroupName, boolean allowEmptyString, boolean checkDefaultValues,
+                           String requiredRuntimeVersion, AnnotationGrammar parentGrammar) {
+        this(memberGroupName, allowEmptyString, checkDefaultValues, requiredRuntimeVersion, parentGrammar, null);
+    }
+
+    public UniqueValueType(String memberGroupName, boolean allowEmptyString, boolean checkDefaultValues,
+                           String requiredRuntimeVersion, AnnotationGrammar parentGrammar,
+                           AnnotationMemberType nextInChain) {
+        super(requiredRuntimeVersion, parentGrammar, nextInChain);
+
+        _allowEmptyString = allowEmptyString;
+        _memberGroupName = memberGroupName;
+        _checkDefaultValues = checkDefaultValues;
+    }
+
+    /**
+     * @return a result (any Object) that will be passed back to the parent checker.  May be null</code>.
+     */
+
+    public Object onCheck(AnnotationTypeElementDeclaration valueDecl, AnnotationValue value,
+                          AnnotationInstance[] parentAnnotations, MemberDeclaration classMember,
+                          int annotationArrayIndex) {
+        String val = value.getValue().toString();
+
+        if (! _allowEmptyString && val.length() == 0) {
+            addError(value, "error.empty-string-not-allowed");
+            return null;
+        }
+
+        if (parentAnnotations.length < 2) return null;    // invalid parents -- will be caught elsewhere
+        AnnotationInstance parentElement = parentAnnotations[parentAnnotations.length - 2];
+        List memberGroup = CompilerUtils.getAnnotationArray(parentElement, _memberGroupName, true);
+
+        //
+        // If memberGroup is null, then this annotation was in the wrong place, and there will be other errors.
+        //
+        if (memberGroup != null) {
+            String valueName = valueDecl.getSimpleName();
+            AnnotationInstance parentAnnotation = parentAnnotations[parentAnnotations.length - 1];
+            checkForDuplicates(value, valueName, parentAnnotation, classMember, memberGroup, false,
+                    annotationArrayIndex);
+
+            //
+            // Get a list of additional annotations (presumably not from the this one's parent) to check.
+            //
+            List additionalAnnsToCheck = getAdditionalAnnotationsToCheck(classMember);
+
+            if (additionalAnnsToCheck != null) {
+                // Check this value against the list of additional annotations.
+                checkForDuplicates(value, valueName, parentAnnotation, classMember, additionalAnnsToCheck, true, -1);
+
+                // Check for duplicates *within* within the list of additional annotations.
+                for (int i = 0; i < additionalAnnsToCheck.size(); ++i) {
+                    AnnotationInstance ann = (AnnotationInstance) additionalAnnsToCheck.get(i);
+                    AnnotationValue valueToCheck = CompilerUtils.getAnnotationValue(ann, valueName, true);
+                    checkForDuplicates(valueToCheck, valueName, ann, classMember, additionalAnnsToCheck, true, -1);
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Plugin point for derived class -- if there should be no duplicates across another entity too.
+     *
+     * @return a List of AnnotationInstance
+     */
+    protected List getAdditionalAnnotationsToCheck(MemberDeclaration classMember) {
+        return null;
+    }
+
+    protected String getErrorMessageExtraInfo() {
+        return null;
+    }
+
+    protected void checkForDuplicates(AnnotationValue member, String memberName, AnnotationInstance parentAnnotation,
+                                      MemberDeclaration classMember, List annotationsToCheck,
+                                      boolean includeEntityInMsg, int annotationArrayIndex) {
+        Object memberValue = member.getValue();
+
+        for (int i = 0; i < annotationsToCheck.size(); ++i) {
+            AnnotationInstance annotation = (AnnotationInstance) annotationsToCheck.get(i);
+
+            if ((annotationArrayIndex != -1 && annotationArrayIndex != i) ||
+                    ! CompilerUtils.annotationsAreEqual(annotation, parentAnnotation, allowExactDuplicates(), getEnv())) {
+                AnnotationValue valueToCheck =
+                        CompilerUtils.getAnnotationValue(annotation, memberName, _checkDefaultValues);
+
+                if (valueToCheck != null && ! valueToCheck.equals(member)
+                        && valueToCheck.getValue().equals(memberValue)) {
+                    if (alreadyAddedErrorForValue(classMember, parentAnnotation, memberValue, getEnv())) return;
+
+                    String annotationName =
+                            CompilerUtils.getDeclaration(parentAnnotation.getAnnotationType()).getSimpleName();
+
+                    if (includeEntityInMsg) {
+                        String extra = getErrorMessageExtraInfo();
+                        Object[] args = new Object[]
+                                {
+                                        annotationName,
+                                        memberName,
+                                        memberValue,
+                                        classMember.getSimpleName(),
+                                        extra
+                                };
+                        addError(member, "error.duplicate-attr2", args);
+                    } else {
+                        addError(member, "error.duplicate-attr",
+                                new Object[]{annotationName, memberName, memberValue});
+                    }
+
+                    return;
+                }
+            }
+        }
+    }
+
+    static boolean alreadyAddedErrorForValue(MemberDeclaration classMember, AnnotationInstance parentAnn,
+                                             Object memberValue, AnnotationProcessorEnvironment env) {
+        // Map of String class-member-name ->
+        //      [ Map of String annotation name -> Set of values for which errors were added ]
+        HashMap errorsAddedRootMap = (HashMap) env.getAttribute("uniqueValueErrors");
+        if (errorsAddedRootMap == null) {
+            errorsAddedRootMap = new HashMap();
+            env.setAttribute("uniqueValueErrors", errorsAddedRootMap);
+        }
+
+        String classMemberName = classMember.getSimpleName();
+        HashMap errorsAddedByAnnotation = (HashMap) errorsAddedRootMap.get(classMemberName);
+        if (errorsAddedByAnnotation == null) {
+            errorsAddedByAnnotation = new HashMap();
+            errorsAddedRootMap.put(classMemberName, errorsAddedByAnnotation);
+        }
+
+        String parentAnnName = parentAnn.getAnnotationType().getAnnotationTypeDeclaration().getQualifiedName();
+        HashSet errorsAdded = (HashSet) errorsAddedByAnnotation.get(parentAnnName);
+        if (errorsAdded == null) {
+            errorsAdded = new HashSet();
+            errorsAddedByAnnotation.put(parentAnnName, errorsAdded);
+        }
+
+        if (errorsAdded.contains(memberValue)) return true;
+
+        errorsAdded.add(memberValue);
+        return false;
+    }
+
+    protected boolean allowExactDuplicates() {
+        return false;
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidActionType.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidActionType.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidActionType.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidActionType.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,46 @@
+/*
+ * 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.ti.compiler.internal.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationGrammar;
+import org.apache.ti.compiler.internal.FlowControllerInfo;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationTypeElementDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationValue;
+import org.apache.ti.compiler.internal.typesystem.declaration.MemberDeclaration;
+
+public class ValidActionType
+        extends WebappPathOrActionType {
+
+    public ValidActionType(String requiredRuntimeVersion, AnnotationGrammar parentGrammar, FlowControllerInfo fcInfo) {
+        super(false, requiredRuntimeVersion, parentGrammar, fcInfo);
+    }
+
+
+    public Object onCheck(AnnotationTypeElementDeclaration valueDecl, AnnotationValue value,
+                          AnnotationInstance[] parentAnnotations, MemberDeclaration classMember,
+                          int annotationArrayIndex) {
+        String stringValue = (String) value.getValue();
+        checkAction(stringValue + ACTION_EXTENSION_DOT, value, classMember);
+        return null;
+    }
+
+    protected boolean doFatalError() {
+        return true;
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidXmlFileType.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidXmlFileType.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidXmlFileType.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidXmlFileType.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,174 @@
+/*
+ * 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.ti.compiler.internal.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationGrammar;
+import org.apache.ti.compiler.internal.FlowControllerInfo;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationValue;
+import org.apache.xmlbeans.SchemaType;
+import org.apache.xmlbeans.XmlError;
+import org.apache.xmlbeans.XmlException;
+import org.apache.xmlbeans.XmlObject;
+import org.apache.xmlbeans.XmlOptions;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+public class ValidXmlFileType
+        extends WebappPathType {
+
+    private SchemaType _schema;
+    private static Map _parseResults = Collections.synchronizedMap(new HashMap());
+
+    public ValidXmlFileType(SchemaType schema, String requiredRuntimeVersion, AnnotationGrammar parentGrammar,
+                            FlowControllerInfo fcInfo) {
+        super(false, requiredRuntimeVersion, parentGrammar, fcInfo);
+        _schema = schema;
+    }
+
+
+    protected boolean checkAnyExtension() {
+        return true;
+    }
+
+
+    protected boolean doFatalError() {
+        return true;
+    }
+
+
+    protected boolean ignoreDirectories() {
+        return false;
+    }
+
+
+    protected boolean allowFileInPageFlowSourceDir() {
+        return true;
+    }
+
+
+    protected void runAdditionalChecks(File file, AnnotationValue value) {
+        try {
+            //
+            // We cache the results of parsing the file until the file is actually modified,
+            // so we don't end up continually re-parsing it.
+            //
+            ParseResults prevResults = (ParseResults) _parseResults.get(file.getPath());
+
+            if (prevResults == null || file.lastModified() > prevResults.getFileModTime()) {
+                try {
+                    XmlOptions options = new XmlOptions();
+                    options.setDocumentType(_schema);
+                    XmlObject xml = XmlObject.Factory.parse(file, options);
+                    List errorListener = new ArrayList();
+                    options.setErrorListener(errorListener);
+
+                    if (!xml.validate(options)) {
+                        assert !errorListener.isEmpty();
+
+                        XmlError err = (XmlError) errorListener.get(0);
+                        assert err != null;
+
+                        throw new XmlException(err.getMessage(), null, err);
+                    }
+                }
+                catch (Exception e) {
+                    _parseResults.put(file.getPath(), new ParseResults(file.lastModified(), e));
+                    throw e;
+                }
+
+                _parseResults.put(file.getPath(), new ParseResults(file.lastModified(), null));
+            } else {
+                Exception e = prevResults.getException();
+
+                if (e != null) {
+                    throw e;
+                }
+            }
+        }
+        catch (XmlException e) {
+            addErrorDiagnostic(e.getError(), value);
+        }
+        catch (Exception e) {
+            addError(value, "error.xml-read-error", new Object[]{file.getPath(), e.getMessage()});
+        }
+    }
+
+    private void addErrorDiagnostic(XmlError err, AnnotationValue value) {
+        if (err.getColumn() != -1 && err.getLine() != -1) {
+            Object[] args =
+                    {
+                            err.getSourceName(),
+                            new Integer(err.getLine()),
+                            new Integer(err.getColumn()),
+                            err.getMessage()
+                    };
+
+            addError(value, "error.xml-parse-error", args);
+        } else if (err.getLine() != -1) {
+            Object[] args =
+                    {
+                            err.getSourceName(),
+                            new Integer(err.getLine()),
+                            err.getMessage()
+                    };
+
+            addError(value, "error.xml-parse-error-nocolumn", args);
+        } else {
+            Object[] args =
+                    {
+                            err.getSourceName(),
+                            err.getMessage()
+                    };
+
+            addError(value, "error.xml-parse-error-nolinecolumn", args);
+        }
+    }
+
+    private static class ParseResults {
+
+        private long _fileModTime;
+        private Exception _exception;
+
+        public ParseResults(long fileModTime, Exception exception) {
+            _fileModTime = fileModTime;
+            _exception = exception;
+        }
+
+        public long getFileModTime() {
+            return _fileModTime;
+        }
+
+        public void setFileModTime(long fileModTime) {
+            _fileModTime = fileModTime;
+        }
+
+        public Exception getException() {
+            return _exception;
+        }
+
+        public void setException(Exception exception) {
+            _exception = exception;
+        }
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidatableBeanGrammar.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidatableBeanGrammar.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidatableBeanGrammar.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidatableBeanGrammar.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,41 @@
+/*
+ * 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.ti.compiler.internal.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationGrammar;
+import org.apache.ti.compiler.internal.Diagnostics;
+import org.apache.ti.compiler.internal.RuntimeVersionChecker;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+
+public class ValidatableBeanGrammar
+        extends AnnotationGrammar {
+
+    private static final String[][] REQUIRED_ATTRS = {{VALIDATABLE_PROPERTIES_ATTR}, {TYPE_ATTR}};
+
+    public ValidatableBeanGrammar(AnnotationProcessorEnvironment env, Diagnostics diags, RuntimeVersionChecker rvc) {
+        super(env, diags, VERSION_9_0_STRING, rvc);
+
+        addMemberArrayGrammar(VALIDATABLE_PROPERTIES_ATTR, new ValidatablePropertyGrammar(env, diags, rvc));
+        // TYPE_ATTR does not need a custom type
+    }
+
+    public String[][] getRequiredAttrs() {
+        return REQUIRED_ATTRS;
+    }
+}
+

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidatablePropertyGrammar.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidatablePropertyGrammar.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidatablePropertyGrammar.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidatablePropertyGrammar.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,89 @@
+/*
+ * 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.ti.compiler.internal.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationMemberType;
+import org.apache.ti.compiler.internal.CompilerUtils;
+import org.apache.ti.compiler.internal.Diagnostics;
+import org.apache.ti.compiler.internal.FatalCompileTimeException;
+import org.apache.ti.compiler.internal.RuntimeVersionChecker;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+import org.apache.ti.compiler.internal.typesystem.declaration.MemberDeclaration;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+
+
+public class ValidatablePropertyGrammar
+        extends ValidationRulesContainerGrammar {
+
+    private static String[][] REQUIRED_ATTRS = {{PROPERTY_NAME_ATTR}};
+    private static String[][] MUTUALLY_EXCLUSIVE_ATTRS = {{DISPLAY_NAME_ATTR, DISPLAY_NAME_KEY_ATTR}};
+
+
+    public ValidatablePropertyGrammar(AnnotationProcessorEnvironment env, Diagnostics diags, RuntimeVersionChecker rvc) {
+        super(env, diags, rvc);
+
+        addMemberType(PROPERTY_NAME_ATTR, new AnnotationMemberType(null, this));
+        addMemberType(DISPLAY_NAME_ATTR, new AnnotationMemberType(null, this));
+        addMemberType(DISPLAY_NAME_KEY_ATTR, new AnnotationMemberType(null, this));
+        addMemberArrayGrammar(LOCALE_RULES_ATTR, new LocaleRulesGrammar(env, diags, rvc));
+    }
+
+    /**
+     * This is overridable by derived classes, which is why it's not simply defined as required in
+     * {@link org.apache.ti.pageflow.annotations.Jpf}.
+     */
+    public String[][] getRequiredAttrs() {
+        return REQUIRED_ATTRS;
+    }
+
+    public String[][] getMutuallyExclusiveAttrs() {
+        return MUTUALLY_EXCLUSIVE_ATTRS;
+    }
+
+    protected boolean onBeginCheck(AnnotationInstance annotation, AnnotationInstance[] parentAnnotations,
+                                   MemberDeclaration classMember)
+            throws FatalCompileTimeException {
+        if (parentAnnotations == null) return true;
+
+        //
+        // Look through all annotation parents for @Jpf.Action or @Jpf.SimpleAction.  If we find one, and there's
+        // no validationErrorForward on it, print a warning.
+        //
+        for (int i = parentAnnotations.length - 1; i >= 0; --i) {
+            AnnotationInstance ann = parentAnnotations[i];
+
+            if (CompilerUtils.isJpfAnnotation(ann, ACTION_TAG_NAME)
+                    || CompilerUtils.isJpfAnnotation(ann, SIMPLE_ACTION_TAG_NAME)) {
+                //
+                // Give a warning if there is no validationErrorForward annotation and doValidation isn't set to false.
+                //
+                if (CompilerUtils.getAnnotationValue(ann, VALIDATION_ERROR_FORWARD_ATTR, true) == null) {
+                    Boolean doValidation = CompilerUtils.getBoolean(ann, DO_VALIDATION_ATTR, true);
+
+                    if (doValidation == null || doValidation.booleanValue()) {
+                        addWarning(annotation, "warning.validation-annotations-no-forward",
+                                ANNOTATION_INTERFACE_PREFIX + ann.getAnnotationType().getDeclaration().getSimpleName(),
+                                VALIDATION_ERROR_FORWARD_ATTR);
+                    }
+                }
+            }
+        }
+
+        return true;
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateCustomGrammar.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateCustomGrammar.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateCustomGrammar.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateCustomGrammar.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,55 @@
+/*
+ * 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.ti.compiler.internal.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationGrammar;
+import org.apache.ti.compiler.internal.Diagnostics;
+import org.apache.ti.compiler.internal.RuntimeVersionChecker;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+
+public class ValidateCustomGrammar
+        extends BaseValidationRuleGrammar {
+
+    private static final String[][] REQUIRED_ATTRS = {{RULE_ATTR}, {MESSAGE_ATTR, MESSAGE_KEY_ATTR}};
+    private static final String[][] VARIABLE_REQUIRED_ATTRS = {{NAME_ATTR}, {VALUE_ATTR}};
+
+    public ValidateCustomGrammar(AnnotationProcessorEnvironment env, Diagnostics diagnostics,
+                                 RuntimeVersionChecker rvc) {
+        super(env, diagnostics, rvc);
+        addMemberArrayGrammar(VARIABLES_ATTR, new ValidateCustomVariableGrammar());
+    }
+
+    public String[][] getRequiredAttrs() {
+        return REQUIRED_ATTRS;
+    }
+
+    private class ValidateCustomVariableGrammar
+            extends AnnotationGrammar {
+
+        public ValidateCustomVariableGrammar() {
+            super(ValidateCustomGrammar.this.getEnv(), ValidateCustomGrammar.this.getDiagnostics(),
+                    null, ValidateCustomGrammar.this.getRuntimeVersionChecker());
+        }
+
+        public String[][] getRequiredAttrs() {
+            return VARIABLE_REQUIRED_ATTRS;
+        }
+    }
+}
+
+

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateRangeGrammar.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateRangeGrammar.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateRangeGrammar.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateRangeGrammar.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,86 @@
+/*
+ * 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.ti.compiler.internal.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationMemberType;
+import org.apache.ti.compiler.internal.Diagnostics;
+import org.apache.ti.compiler.internal.RuntimeVersionChecker;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationTypeElementDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationValue;
+import org.apache.ti.compiler.internal.typesystem.declaration.MemberDeclaration;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+
+
+public class ValidateRangeGrammar
+        extends BaseValidationRuleGrammar {
+
+    private static String[][] MUTUALLY_EXCLUSIVE_ATTRS =
+            {{MIN_INT_ATTR, MIN_FLOAT_ATTR}, {MAX_INT_ATTR, MAX_FLOAT_ATTR}};
+
+    private static String[][] ATTR_DEPENDENCIES =
+            {
+                    {MIN_INT_ATTR, MAX_INT_ATTR},
+                    {MIN_FLOAT_ATTR, MAX_FLOAT_ATTR},
+                    {MAX_INT_ATTR, MIN_INT_ATTR},
+                    {MAX_FLOAT_ATTR, MIN_FLOAT_ATTR}
+            };
+
+    public ValidateRangeGrammar(AnnotationProcessorEnvironment env, Diagnostics diags,
+                                RuntimeVersionChecker runtimeVersionChecker) {
+        super(env, diags, runtimeVersionChecker);
+
+        // The annotation defines these as doubles to avoid forcing us to type 'f' after every initialization value.
+        addMemberType(MIN_FLOAT_ATTR, new FloatType());
+        addMemberType(MAX_FLOAT_ATTR, new FloatType());
+
+        // no custom types needed for minInt, maxInt
+    }
+
+    public String[][] getMutuallyExclusiveAttrs() {
+        return MUTUALLY_EXCLUSIVE_ATTRS;
+    }
+
+    public String[][] getRequiredAttrs() {
+        return null;
+    }
+
+    public String[][] getAttrDependencies() {
+        return ATTR_DEPENDENCIES;
+    }
+
+    private class FloatType
+            extends AnnotationMemberType {
+
+        public FloatType() {
+            super(ValidateRangeGrammar.this.getRequiredRuntimeVersion(), ValidateRangeGrammar.this);
+        }
+
+
+        public Object onCheck(AnnotationTypeElementDeclaration valueDecl, AnnotationValue member,
+                              AnnotationInstance[] parentAnnotations, MemberDeclaration classMember,
+                              int annotationArrayIndex) {
+            double d = ((Double) member.getValue()).doubleValue();
+
+            if (d < -Float.MAX_VALUE) addError(member, "error.min-float", new Double(-Float.MAX_VALUE));
+            else if (d > Float.MAX_VALUE) addError(member, "error.max-float", new Double(Float.MAX_VALUE));
+
+            return null;
+        }
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateRequiredGrammar.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateRequiredGrammar.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateRequiredGrammar.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateRequiredGrammar.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,56 @@
+/*
+ * 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.ti.compiler.internal.grammar;
+
+import org.apache.ti.compiler.internal.Diagnostics;
+import org.apache.ti.compiler.internal.FatalCompileTimeException;
+import org.apache.ti.compiler.internal.RuntimeVersionChecker;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+import org.apache.ti.compiler.internal.typesystem.declaration.MemberDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.MethodDeclaration;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+import org.apache.ti.compiler.internal.typesystem.type.PrimitiveType;
+import org.apache.ti.compiler.internal.typesystem.type.TypeInstance;
+
+
+public class ValidateRequiredGrammar
+        extends BaseValidationRuleGrammar {
+
+    public ValidateRequiredGrammar(AnnotationProcessorEnvironment env, Diagnostics diags, RuntimeVersionChecker rvc) {
+        super(env, diags, rvc);
+    }
+
+    protected boolean onBeginCheck(AnnotationInstance annotation, AnnotationInstance[] parentAnnotations,
+                                   MemberDeclaration classMember)
+            throws FatalCompileTimeException {
+        //
+        // Add a warning when this annotation is on a getter method which returns a primitive type.
+        // In that case, it will never be null.
+        //
+        if (classMember instanceof MethodDeclaration) {
+            TypeInstance returnType = ((MethodDeclaration) classMember).getReturnType();
+
+            if (returnType instanceof PrimitiveType) {
+                addWarning(annotation, "warning.validate-required-on-primitive-type",
+                        ANNOTATION_INTERFACE_PREFIX + VALIDATE_REQUIRED_TAG_NAME);
+            }
+        }
+
+        return super.onBeginCheck(annotation, parentAnnotations, classMember);
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateTypeGrammar.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateTypeGrammar.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateTypeGrammar.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateTypeGrammar.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,92 @@
+/*
+* 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.ti.compiler.internal.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationMemberType;
+import org.apache.ti.compiler.internal.Diagnostics;
+import org.apache.ti.compiler.internal.RuntimeVersionChecker;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationTypeElementDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationValue;
+import org.apache.ti.compiler.internal.typesystem.declaration.MemberDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.MethodDeclaration;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+import org.apache.ti.compiler.internal.typesystem.type.PrimitiveType;
+import org.apache.ti.compiler.internal.typesystem.type.TypeInstance;
+
+
+public class ValidateTypeGrammar
+        extends BaseValidationRuleGrammar {
+
+    private static final String[][] REQUIRED_ATTRS = {{TYPE_ATTR}};
+
+    public ValidateTypeGrammar(AnnotationProcessorEnvironment env, Diagnostics diags,
+                               RuntimeVersionChecker runtimeVersionChecker) {
+        super(env, diags, runtimeVersionChecker);
+
+        addMemberType(TYPE_ATTR, new PrimitiveTypeType());
+    }
+
+    public String[][] getRequiredAttrs() {
+        return REQUIRED_ATTRS;
+    }
+
+    private class PrimitiveTypeType
+            extends AnnotationMemberType {
+
+        public PrimitiveTypeType() {
+            super(ValidateTypeGrammar.this.getRequiredRuntimeVersion(), ValidateTypeGrammar.this);
+        }
+
+
+        public Object onCheck(AnnotationTypeElementDeclaration valueDecl, AnnotationValue value,
+                              AnnotationInstance[] parentAnnotations, MemberDeclaration classMember,
+                              int annotationArrayIndex) {
+            Object val = value.getValue();
+
+            //
+            // Make sure the type is in the list of valid types.
+            //
+            if (! (val instanceof PrimitiveType)) {
+                addError(value, "error.must-be-primitive-type");
+            } else {
+                PrimitiveType.Kind kind = ((PrimitiveType) val).getKind();
+
+                if (kind.equals(PrimitiveType.Kind.BOOLEAN)) {
+                    addError(value, "error.invalid-type");
+                } else if (classMember instanceof MethodDeclaration) {
+                    //
+                    // Add a warning if this annotation is on a property getter of the same type, in which case the
+                    // validation rule will never fail.
+                    //
+                    TypeInstance returnType = ((MethodDeclaration) classMember).getReturnType();
+
+                    if (returnType instanceof PrimitiveType) {
+                        if (((PrimitiveType) returnType).getKind().equals(kind)) {
+                            addWarning(value, "warning.validate-type-on-same-type",
+                                    ANNOTATION_INTERFACE_PREFIX + VALIDATE_TYPE_TAG_NAME,
+                                    kind.toString().toLowerCase());
+                        }
+                    }
+                }
+            }
+
+            return null;
+        }
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateValidWhenGrammar.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateValidWhenGrammar.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateValidWhenGrammar.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidateValidWhenGrammar.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,38 @@
+/*
+ * 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.ti.compiler.internal.grammar;
+
+import org.apache.ti.compiler.internal.Diagnostics;
+import org.apache.ti.compiler.internal.RuntimeVersionChecker;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+
+
+public class ValidateValidWhenGrammar
+        extends BaseValidationRuleGrammar {
+
+    private static final String[][] REQUIRED_ATTRS = {{CONDITION_ATTR}, {MESSAGE_ATTR, MESSAGE_KEY_ATTR}};
+
+    public ValidateValidWhenGrammar(AnnotationProcessorEnvironment env, Diagnostics diagnostics,
+                                    RuntimeVersionChecker rvc) {
+        super(env, diagnostics, rvc);
+    }
+
+    public String[][] getRequiredAttrs() {
+        return REQUIRED_ATTRS;
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidationMessageArgsGrammar.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidationMessageArgsGrammar.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidationMessageArgsGrammar.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidationMessageArgsGrammar.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,91 @@
+/*
+* 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.ti.compiler.internal.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationGrammar;
+import org.apache.ti.compiler.internal.CompilerUtils;
+import org.apache.ti.compiler.internal.Diagnostics;
+import org.apache.ti.compiler.internal.RuntimeVersionChecker;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+import org.apache.ti.compiler.internal.typesystem.declaration.MemberDeclaration;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+
+import java.util.Map;
+
+
+public class ValidationMessageArgsGrammar
+        extends AnnotationGrammar {
+
+    private static final String[][] MUTUALLY_EXCLUSIVE_ATTRS =
+            {
+                    {ARG_KEY_ATTR, ARG_ATTR}
+            };
+
+    private static final String[][] REQUIRED_ATTRS =
+            {
+                    {ARG_KEY_ATTR, ARG_ATTR},
+            };
+
+    private static final String[][] ATTR_DEPENDENCIES =
+            {
+                    {BUNDLE_NAME_ATTR, ARG_KEY_ATTR}
+            };
+
+
+    public ValidationMessageArgsGrammar(AnnotationProcessorEnvironment env, Diagnostics diags,
+                                        RuntimeVersionChecker rvc) {
+        super(env, diags, VERSION_9_0_STRING, rvc);
+
+        // ARG_KEY_ATTR, ARG_ATTR do not need a custom type.
+        addMemberType(POSITION_ATTR, new UniqueValueType(MESSAGE_ARGS_ATTR, false, true, null, this));
+        addMemberType(BUNDLE_NAME_ATTR, new BundleNameType(null, this));
+    }
+
+
+    public String[][] getMutuallyExclusiveAttrs() {
+        return MUTUALLY_EXCLUSIVE_ATTRS;
+    }
+
+
+    public String[][] getRequiredAttrs() {
+        return REQUIRED_ATTRS;
+    }
+
+
+    public String[][] getAttrDependencies() {
+        return ATTR_DEPENDENCIES;
+    }
+
+
+    protected Object onEndCheck(AnnotationInstance annotation, AnnotationInstance[] parentAnnotations,
+                                MemberDeclaration classMember, Map checkResults) {
+        Integer position = CompilerUtils.getInteger(annotation, POSITION_ATTR, true);
+
+        if (position == null) {
+            //
+            // Note, GenValidationModel.addMessageArgs() infers the position for
+            // a null position attribute from the postion of the arg in the array.
+            //
+        } else if (position.intValue() < 0 || position.intValue() > 3) {
+            addError(annotation, "error.integer-attribute-not-in-range", POSITION_ATTR,
+                    new Integer(0), new Integer(3));
+        }
+
+        return null;
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidationRulesContainerGrammar.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidationRulesContainerGrammar.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidationRulesContainerGrammar.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/ValidationRulesContainerGrammar.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,48 @@
+/*
+ * 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.ti.compiler.internal.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationGrammar;
+import org.apache.ti.compiler.internal.Diagnostics;
+import org.apache.ti.compiler.internal.RuntimeVersionChecker;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+
+public abstract class ValidationRulesContainerGrammar
+        extends AnnotationGrammar {
+
+    protected ValidationRulesContainerGrammar(AnnotationProcessorEnvironment env, Diagnostics diags,
+                                              RuntimeVersionChecker rvc) {
+        super(env, diags, VERSION_9_0_STRING, rvc);
+
+        addMemberGrammar(VALIDATE_REQUIRED_ATTR, new ValidateRequiredGrammar(env, diags, rvc));
+        addMemberGrammar(VALIDATE_RANGE_ATTR, new ValidateRangeGrammar(env, diags, rvc));
+        addMemberGrammar(VALIDATE_MIN_LENGTH_ATTR,
+                new BaseValidationRuleGrammar(env, diags, rvc, new String[][]{{CHARS_ATTR}}));
+        addMemberGrammar(VALIDATE_MAX_LENGTH_ATTR,
+                new BaseValidationRuleGrammar(env, diags, rvc, new String[][]{{CHARS_ATTR}}));
+        addMemberGrammar(VALIDATE_CREDIT_CARD_ATTR, new BaseValidationRuleGrammar(env, diags, rvc));
+        addMemberGrammar(VALIDATE_EMAIL_ATTR, new BaseValidationRuleGrammar(env, diags, rvc));
+        addMemberGrammar(VALIDATE_MASK_ATTR,
+                new BaseValidationRuleGrammar(env, diags, rvc, new String[][]{{REGEX_ATTR}}));
+        addMemberGrammar(VALIDATE_DATE_ATTR,
+                new BaseValidationRuleGrammar(env, diags, rvc, new String[][]{{PATTERN_ATTR}}));
+        addMemberGrammar(VALIDATE_TYPE_ATTR, new ValidateTypeGrammar(env, diags, rvc));
+        addMemberGrammar(VALIDATE_VALID_WHEN_ATTR, new ValidateValidWhenGrammar(env, diags, rvc));
+        addMemberArrayGrammar(VALIDATE_CUSTOM_ATTR, new ValidateCustomGrammar(env, diags, rvc));
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/WebappPathOrActionType.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/WebappPathOrActionType.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/WebappPathOrActionType.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/WebappPathOrActionType.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,142 @@
+/*
+ * 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.ti.compiler.internal.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationGrammar;
+import org.apache.ti.compiler.internal.CompilerUtils;
+import org.apache.ti.compiler.internal.FatalCompileTimeException;
+import org.apache.ti.compiler.internal.FlowControllerInfo;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationTypeElementDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationValue;
+import org.apache.ti.compiler.internal.typesystem.declaration.ClassDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.MemberDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.MethodDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.TypeDeclaration;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+import org.apache.ti.compiler.internal.typesystem.type.ClassType;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+public class WebappPathOrActionType
+        extends WebappPathType {
+
+    public WebappPathOrActionType(boolean pathMustBeRelative, String requiredRuntimeVersion,
+                                  AnnotationGrammar parentGrammar, FlowControllerInfo fcInfo) {
+        super(pathMustBeRelative, requiredRuntimeVersion, parentGrammar, fcInfo);
+    }
+
+
+    public Object onCheck(AnnotationTypeElementDeclaration valueDecl, AnnotationValue value,
+                          AnnotationInstance[] parentAnnotations, MemberDeclaration classMember,
+                          int annotationArrayIndex)
+            throws FatalCompileTimeException {
+        String stringValue = (String) value.getValue();
+        checkAction(stringValue, value, classMember);
+        return super.onCheck(valueDecl, value, parentAnnotations, classMember, annotationArrayIndex);
+    }
+
+    protected void checkAction(String stringValue, AnnotationValue annValue, MemberDeclaration classMember) {
+        if (stringValue.endsWith(ACTION_EXTENSION_DOT) && stringValue.indexOf('/') == -1) {
+            TypeDeclaration outerType = CompilerUtils.getOuterClass(classMember);
+
+            if (outerType != null)    // null in some error conditions
+            {
+                int extensionPos = stringValue.lastIndexOf(ACTION_EXTENSION_DOT);
+                String actionMethodName = stringValue.substring(0, extensionPos);
+                FlowControllerInfo fcInfo = getFlowControllerInfo();
+                boolean foundIt = actionExists(actionMethodName, outerType, null, getEnv(), fcInfo, true);
+
+                if (! foundIt && actionMethodName.length() > 0) {
+                    //
+                    // Check for a Shared Flow action reference of the form <shared-flow-name>..
+                    //
+                    int dot = actionMethodName.indexOf('.');
+
+                    if (dot != -1 && dot < actionMethodName.length() - 1) {
+                        String sharedFlowName = actionMethodName.substring(0, dot);
+                        TypeDeclaration sfTypeDecl = (TypeDeclaration) getFlowControllerInfo().getSharedFlowTypes().get(sharedFlowName);
+
+                        if (sfTypeDecl != null) {
+                            actionMethodName = actionMethodName.substring(dot + 1);
+                            foundIt = actionExists(actionMethodName, sfTypeDecl, null, getEnv(), fcInfo, true);
+                        }
+                    }
+                }
+
+                if (! foundIt) {
+                    if (doFatalError()) {
+                        addError(annValue, "error.action-not-found", actionMethodName);
+                    } else {
+                        addWarning(annValue, "warning.action-not-found", actionMethodName);
+                    }
+                }
+            }
+        }
+    }
+
+    public static boolean actionExists(String actionName, TypeDeclaration type, AnnotationInstance annotationToIgnore,
+                                       AnnotationProcessorEnvironment env, FlowControllerInfo fcInfo,
+                                       boolean checkInheritedActions) {
+        if (! (type instanceof ClassDeclaration)) {
+            return false;
+        }
+
+        ClassDeclaration classDecl = (ClassDeclaration) type;
+
+        do {
+            //
+            // First look through the action methods.
+            //
+            MethodDeclaration[] methods = classDecl.getMethods();
+
+            for (int i = 0; i < methods.length; i++) {
+                MethodDeclaration method = methods[i];
+                if (method.getSimpleName().equals(actionName)
+                        && CompilerUtils.getAnnotation(method, ACTION_TAG_NAME) != null) {
+                    return true;
+                }
+            }
+
+            //
+            // Next, look through the simple actions (annotations).
+            //
+            Collection simpleActionAnnotations =
+                    CompilerUtils.getAnnotationArrayValue(classDecl, CONTROLLER_TAG_NAME, SIMPLE_ACTIONS_ATTR, true);
+
+            if (simpleActionAnnotations != null) {
+                for (Iterator i = simpleActionAnnotations.iterator(); i.hasNext();) {
+                    AnnotationInstance ann = (AnnotationInstance) i.next();
+                    String name = CompilerUtils.getString(ann, NAME_ATTR, false);
+
+                    if (actionName.equals(name)
+                            && ! CompilerUtils.annotationsAreEqual(ann, annotationToIgnore, false, env)) {
+                        return true;
+                    }
+                }
+            }
+
+            ClassType superType = classDecl.getSuperclass();
+            classDecl = superType != null ? superType.getClassTypeDeclaration() : null;
+        } while (checkInheritedActions && classDecl != null);
+
+
+        return false;
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/WebappPathType.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/WebappPathType.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/WebappPathType.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/WebappPathType.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,245 @@
+/*
+ * 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.ti.compiler.internal.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationGrammar;
+import org.apache.ti.compiler.internal.AnnotationMemberType;
+import org.apache.ti.compiler.internal.CompilerUtils;
+import org.apache.ti.compiler.internal.FatalCompileTimeException;
+import org.apache.ti.compiler.internal.FlowControllerInfo;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationTypeElementDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationValue;
+import org.apache.ti.compiler.internal.typesystem.declaration.MemberDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.Modifier;
+import org.apache.ti.compiler.internal.typesystem.declaration.PackageDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.TypeDeclaration;
+import org.apache.ti.compiler.internal.typesystem.env.AnnotationProcessorEnvironment;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * String type that emits a warning if the given path does not exist in the webapp for this pageflow.
+ */
+public class WebappPathType
+        extends AnnotationMemberType {
+
+    private static final String[] CHECKABLE_EXTENSIONS =
+            {
+                    JSP_FILE_EXTENSION,
+                    XJSP_FILE_EXTENSION,
+                    JPF_FILE_EXTENSION,
+                    "xml",
+                    "htm",
+                    "html"
+            };
+
+    private boolean _pathMustBeRelative = false;
+    private FlowControllerInfo _flowControllerInfo;
+
+
+    public WebappPathType(boolean pathMustBeRelative, String requiredRuntimeVersion, AnnotationGrammar parentGrammar,
+                          FlowControllerInfo fcInfo) {
+        super(requiredRuntimeVersion, parentGrammar);
+        _pathMustBeRelative = pathMustBeRelative;
+        _flowControllerInfo = fcInfo;
+    }
+
+    private static boolean isCheckableExtension(String filePath) {
+        for (int i = 0; i < CHECKABLE_EXTENSIONS.length; ++i) {
+            if (filePath.endsWith(CHECKABLE_EXTENSIONS[i])) return true;
+        }
+
+        return false;
+    }
+
+    public Object onCheck(AnnotationTypeElementDeclaration valueDecl, AnnotationValue value,
+                          AnnotationInstance[] parentAnnotations, MemberDeclaration classMember,
+                          int annotationArrayIndex)
+            throws FatalCompileTimeException {
+        String filePath = (String) value.getValue();
+
+        //
+        // First make sure it's a valid URI.
+        //
+        try {
+            URI uri = new URI(filePath);
+            filePath = uri.getPath();   // decodes the path
+        }
+        catch (URISyntaxException e) {
+            addError(value, "error.invalid-uri", e.getLocalizedMessage());
+            return null;
+        }
+
+        //
+        // The path will be null for an 'opaque' URI, like "news:comp.lang.java".
+        //
+        if (filePath == null || filePath.length() == 0) return null;
+
+        //
+        // Make sure it's a filetype that should exist on the filesystem.  If not, ignore it.
+        //
+        if (! checkAnyExtension() && ! isCheckableExtension(filePath)) return null;
+
+        boolean fileExists = true;
+        TypeDeclaration outerClass = CompilerUtils.getOutermostClass(classMember);
+        File fileToCheck = null;
+
+        if (filePath.charAt(0) == '/')  // relative to webapp root
+        {
+            if (_pathMustBeRelative) addError(value, "error.relative-uri");
+
+            if (filePath.endsWith(JPF_FILE_EXTENSION_DOT)) {
+                TypeDeclaration type = CompilerUtils.inferTypeFromPath(filePath, getEnv());
+                fileToCheck = type != null ? CompilerUtils.getSourceFile(type, false) : null;
+
+                // Note that if we can't infer the file from the type, we'll fall through to the next case, where
+                // we actually look for the file in the webapp.
+            }
+
+            if (fileToCheck == null) {
+                File jpfSourceFile = CompilerUtils.getSourceFile(CompilerUtils.getOuterClass(classMember), false);
+
+                //
+                // We don't always have the source file for the classMember's containing class (e.g., when this class
+                // extends a class that's on classpath but not sourcepath).  If we don't have the source, just ignore.
+                //
+                if (jpfSourceFile != null) {
+                    fileToCheck = CompilerUtils.getWebappRelativeFile(filePath, allowFileInPageFlowSourceDir(), getEnv());
+
+                    if (fileToCheck != null && ! fileToCheck.exists() && ! (ignoreDirectories() && fileToCheck.isDirectory())) {
+                        fileExists = false;
+                    }
+                }
+            }
+        }
+
+        //
+        // If the class being compiled is abstract, don't print warnings for relative-path files that aren't
+        // found.  The derived class might have them.
+        //
+        else if (filePath.indexOf('/') != 0 && ! outerClass.hasModifier(Modifier.ABSTRACT)) {
+            CompilerUtils.Mutable retFileToCheck = new CompilerUtils.Mutable();
+            fileExists = checkRelativePath(filePath, outerClass, retFileToCheck, ignoreDirectories(),
+                    allowFileInPageFlowSourceDir(), getEnv());
+            fileToCheck = (File) retFileToCheck.get();
+        }
+
+        if (fileExists) {
+            if (fileToCheck != null) runAdditionalChecks(fileToCheck, value);
+        } else {
+            if (doFatalError()) {
+                addError(value, "error.file-not-found", filePath);
+            } else {
+                addWarning(value, "warning.file-not-found", filePath);
+            }
+        }
+
+        if (fileToCheck != null) _flowControllerInfo.addReferencedFile(fileToCheck);
+
+        return null;
+    }
+
+    public static boolean relativePathExists(String filePath, TypeDeclaration outerClass,
+                                             AnnotationProcessorEnvironment env)
+            throws FatalCompileTimeException {
+        assert filePath.charAt(0) != '/' : filePath + " is not a relative path";
+        if (! isCheckableExtension(filePath)) return true;
+        return checkRelativePath(filePath, outerClass, null, true, false, env);
+    }
+
+    private static boolean checkRelativePath(String filePath, TypeDeclaration outerClass,
+                                             CompilerUtils.Mutable retFileToCheck,
+                                             boolean ignoreDirectories, boolean allowFileInPageFlowSourceDir,
+                                             AnnotationProcessorEnvironment env)
+            throws FatalCompileTimeException
+
+    {
+        File fileToCheck = null;
+        boolean fileExists = true;
+
+        if (filePath.endsWith(JPF_FILE_EXTENSION_DOT)) {
+            String className = filePath.substring(0, filePath.length() - JPF_FILE_EXTENSION_DOT.length());
+            String pkg = outerClass.getPackage().getQualifiedName();
+            while (className.startsWith("../") && className.length() > 3) {
+                className = className.substring(3);
+                int lastDot = pkg.lastIndexOf('.');
+                pkg = lastDot != -1 ? pkg.substring(0, lastDot) : "";
+            }
+            className = (pkg.length() > 0 ? pkg + '.' : "") + className.replace('/', '.');
+            TypeDeclaration type = env.getTypeDeclaration(className);
+            fileToCheck = type != null ? CompilerUtils.getSourceFile(type, false) : null;
+            if (fileToCheck == null) fileExists = false;
+        }
+        // In certain error conditions (jpfFile == null), we can't determine the file.  In this case, just ignore.
+        else if (CompilerUtils.getSourceFile(outerClass, false) != null) {
+            if (allowFileInPageFlowSourceDir) {
+                fileToCheck = CompilerUtils.getFileRelativeToSourceFile(outerClass, filePath, env);
+            } else {
+                // Use the package name to infer the relative path (from web content root) to the page flow directory.
+                String[] webContentRoots = CompilerUtils.getWebContentRoots(env);
+                String jpfParentRelativePath = "";
+                PackageDeclaration jpfPackage = outerClass.getPackage();
+                if (jpfPackage != null) jpfParentRelativePath = jpfPackage.getQualifiedName().replace('.', '/');
+
+                for (int i = 0; i < webContentRoots.length; i++) {
+                    String webContentRoot = webContentRoots[i];
+                    File desiredParentDir = new File(webContentRoot, jpfParentRelativePath);
+                    fileToCheck = new File(desiredParentDir, filePath);
+                    if (fileToCheck.exists()) break;
+                }
+            }
+
+            if (fileToCheck != null && ! fileToCheck.exists() && ! (ignoreDirectories && fileToCheck.isDirectory())) {
+                fileExists = false;
+            }
+        }
+
+        if (retFileToCheck != null) retFileToCheck.set(fileToCheck);
+        return fileExists;
+    }
+
+    protected boolean checkAnyExtension() {
+        return false;
+    }
+
+    protected boolean doFatalError() {
+        return false;
+    }
+
+    protected void runAdditionalChecks(File file, AnnotationValue member) {
+    }
+
+    protected boolean ignoreDirectories() {
+        return true;
+    }
+
+    /**
+     * Tell whether the file must be in the page flow directory.  If not, it is assumed to live in a webapp-addressable
+     * directory whose path corresponds to the page flow's package.  This is here to support page flows in WEB-INF.
+     */
+    protected boolean allowFileInPageFlowSourceDir() {
+        return false;
+    }
+
+    protected FlowControllerInfo getFlowControllerInfo() {
+        return _flowControllerInfo;
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/WritableFieldType.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/WritableFieldType.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/WritableFieldType.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/grammar/WritableFieldType.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,67 @@
+/*
+ * 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.ti.compiler.internal.grammar;
+
+import org.apache.ti.compiler.internal.AnnotationGrammar;
+import org.apache.ti.compiler.internal.CompilerUtils;
+import org.apache.ti.compiler.internal.JpfLanguageConstants;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationInstance;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationTypeElementDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.AnnotationValue;
+import org.apache.ti.compiler.internal.typesystem.declaration.MemberDeclaration;
+import org.apache.ti.compiler.internal.typesystem.declaration.MethodDeclaration;
+
+public class WritableFieldType
+        extends MemberFieldType
+        implements JpfLanguageConstants {
+
+    private String _attrName;
+
+
+    public WritableFieldType(String requiredSuperclassName, String attrName, String requiredRuntimeVersion,
+                             AnnotationGrammar parentGrammar) {
+        super(requiredSuperclassName, requiredRuntimeVersion, parentGrammar);
+        _attrName = attrName;
+    }
+
+
+    public Object onCheck(AnnotationTypeElementDeclaration valueDecl, AnnotationValue value,
+                          AnnotationInstance[] parentAnnotations, MemberDeclaration classMember,
+                          int annotationArrayIndex) {
+        //
+        // Look for the "readOnly" attribute on the current action method or the current class.  If it's there,
+        // then this attribute cannot refer to the given field.
+        //
+        Boolean readonlyValue = null;
+
+        if (classMember instanceof MethodDeclaration) {
+            readonlyValue = CompilerUtils.getBooleanValue(classMember, ACTION_TAG_NAME, READONLY_ATTR, true);
+        }
+
+        if (readonlyValue == null) {
+            BaseFlowControllerGrammar fcGrammar = (BaseFlowControllerGrammar) getParentGrammar();
+            readonlyValue = Boolean.valueOf(fcGrammar.getFlowControllerInfo().getMergedControllerAnnotation().isReadOnly());
+        }
+
+        if (readonlyValue != null && readonlyValue.booleanValue()) {
+            addError(value, "error.readonly-writable-field-value", _attrName);
+        }
+
+        return super.onCheck(valueDecl, value, parentAnnotations, classMember, annotationArrayIndex);
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/model/AbstractResultContainer.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/model/AbstractResultContainer.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/model/AbstractResultContainer.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/model/AbstractResultContainer.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,91 @@
+/*
+ * 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.ti.compiler.internal.model;
+
+import org.w3c.dom.Element;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+
+abstract class AbstractResultContainer
+        extends XWorkElementSupport
+        implements XWorkResultContainer {
+
+    private LinkedHashMap _forwards = new LinkedHashMap();
+
+
+    public AbstractResultContainer(XWorkModuleConfigModel parentApp) {
+        super(parentApp);
+    }
+
+    public AbstractResultContainer(AbstractResultContainer src) {
+        super(src.getParentApp());
+        _forwards = (LinkedHashMap) src._forwards.clone();
+    }
+
+    /**
+     * Implemented for {@link XWorkResultContainer}.
+     */
+    public void addForward(XWorkResultModel newActionForward) {
+        if (_forwards.containsKey(newActionForward.getName())) {
+            // TODO: logging
+//                if ( ! fwd.getPath().equals( newActionForward.getPath() ) )
+//                {
+//                    logger.warn( "Could not add forward \"" + newActionForward.getName() + "\", path=\""
+//                                 + newActionForward.getPath() + "\" because there is already a forward with"
+//                                 + " the same name (path=\"" + fwd.getPath() + "\")." );
+//                }
+
+            return;
+        }
+
+        _forwards.put(newActionForward.getName(), newActionForward);
+    }
+
+    public XWorkResultModel findForward(String forwardName) {
+        return (XWorkResultModel) _forwards.get(forwardName);
+    }
+
+    public void writeForwards(XmlModelWriter xw, Element parentElement) {
+        for (Iterator i = _forwards.values().iterator(); i.hasNext();) {
+            XWorkResultModel fwd = (XWorkResultModel) i.next();
+            fwd.writeXML(xw, parentElement);
+        }
+    }
+
+    public XWorkResultModel[] getForwards() {
+        return (XWorkResultModel[]) _forwards.values().toArray(new XWorkResultModel[ _forwards.size() ]);
+    }
+
+    public List getForwardsAsList() {
+        List ret = new ArrayList();
+        ret.addAll(_forwards.values());
+        return ret;
+    }
+
+    protected XWorkResultModel getForward(String forwardName) {
+        return (XWorkResultModel) _forwards.get(forwardName);
+    }
+
+    public void deleteForward(XWorkResultModel forward) {
+        _forwards.remove(forward.getName());
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/model/ActionOutputModel.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/model/ActionOutputModel.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/model/ActionOutputModel.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/model/ActionOutputModel.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,64 @@
+/*
+ * 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.ti.compiler.internal.model;
+
+
+/**
+ * Represents an Action Output (NetUI, not a Struts concept) that will be attached to a forward ({@link XWorkResultModel}).
+ */
+public class ActionOutputModel {
+
+    String _name;
+    String _type;
+    boolean _isNullable;
+
+    protected ActionOutputModel() {
+    }
+
+    public ActionOutputModel(String name, String type, boolean isNullable) {
+        _name = name;
+        _type = type;
+        _isNullable = isNullable;
+    }
+
+    public String getName() {
+        return _name;
+    }
+
+    public String getType() {
+        return _type;
+    }
+
+    public boolean getNullable() {
+        return _isNullable;
+    }
+
+    public void setName(String name) {
+        assert name != null;
+        _name = name;
+    }
+
+    public void setType(String type) {
+        assert type != null;
+        _type = type;
+    }
+
+    public void setNullable(boolean nullable) {
+        _isNullable = nullable;
+    }
+}

Added: struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/model/XWorkActionModel.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/model/XWorkActionModel.java?rev=280879&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/model/XWorkActionModel.java (added)
+++ struts/sandbox/trunk/ti/jars/core/src/java/org/apache/ti/compiler/internal/model/XWorkActionModel.java Wed Sep 14 09:20:05 2005
@@ -0,0 +1,364 @@
+/*
+ * 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.ti.compiler.internal.model;
+
+import org.apache.ti.compiler.internal.JpfLanguageConstants;
+import org.w3c.dom.Element;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+
+/**
+ * Represents an action in an XWork-based application.
+ */
+public class XWorkActionModel
+        extends AbstractResultContainer
+        implements XWorkResultContainer, XWorkExceptionHandlerContainer, JpfLanguageConstants {
+
+    public static final String DEFAULT_FORM_SCOPE = "request";
+
+
+    private ArrayList _exceptionCatches = new ArrayList();
+    private String _attribute;
+    private String _className;
+    private String _validationErrorForward;
+    private String _formBeanType;
+    private String _formBeanAttribute;
+    private String _name;  // required to be set
+    private String _prefix;
+    private String _scope = DEFAULT_FORM_SCOPE;
+    private String _suffix;
+    private String _type;
+    private boolean _unknown;
+    private String _roles;
+    private boolean _validate;
+    private String _unqualifiedName;
+    private boolean _loginRequired;
+    private boolean _isOverloaded;
+    private boolean _readonly;
+    private boolean _isSimpleAction = false;
+    private boolean _preventDoubleSubmit = false;
+    private String _formBeanMember;     // pageflow-scoped form
+    private Map _conditionalForwards;
+    private String _formBeanMessageResourcesKey;
+    private String _defaultForwardName;     // for Simple Actions
+
+
+    public XWorkActionModel(String path, XWorkModuleConfigModel parent) {
+        super(parent);
+        _name = path;
+    }
+
+    protected XWorkActionModel(XWorkModuleConfigModel parent) {
+        this(null, parent);
+    }
+
+    /**
+     * Construct a copy of the given mapping, with the given path.
+     */
+    public XWorkActionModel(XWorkActionModel src, String newPath) {
+        super(src);
+        _name = newPath;
+        _formBeanType = src._formBeanType;
+        _formBeanAttribute = src._formBeanAttribute;
+        _exceptionCatches = (ArrayList) src._exceptionCatches.clone();
+        _attribute = src._attribute;
+        _className = src._className;
+        _validationErrorForward = src._validationErrorForward;
+        _validate = src._validate;
+        _prefix = src._prefix;
+        _scope = src._scope;
+        _suffix = src._suffix;
+        _type = src._type;
+        _unknown = src._unknown;
+        _formBeanMember = src._formBeanMember;
+        _roles = src._roles;
+        _loginRequired = src._loginRequired;
+        _preventDoubleSubmit = src._preventDoubleSubmit;
+        _isSimpleAction = src._isSimpleAction;
+        _isOverloaded = src._isOverloaded;
+        _readonly = src._readonly;
+        _unqualifiedName = src._unqualifiedName;
+        _defaultForwardName = src._defaultForwardName;
+    }
+
+    public void writeXML(XmlModelWriter xw, Element parentElement) {
+        Element actionElement = xw.addElement(parentElement, "action");
+        xw.addComment(actionElement, getComment());
+
+        actionElement.setAttribute("name", _name);
+        actionElement.setAttribute("class", PAGEFLOW_XWORK_PACKAGE + ".PageFlowAction");
+
+        addParam(xw, actionElement, "formBeanType", _formBeanType);
+        addParam(xw, actionElement, "formBeanAttribute", _formBeanAttribute);
+        addParam(xw, actionElement, "validationErrorForward", _validationErrorForward);
+        addParam(xw, actionElement, "unqualifiedName", _unqualifiedName);
+        addParam(xw, actionElement, "formBeanMember", _formBeanMember);
+        addParam(xw, actionElement, "rolesAllowed", _roles);
+        if (_loginRequired) addParam(xw, actionElement, "loginRequired", true);
+        if (_preventDoubleSubmit) addParam(xw, actionElement, "preventDoubleSubmit", true);
+        if (_isOverloaded) addParam(xw, actionElement, "overloaded", true);
+        if (_readonly) addParam(xw, actionElement, "readonly", true);
+        if (_isSimpleAction) addParam(xw, actionElement, "simpleAction", true);
+        addParam(xw, actionElement, "defaultForward", _defaultForwardName);
+
+        if (_conditionalForwards != null) {
+            addParam(xw, actionElement, "conditionalForwards", getMapString(_conditionalForwards));
+        }
+
+        if (_formBeanMessageResourcesKey != null) {
+            addParam(xw, actionElement, "formBeanMessageResourcesKey", _formBeanMessageResourcesKey);
+        }
+
+        if (_exceptionCatches != null && ! _exceptionCatches.isEmpty()) {
+            for (Iterator i = _exceptionCatches.iterator(); i.hasNext();) {
+                XWorkExceptionHandlerModel exceptionModel = (XWorkExceptionHandlerModel) i.next();
+                exceptionModel.writeXML(xw, parentElement);
+            }
+        }
+
+        writeForwards(xw, actionElement);
+    }
+
+    /**
+     * Implemented for {@link XWorkExceptionHandlerContainer}.
+     */
+    public void addException(XWorkExceptionHandlerModel em) {
+        _exceptionCatches.add(em);
+    }
+
+    public String getAttribute() {
+        return _attribute;
+    }
+
+    public void setAttribute(String attribute) {
+        _attribute = attribute;
+    }
+
+    public String getClassName() {
+        return _className;
+    }
+
+    public void setClassName(String className) {
+        _className = className;
+    }
+
+    public String getValidationErrorForward() {
+        return _validationErrorForward;
+    }
+
+    public void setValidationErrorForward(String validationErrorForward) {
+        _validationErrorForward = validationErrorForward;
+    }
+
+    public String getFormBeanType() {
+        return _formBeanType;
+    }
+
+    public void setFormBeanType(String formBeanType) {
+        _formBeanType = formBeanType;
+        _formBeanAttribute = generateFormBeanAttribute(formBeanType, getParentApp());
+    }
+
+    public boolean isValidate() {
+        return _validate;
+    }
+
+    public void setValidate(boolean validate) {
+        _validate = validate;
+    }
+
+    public String getName() {
+        return _name;
+    }
+
+    public String getPath(boolean useUnqualifiedPath) {
+        if (useUnqualifiedPath && _unqualifiedName != null) {
+            return _unqualifiedName;
+        } else {
+            return _name;
+        }
+    }
+
+    public void setName(String name) {
+        _name = name;
+    }
+
+    public String getPrefix() {
+        return _prefix;
+    }
+
+    public void setPrefix(String prefix) {
+        _prefix = prefix;
+    }
+
+    public String getScope() {
+        return _scope == null ? DEFAULT_FORM_SCOPE : _scope;
+    }
+
+    public void setScope(String scope) {
+        _scope = scope;
+    }
+
+    public String getSuffix() {
+        return _suffix;
+    }
+
+    public void setSuffix(String suffix) {
+        _suffix = suffix;
+    }
+
+    public String getType() {
+        return _type;
+    }
+
+    public void setType(String type) {
+        _type = type;
+    }
+
+    public boolean isUnknown() {
+        return _unknown;
+    }
+
+    public void setUnknown(boolean unknown) {
+        _unknown = unknown;
+    }
+
+    public String getUnqualifiedName() {
+        return _unqualifiedName;
+    }
+
+    public void setUnqualifiedName(String unqualifiedName) {
+        _unqualifiedName = unqualifiedName;
+    }
+
+    public String getDefaultForwardName() {
+        return _defaultForwardName;
+    }
+
+    public void setDefaultForwardName(String defaultForwardName) {
+        _defaultForwardName = defaultForwardName;
+    }
+
+    public String getRoles() {
+        return _roles;
+    }
+
+    public void setRoles(String roles) {
+        _roles = roles;
+    }
+
+    public void setLoginRequired(boolean loginRequired) {
+        _loginRequired = loginRequired;
+    }
+
+    public void setPreventDoubleSubmit(boolean preventDoubleSubmit) {
+        _preventDoubleSubmit = preventDoubleSubmit;
+    }
+
+    public boolean isSimpleAction() {
+        return _isSimpleAction;
+    }
+
+    public void setSimpleAction(boolean simpleAction) {
+        _isSimpleAction = simpleAction;
+    }
+
+    public boolean isOverloaded() {
+        return _isOverloaded;
+    }
+
+    public void setOverloaded(boolean overloaded) {
+        _isOverloaded = overloaded;
+    }
+
+    public String getFormBeanMember() {
+        return _formBeanMember;
+    }
+
+    public void setFormBeanMember(String formBeanMember) {
+        _formBeanMember = formBeanMember;
+    }
+
+    public boolean isReadonly() {
+        return _readonly;
+    }
+
+    public void setReadonly(boolean readonly) {
+        _readonly = readonly;
+    }
+
+    public void addConditionalForward(String expression, String forwardName) {
+        if (_conditionalForwards == null) _conditionalForwards = new LinkedHashMap();
+        _conditionalForwards.put(expression, forwardName);
+    }
+
+    private static String getMapString(Map map) {
+        StringBuffer retVal = new StringBuffer();
+
+        for (Iterator i = map.entrySet().iterator(); i.hasNext();) {
+            Map.Entry entry = (Map.Entry) i.next();
+            retVal.append(entry.getValue()).append(':').append(entry.getKey()).append(';');
+        }
+
+        return retVal.toString();
+    }
+
+    public void setFormBeanMessageResourcesKey(String formBeanMessageResourcesKey) {
+        _formBeanMessageResourcesKey = formBeanMessageResourcesKey;
+    }
+
+    public String getHandlerPrefix() {
+        return _name + ':';
+    }
+
+    public String getDescription() {
+        return "action " + _name;
+    }
+
+    /**
+     * Generate the attribute name of the form bean (to be set in request scope at runtime).
+     */
+    private static String generateFormBeanAttribute(String formBeanType, XWorkModuleConfigModel parentApp) {
+        if (formBeanType == null) {
+            return null;
+        }
+
+        int lastQualifier = formBeanType.lastIndexOf('$');
+
+        if (lastQualifier == -1) {
+            lastQualifier = formBeanType.lastIndexOf('.');
+        }
+
+        String formBeanAttr = formBeanType.substring(lastQualifier + 1);
+        formBeanAttr = Character.toLowerCase(formBeanAttr.charAt(0)) + formBeanAttr.substring(1);
+
+        // If this attribute is already being used by another form bean type, add one based on the fully-qualified name.
+        for (Iterator i = parentApp.getActions().iterator(); i.hasNext();) {
+            XWorkActionModel action = (XWorkActionModel) i.next();
+            if (formBeanAttr.equals(action._formBeanAttribute) && ! formBeanType.equals(action.getFormBeanType())) {
+                formBeanAttr = formBeanType.replace('.', '_').replace('$', '_');
+            }
+        }
+
+        return formBeanAttr;
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org