Added: 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/compiler/xdoclet/typesystem/impl/type/TypeVariableImpl.java
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/compiler/xdoclet/typesystem/impl/type/TypeVariableImpl.java?view=auto&rev=157713
==============================================================================
--- 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/compiler/xdoclet/typesystem/impl/type/TypeVariableImpl.java
 (added)
+++ 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/compiler/xdoclet/typesystem/impl/type/TypeVariableImpl.java
 Tue Mar 15 23:14:32 2005
@@ -0,0 +1,39 @@
+/*
+ * 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.xdoclet.typesystem.impl.type;
+
+import 
org.apache.beehive.netui.compiler.typesystem.declaration.TypeParameterDeclaration;
+import org.apache.beehive.netui.compiler.typesystem.type.TypeVariable;
+
+public class TypeVariableImpl
+        extends ReferenceTypeImpl
+        implements TypeVariable
+{
+    public TypeVariableImpl()
+    {
+        super( null );
+        assert false : "NYI";
+        throw new UnsupportedOperationException( "NYI" );
+    }
+    
+    public TypeParameterDeclaration getDeclaration()
+    {
+        assert false : "NYI";
+        throw new UnsupportedOperationException( "NYI" );
+    }
+}

Propchange: 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/compiler/xdoclet/typesystem/impl/type/TypeVariableImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/compiler/xdoclet/typesystem/impl/type/VoidTypeImpl.java
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/compiler/xdoclet/typesystem/impl/type/VoidTypeImpl.java?view=auto&rev=157713
==============================================================================
--- 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/compiler/xdoclet/typesystem/impl/type/VoidTypeImpl.java
 (added)
+++ 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/compiler/xdoclet/typesystem/impl/type/VoidTypeImpl.java
 Tue Mar 15 23:14:32 2005
@@ -0,0 +1,31 @@
+/*
+ * 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.xdoclet.typesystem.impl.type;
+
+import org.apache.beehive.netui.compiler.typesystem.type.VoidType;
+import xjavadoc.XClass;
+
+public class VoidTypeImpl
+        extends TypeMirrorImpl
+        implements VoidType
+{
+    public VoidTypeImpl( XClass delegate )
+    {
+        super( delegate );
+    }
+}

Propchange: 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/compiler/xdoclet/typesystem/impl/type/VoidTypeImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/tasks/SourceCopy.java
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/tasks/SourceCopy.java?view=auto&rev=157713
==============================================================================
--- 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/tasks/SourceCopy.java
 (added)
+++ 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/tasks/SourceCopy.java
 Tue Mar 15 23:14:32 2005
@@ -0,0 +1,133 @@
+package org.apache.beehive.netui.tasks;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.taskdefs.Copy;
+
+import java.util.Enumeration;
+import java.io.*;
+
+/**
+ * Extend the default ant copy task to do some verification on java and 
pageflow source files.
+ */ 
+public class SourceCopy extends Copy
+{
+    protected static final String PACKAGE = "package";
+
+    /**
+     * Override doFileOperations to verify things that a source file's
+     * package name is the same as directory name.
+     * 
+     * Note: we are not checking that anything named .jpf extends 
PageFlowController because
+     * that would require more advanced source parsing; the netui doclet task 
handles this by
+     * making sure that if we find a class that extends PageFlowController, 
there is a corresponding
+     * jpf file.
+     */
+    protected void doFileOperations()
+    {
+        if (fileCopyMap.size() > 0)
+        {
+            log("Verifying " + fileCopyMap.size()
+                    + " source file" + (fileCopyMap.size() == 1 ? "" : "s")
+                    + " before copy");
+
+           
+            Enumeration e = fileCopyMap.keys();
+            while (e.hasMoreElements())
+            {
+                String fromFile = (String) e.nextElement();
+                
+                if ( !fromFile.endsWith( ".java" ) && !fromFile.endsWith( 
".jpf" ) &&
+                        !fromFile.endsWith( ".app" ) )
+                    continue;
+
+                try
+                {
+                    File sourceFile = new File( fromFile );
+                    if ( sourceFile.exists() && sourceFile.isFile() )
+                    {
+                        String packageName = getPackage( sourceFile );
+                        if ( packageName != null && packageName.length() > 0 )
+                        {
+                            String path = sourceFile.getParentFile().getPath();
+                            path = path.replace( File.separatorChar, '.' );
+                            if ( !path.endsWith( packageName ) )
+                            {
+                                throw new BuildException( "File " + fromFile + 
" failed verification because its package (" +
+                                        packageName + ") differs from its 
directory location. This will cause errors with the pageflow compiler." );
+                            }
+                        }                        
+                    }
+                }
+                catch (Exception ioe)
+                {
+                    String msg = "Failed to verify " + fromFile
+                            + " due to " + ioe.getMessage();
+                    throw new BuildException(msg, ioe, getLocation());
+                }
+            }
+        }
+
+        super.doFileOperations();
+    }
+
+    /**
+     * Get the package name of a java source file. This just does some really 
basic parsing to find
+     * the first line that starts with "package", and then returns the rest of 
that line before the
+     * first semicolon. It won't catch any possible way that a package could 
be specified (after a comment,
+     * with line breaks, etc) but it's a good-faith effort to determine the 
package name. If no package
+     * name is found, the file will be skipped during the verification process.
+     * @param sourceFile
+     * @return
+     * @throws IOException
+     */ 
+    protected String getPackage(File sourceFile)
+            throws IOException
+    {
+        BufferedReader in = null;
+        String packageName = null;
+        String encoding = getEncoding();
+
+        try
+        {
+            if (encoding == null)
+            {
+                in = new BufferedReader(new FileReader(sourceFile));
+            }
+            else
+            {
+                in = new BufferedReader(new InputStreamReader(
+                                new FileInputStream(sourceFile),
+                                encoding));
+            }
+
+            String line = in.readLine();
+            while (line != null)
+            {
+                if (line.length() != 0)
+                {
+                    line = line.trim();
+                    if (line.startsWith(PACKAGE))
+                    {
+                        int semi = line.indexOf(";");
+                        if ( semi != -1 )
+                        {
+                            packageName = line.substring(PACKAGE.length() + 1, 
semi);
+                            packageName = packageName.trim();
+                        }
+                        break;
+                    }
+                }
+                line = in.readLine();
+            }
+        }
+        finally
+        {
+            if (in != null)
+            {
+                in.close();
+            }
+        }
+
+        return packageName;
+    }
+}

Propchange: 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/tasks/SourceCopy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/Messages.properties
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/Messages.properties?view=auto&rev=157713
==============================================================================
--- 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/Messages.properties
 (added)
+++ 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/Messages.properties
 Tue Mar 15 23:14:32 2005
@@ -0,0 +1,9 @@
+compiler.build.failed = \n\nPage Flow build failed; see errors above.
+compiler.build.results = \n\n----->{0} error(s) and {1} warning(s) found in 
{2}:
+compiler.warning = warning: 
+compiler.line = (line {0}) 
+
+error.no-parent-annotation = There is no valid parent annotation for @{0}.
+error.no-such-member = There is no member "{0}" on annotation @{1}.
+error.invalid-enum-value = "{0}" is not a valid value for attribute {1}.  
Valid values are:{2}.
+error.unknown-class = Unrecognized type {0} for attribute {1}.

Propchange: 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/Messages.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/NetuiBuildException.java
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/NetuiBuildException.java?view=auto&rev=157713
==============================================================================
--- 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/NetuiBuildException.java
 (added)
+++ 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/NetuiBuildException.java
 Tue Mar 15 23:14:32 2005
@@ -0,0 +1,23 @@
+package org.apache.beehive.netui.xdoclet;
+
+import org.apache.tools.ant.BuildException;
+
+/**
+ * Extension of ant's BuildException that does not print a stack trace. This 
is used to
+ * signal ant that the build has failed from the doclet task, but without the
+ * XJavaDocTask superclass printing out a stacktrace, so that pageflow build 
error messages
+ * will be easier to find.
+ */
+public class NetuiBuildException extends BuildException
+{
+
+    public NetuiBuildException()
+    {
+        super();
+    }
+
+    public void printStackTrace()
+    {
+        // no-op so we won't let XJavaDocTask print out a stack when the build 
fails
+    }
+}

Propchange: 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/NetuiBuildException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/NetuiDocletTask.java
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/NetuiDocletTask.java?view=auto&rev=157713
==============================================================================
--- 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/NetuiDocletTask.java
 (added)
+++ 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/NetuiDocletTask.java
 Tue Mar 15 23:14:32 2005
@@ -0,0 +1,195 @@
+package org.apache.beehive.netui.xdoclet;
+
+import org.apache.beehive.netui.compiler.typesystem.util.SourcePosition;
+import org.apache.tools.ant.BuildException;
+import xdoclet.DocletTask;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Netui XDoclet task
+ *
+ * @ant.element name="netuidoclet" display-name="NetUI Task"
+ */
+public class NetuiDocletTask extends DocletTask
+{
+    private static HashMap _buildMessages = new HashMap();   // String 
filename -> List messages
+
+    private static File _webappRoot = null;
+
+
+
+    /**
+     * @throws BuildException
+     *
+     */
+    protected void start() throws BuildException
+    {
+        try
+        {
+            assert _webappRoot != null;     // should have been set in the ant 
task
+            super.start();
+        }
+        finally
+        {
+            _webappRoot = null;
+
+            // list any warnings and errors
+            boolean overallError = false;
+            if ( _buildMessages != null )
+            {
+                Iterator i = _buildMessages.keySet().iterator();
+                
+                while ( i.hasNext() )
+                {
+                    String sourceFile = ( String ) i.next();
+                    List messages = ( List ) _buildMessages.get( sourceFile );
+                    int errorCount = 0;
+                    int warningCount = 0;
+                    
+                    for ( Iterator j = messages.iterator(); j.hasNext(); )
+                    {
+                        BuildMessage message = ( BuildMessage ) j.next();
+                        System.err.println();
+                        System.err.print( sourceFile );
+                        System.err.print( ": " );
+                        
+                        if ( message.getLine() > 0 )
+                        {
+                            String[] args = { Integer.valueOf( 
message.getLine() ).toString() };
+                            System.err.println( 
XDocletCompilerUtils.getMessage( "compiler.line", args ) );
+                        }
+                        
+                        if ( message.isError() )
+                        {
+                            overallError = true;
+                            ++errorCount;
+                        }
+                        else
+                        {
+                            System.err.print( XDocletCompilerUtils.getMessage( 
"compiler.warning", null ) );
+                            ++warningCount;
+                        }
+                        
+                        System.err.println( message.getMessage() );
+                    }
+                    
+                    System.err.println( XDocletCompilerUtils.getMessage( 
"compiler.build.results",
+                                                    new String[]{ 
Integer.valueOf( errorCount ).toString(),
+                                                                  
Integer.valueOf( warningCount ).toString(),
+                                                                  sourceFile } 
) );
+                }
+            }
+
+            _buildMessages = null;
+
+            if ( overallError )
+            {
+                System.err.println( XDocletCompilerUtils.getMessage( 
"compiler.build.failed", null ) );
+                throw new NetuiBuildException();
+            }
+        }
+    }
+
+    public static void addError( String error, SourcePosition sourcePosition )
+    {
+        assert sourcePosition != null;
+        String sourceFilePath = sourcePosition.file().getPath();
+        int line = sourcePosition.line();
+        addError( error, sourceFilePath, line );
+    }
+    
+    public static void addError( String error, String sourceFile, int line )
+    {
+        List messages = ( List ) _buildMessages.get( sourceFile );
+        
+        if ( messages == null )
+        {
+            messages = new ArrayList();
+            _buildMessages.put( sourceFile, messages );
+        }
+        
+        messages.add( new BuildMessage( error, line, true ) );
+    }
+
+    public static void addWarning( String warning, SourcePosition 
sourcePosition )
+    {
+        assert sourcePosition != null;
+        String sourceFilePath = sourcePosition.file().getPath();
+        int line = sourcePosition.line();
+        addWarning( warning, sourceFilePath, line );
+    }
+    
+    public static void addWarning( String warning, String sourceFile, int line 
)
+    {
+        List messages = ( List ) _buildMessages.get( sourceFile );
+        
+        if ( messages == null )
+        {
+            messages = new ArrayList();
+            _buildMessages.put( sourceFile, messages );
+        }
+        
+        messages.add( new BuildMessage( warning, line, false ) );
+    }
+
+    private static class BuildMessage
+    {
+        private String _message;
+        private boolean _error;
+        private int _line;
+
+        public BuildMessage( String message, int line, boolean error )
+        {
+            _message = message;
+            _error = error;
+            _line = line;
+        }
+
+        public final String getMessage()
+        {
+            return _message;
+        }
+
+        public final boolean isError()
+        {
+            return _error;
+        }
+
+        public final int getLine()
+        {
+            return _line;
+        }
+    }
+    
+    /**
+     * Called by superclass before start() is called
+     *
+     * @throws BuildException Describe the exception
+     */
+    protected void validateOptions() throws BuildException
+    {
+        // we don't support the destdir attribute; so if it's null, just fake 
it so super won't
+        // fail validation
+        if ( getDestDir() == null )
+        {
+            setDestDir( new File( "bogus" ) );
+        }
+        super.validateOptions();
+    }
+
+    public void setWebappRoot( File file )
+    {
+        _webappRoot = file;
+    }
+
+    public static File getWebappRoot()
+    {
+        return _webappRoot;
+    }
+
+}

Propchange: 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/NetuiDocletTask.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/NetuiSubTask.java
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/NetuiSubTask.java?view=auto&rev=157713
==============================================================================
--- 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/NetuiSubTask.java
 (added)
+++ 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/NetuiSubTask.java
 Tue Mar 15 23:14:32 2005
@@ -0,0 +1,1349 @@
+package org.apache.beehive.netui.xdoclet;
+
+import org.apache.beehive.netui.compiler.processor.PageFlowAnnotationProcessor;
+import 
org.apache.beehive.netui.compiler.typesystem.declaration.AnnotationTypeDeclaration;
+import 
org.apache.beehive.netui.compiler.typesystem.env.AnnotationProcessorEnvironment;
+import 
org.apache.beehive.netui.compiler.xdoclet.typesystem.impl.declaration.DeclarationImpl;
+import 
org.apache.beehive.netui.compiler.xdoclet.typesystem.impl.env.AnnotationProcessorEnvironmentImpl;
+import xdoclet.DocletContext;
+import xdoclet.SubTask;
+import xdoclet.XDocletException;
+import xjavadoc.SourceClass;
+import xjavadoc.XJavaDoc;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+
+/**
+ * XJavaDoc subtask to run through a set of pageflows in a webapp and generate 
struts-config files for them.
+ * This uses a lot of the generic compiler model objects and xml generation 
code fom com.bea.netui.pageflow.model.
+ * 
+ * @ant.element          display-name="Netui" name="netui" 
parent="org.apache.beehive.netui.xdoclet.NetuiDocletTask"
+ */
+public class NetuiSubTask extends SubTask
+{
+    private SourceClass _currentSourceClass;
+    
+    /**
+     * Main entry point for xjavadoc tasks. Here we iterate through all the 
classes found by
+     * xjavadoc and process the ones that we recognize as pageflows.
+     * 
+     * @throws XDocletException
+     */ 
+    public void execute() throws XDocletException
+    {
+    /*
+        if ( DocletContext.getInstance().isVerbose() )
+            System.out.println( CompilerUtil.genMessage( 
"compiler.info.gen.location",
+                    new String[] {getDestDir().getPath()} ) );
+    */
+        Collection classes = getXJavaDoc().getSourceClasses();
+        
+        /*
+        // issue a warning if xjavadoc didn't find any classes at all
+        if ( classes.size() == 0 )
+        {
+            System.out.println( CompilerUtil.genMessage( "no.classes.found" ) 
);
+            return;
+        }
+        
+        _pageflowCount = 0;
+        */
+        
+        Iterator iter = classes.iterator();
+        while ( iter.hasNext() )
+        {
+            SourceClass sourceClass = ( SourceClass ) iter.next();
+            AnnotationProcessorEnvironment env = 
AnnotationProcessorEnvironmentImpl.get( getContext(), this, sourceClass );
+            AnnotationTypeDeclaration[] decls = 
DeclarationImpl.getAllAnnotations();    // TODO: filter appropriately
+            
+            PageFlowAnnotationProcessor pfap = new 
PageFlowAnnotationProcessor( decls, env );
+            
+            try
+            {
+                _currentSourceClass = sourceClass;
+                pfap.process();
+            }
+            finally
+            {
+                _currentSourceClass = null;
+            }
+            /*
+            
+            for ( Iterator i = c.getMethods().iterator(); i.hasNext(); )
+            {
+                XMethod method = ( XMethod ) i.next();
+                XDoc doc = method.getDoc();
+                System.err.println( "    method " + method.getName() + ": " + 
method.getReturnType().getType().getName() + " : " + method.getModifiers() );
+                List tags = doc.getTags();
+                for ( Iterator j = tags.iterator(); j.hasNext(); )
+                {
+                    XTag tag = ( XTag ) j.next();
+                    System.err.println( "        " + tag.getName() + ": " + 
tag.getValue() );
+                    
+                    Collection attrs = tag.getAttributeNames();
+                    for ( Iterator k = attrs.iterator(); k.hasNext(); )
+                    {
+                        String attrName = ( String ) k.next();
+                        System.err.println( "            " + attrName + ": " + 
tag.getAttributeValue( attrName ) );
+                    }
+                }
+            }
+            */
+
+            /*
+            if ( c.isA( PAGEFLOW_CLASS_NAME, true ) )
+                processJpf( c, false );
+            else if ( c.isA( GLOBALAPP_BASE_CLASS_NAME, true ) )
+                processJpf( c, true );
+            else
+            {
+                // workaround for needing to import explicit types - if the 
pageflow package
+                // was imported, and we extend the right class name, go for it.
+                List pkgs = c.getImportedPackages();
+                Iterator pkgIter = pkgs.iterator();
+                boolean found = false;
+                while ( pkgIter.hasNext() )
+                {
+                    XPackage pkg = (XPackage) pkgIter.next();
+                    if ( pkg.getName().equals( PAGEFLOW_PACKAGE ) )
+                    {
+                        found = true;
+                        break;
+                    }
+                }
+
+                boolean isJpf = false;
+                if ( found )
+                {
+                    XClass superClass = c.getSuperclass();
+                    if ( superClass.getName().equals( 
PAGEFLOW_SHORT_CLASS_NAME ) )
+                    {
+                        isJpf = true;
+                        processJpf( c, false );
+                    }                        
+                    else if ( superClass.getName().equals( 
GLOBALAPP_SHORT_CLASS_NAME ) )
+                    {
+                        isJpf = true;
+                        processJpf( c, true );
+                    }
+                }
+                
+                if ( !isJpf && !c.isInner() )
+                {
+                    // this is not a pageflow class, make sure it did not come 
from a .jpf file
+                    try
+                    {
+                        File sourceFile = new File( 
((SourceClass)c).getFile().getPath() );
+                        File f = XDocletStrutsApp.getOriginalJpfSourceFile( 
sourceFile.getName(), c, false );
+                        if ( f.exists() )
+                        {
+                            CompilerUtil.error( f.toString(), 
CompilerUtil.genMessage( "pageflow.error.does-not-extend-base", new String[] 
{PAGEFLOW_CLASS_NAME} ) );
+                        }
+                        f = XDocletStrutsApp.getOriginalJpfSourceFile( 
sourceFile.getName(), c, true ); 
+                        if ( f.exists() )
+                        {
+                            CompilerUtil.error( f.toString(), 
CompilerUtil.genMessage( "pageflow.error.does-not-extend-base", new String[] 
{GLOBALAPP_BASE_CLASS_NAME} ) );
+                        }
+                    }
+                    catch ( NoWebInfDirectoryException e )
+                    {
+                        // ignore
+                    }
+                }
+            }
+            */
+        }
+    }
+
+    /*
+    protected void processJpf( XClass jpfClass, boolean global )
+        throws XDocletException
+    {
+        _pageflowCount++;
+        try
+        {
+            File webappRoot = XDocletStrutsApp.getWebappRootFromJpf();
+            File strutsConfigDir = new File( webappRoot + STRUTS_OUTPUT_DIR );
+            if ( !strutsConfigDir.exists() )
+            {
+                strutsConfigDir.mkdirs();
+            }
+
+            _isGlobal = global;
+            StringBuffer configFileName = new StringBuffer();
+            if ( _isGlobal )
+            {
+                configFileName.append( STRUTS_CONFIG_PREFIX )
+                        .append( GLOBALAPP_MODULE_NAME )
+                        .append( STRUTS_CONFIG_EXTENSION );
+            }
+            else
+            {
+                XPackage pkg = jpfClass.getContainingPackage();
+                if ( !pkg.isDefaultPackage() )
+                {
+                    configFileName.append( STRUTS_CONFIG_PREFIX );
+                    configFileName.append( pkg.getName().replace( '.', '-' ) );
+                    configFileName.append( STRUTS_CONFIG_EXTENSION );
+                }
+                else
+                {
+                    configFileName.append( ROOT_STRUTS_CONFIG );
+                }
+            }
+            File strutsConfigFile = new File( strutsConfigDir, 
configFileName.toString() );
+
+            // note: webapp root is not used in this situation
+            _strutsApp = new XDocletStrutsApp( 
jpfClass.getContainingPackage().getName(), strutsConfigFile,
+                    webappRoot.getPath(), jpfClass, global );
+            _strutsApp.setJpfSourceFile( new File( 
((SourceClass)jpfClass).getFile().getPath() ) );
+
+            if ( DocletContext.getInstance().isVerbose() )
+            {
+                System.out.println( CompilerUtil.genMessage( 
"compiler.info.gen.file",
+                        new String[] { configFileName.toString(), 
jpfClass.getQualifiedName() } ) );
+                System.out.println( CompilerUtil.genMessage( 
"compiler.info.original.jpf",
+                        new String[] 
{_strutsApp.getOriginalJpfSourceFile().getPath()} ) );
+            }
+
+            File originalJpf = _strutsApp.getOriginalJpfSourceFile();
+            File jpfParentDir = originalJpf.getParentFile();
+            String jpfName = originalJpf.getName();
+
+            if ( global )
+            {
+                // if global, make sure the file name is correct and it's in 
the right place
+                if ( !jpfName.equals( GLOBALAPP_FILENAME ) )
+                    CompilerUtil.error( 
"pageflow.error.global-app-wrong-name", (String[])null );
+
+                XPackage pkg = jpfClass.getContainingPackage();
+                String pkgName = pkg.getName();
+                if ( !pkgName.equals( GLOBALAPP_PACKAGE ) )
+                    CompilerUtil.error( "pageflow.error.wrong-package", new 
String[] {GLOBALAPP_PACKAGE} );
+
+                String fullGlobalPath = _strutsApp.getWebappRootPath() + 
File.separatorChar + GLOBALAPP_SOURCE_DIR;
+                String myPath = jpfParentDir.getPath();
+                if ( !myPath.equals( fullGlobalPath ) || !originalJpf.exists() 
)
+                    CompilerUtil.error( "pageflow.error.global-app-wrong-dir",
+                            new String[] { GLOBALAPP_FILENAME, 
GLOBALAPP_SOURCE_DIR } );
+            }
+            else
+            {
+                //otherwise make sure it's a jpf file
+                if ( !jpfName.endsWith( PAGEFLOW_EXTENSION ) || 
!originalJpf.exists() )
+                    CompilerUtil.error( "compiler.error.wrong.extension", 
(String[])null );
+
+                // then check for other pageflows in the package
+                String[] otherFiles = jpfParentDir.list();
+                List otherJpfs = new ArrayList();
+                for ( int i=0; i<otherFiles.length; i++ )
+                {
+                    if ( otherFiles[i].endsWith( PAGEFLOW_EXTENSION ) && 
!otherFiles[i].equals( jpfName ) )
+                        otherJpfs.add( otherFiles[i] );
+                }
+                if ( otherJpfs.size() == 1 )
+                    CompilerUtil.error( 
"pageflow.error.overlapping-pageflows1",
+                            new String[] { (String)otherJpfs.get(0) } );
+                else if ( otherJpfs.size() == 2 )
+                    CompilerUtil.error( 
"pageflow.error.overlapping-pageflows2",
+                            new String[] { (String)otherJpfs.get(0), 
(String)otherJpfs.get(1) } );
+                else if ( otherJpfs.size() == 3 )
+                    CompilerUtil.error( 
"pageflow.error.overlapping-pageflows3",
+                            new String[] { (String)otherJpfs.get(0), 
(String)otherJpfs.get(1), (String)otherJpfs.get(2) } );
+                else if ( otherJpfs.size() > 3 )
+                    CompilerUtil.error( "pageflow.error.overlapping-pageflows",
+                            new String[] { (String)otherJpfs.get(0), 
(String)otherJpfs.get(1), (String)otherJpfs.get(2) } );
+            }
+
+            // we are catching and ignoring NetuiDocletException so that the 
compiler will
+            // continue to process and accumulate errors.
+            try
+            { checkTagPlacement( jpfClass ); }
+            catch ( NetuiDocletException e ) { }
+
+            try
+            { processController( jpfClass ); }
+            catch ( NetuiDocletException e ) { }
+
+            try
+            { processFormBeans( jpfClass ); }
+            catch ( NetuiDocletException e ) { }
+
+            try
+            { processActions( jpfClass ); }
+            catch ( NetuiDocletException e ) { }
+
+            // check for an explicit alternate location for the generated file
+            // for root or global controller only
+            if ( global || jpfClass.getContainingPackage().isDefaultPackage() )
+            {
+                String alternateLocation = getAlternateLocation( 
_strutsApp.getWebappRootPath(),
+                        _strutsApp.getStrutsConfigFile() );
+                if ( alternateLocation != null )
+                {
+                    if ( DocletContext.getInstance().isVerbose() )
+                    {
+                        System.out.println( "Using alternate config file 
location: " + alternateLocation );
+                    }                    
+                    _strutsApp.setStrutsConfigFile( new File( 
_strutsApp.getWebappRootPath() + alternateLocation ) );
+                }
+            }
+            
+            // write out the config file if we haven't gotten any errors
+            if ( !NetuiDocletTask.hasErrors( 
_strutsApp.getOriginalJpfSourceFile().toString() ) )
+                _strutsApp.writeToSource();
+        }
+        catch ( NetuiDocletException e )
+        {
+            // ignore, an error was added to the task
+        }
+        catch ( NoWebInfDirectoryException e )
+        {
+            CompilerUtil.error( e.getMessage() );
+        }
+        catch ( Exception e )
+        {
+            throw new XDocletException(e, e.getMessage() );
+        }
+        finally
+        {
+            _strutsApp = null;
+            _exceptionHandlers = null;
+            _isGlobal = false;
+        }
+    }
+
+    public void checkTagPlacement(XClass jpfClass)
+        throws XDocletException
+    {
+        checkTagPlacement( jpfClass.getDoc(), TAG_NAMESPACE, 
PageflowTags.VALID_CLASS_TAGS );
+
+        List fields = jpfClass.getFields();
+        Iterator fieldIter = fields.iterator();
+        while ( fieldIter.hasNext() )
+        {
+            XField field = (XField) fieldIter.next();
+            checkTagPlacement( field.getDoc(), TAG_NAMESPACE, 
PageflowTags.VALID_FIELD_TAGS );
+        }
+
+        List methods = jpfClass.getMethods();
+        Iterator methodIter = methods.iterator();
+        while ( methodIter.hasNext() )
+        {
+            XMethod method = (XMethod) methodIter.next();
+            XDoc doc = method.getDoc();
+            checkTagPlacement( doc, TAG_NAMESPACE, 
PageflowTags.VALID_METHOD_TAGS );
+            
+            // make sure any methods with a forward tag are really actions or 
exception handlers
+            XTag fwdTag = doc.getTag( FORWARD_TAG_FULL_NAME );
+            if ( fwdTag != null )
+            {
+                XTag actionTag = doc.getTag( ACTION_TAG_FULL_NAME );
+                if ( actionTag == null )
+                {
+                    XTag exTag = doc.getTag( EXCEPTION_HANDLER_TAG_FULL_NAME );
+                    if ( exTag == null )
+                    {
+                        CompilerUtil.error( fwdTag, 
"pageflow.error.inappropriate-forward-tag",
+                                new String[] { FORWARD_TAG_FULL_NAME, 
ACTION_TAG_FULL_NAME,
+                                               EXCEPTION_HANDLER_TAG_FULL_NAME 
} );
+                    }
+                }
+            }
+        }
+    }
+
+    private void checkTagPlacement( XDoc doc, String namespace, String[] valid 
)
+        throws XDocletException
+    {
+        // XTags are namespaced with a '.', not a ':'
+        String nsDot = namespace + ".";
+        int nsDotLength = nsDot.length();
+        List validList = Arrays.asList( valid );
+
+        List allTags = doc.getTags();
+        Iterator iter = allTags.iterator();
+        while( iter.hasNext() )
+        {
+            XTag tag = (XTag) iter.next();
+            if ( tag.getName().startsWith( nsDot ) )
+            {
+                String tagName = tag.getName().substring( nsDotLength );
+                if ( !validList.contains( tagName ) )
+                {
+                    try
+                    { CompilerUtil.error( tag, 
"compiler.error.invalid.tag.location", new String[] {tag.getName()} ); }
+                    catch ( NetuiDocletException e )
+                    { } // we want to continue here
+                }
+            }
+        }
+    }
+
+    public void processController( XClass jpfClass )
+        throws XDocletException
+    {
+        XTag jpfTag = jpfClass.getDoc().getTag( CONTROLLER_TAG_FULL_NAME );
+        if ( jpfTag != null )
+        {
+            // this tag isn't required, but validate it if it's there
+            PageflowTags.CONTROLLER_TAG_GRAMMAR.validateTag( jpfTag, jpfClass 
);
+            _strutsApp.setStrutsMerge( jpfTag.getAttributeValue( 
STRUTSMERGE_ATTR ) );
+
+            // if nested, check for a fwd with return-action
+            if ( "true".equals( jpfTag.getAttributeValue( NESTED_ATTR ) ) )
+            {
+                _strutsApp.setNestedPageFlow( true );
+
+                List fwdTags = jpfClass.getMethodTags( FORWARD_TAG_FULL_NAME, 
false );
+                boolean foundReturnAction = atLeastOneTagHasAttribute( 
fwdTags, RETURN_ACTION_ATTR );
+                if ( !foundReturnAction )
+                {
+                    // check the global forwards if we still didn't find one
+                    fwdTags = jpfClass.getDoc().getTags( FORWARD_TAG_FULL_NAME 
);
+                    foundReturnAction = atLeastOneTagHasAttribute( fwdTags, 
RETURN_ACTION_ATTR );
+                }
+                if ( !foundReturnAction )
+                {
+                    // last chance, check for a validation-error-forward
+                    fwdTags = jpfClass.getMethodTags( 
VALIDATION_ERROR_FORWARD_TAG_FULL_NAME, false );
+                    foundReturnAction = atLeastOneTagHasAttribute( fwdTags, 
RETURN_ACTION_ATTR );
+                }
+                if ( !foundReturnAction )
+                    CompilerUtil.error( jpfTag, 
"pageflow.error.no-return-action", null );
+            }
+        }
+
+        // check for a begin action
+        if ( !_isGlobal )
+        {
+            boolean foundBegin = false;
+            List methods = jpfClass.getMethods();
+            Iterator iter = methods.iterator();
+            while ( !foundBegin && iter.hasNext() )
+            {
+                XMethod method = (XMethod) iter.next();
+                if ( method.getName().equals( BEGIN_ACTION_NAME ) )
+                {
+                    XTag tag = method.getDoc().getTag(ACTION_TAG_FULL_NAME);
+                    if ( tag != null )
+                        foundBegin = true;
+                }
+            }
+            if ( !foundBegin )
+                CompilerUtil.error( jpfTag, "pageflow.error.no-begin-action", 
null );
+        }
+
+        // check for invalid tags
+        List fields = jpfClass.getFields();
+        Iterator fieldIter = fields.iterator();
+        while ( fieldIter.hasNext() )
+        {
+            XField field = (XField) fieldIter.next();
+            XDoc doc = field.getDoc();
+            for ( int i=0; i<INVALID_FIELD_TAGS.length; i++ )
+            {
+                if ( doc.hasTag( INVALID_FIELD_TAGS[i] ) )
+                {
+                    XTag badTag = doc.getTag( INVALID_FIELD_TAGS[i] );
+                    CompilerUtil.error( badTag, 
"compiler.error.portable.notsupported",
+                            new String[] {INVALID_FIELD_TAGS[i]} );
+                }
+            }
+
+            // also check for non-transient/static/serializable fields
+            if ( !field.isTransient() && !field.isStatic() &&
+                    !field.getType().isImplementingInterface( 
SERIALIZABLE_INTERFACE_NAME, true ) )
+            {
+                CompilerUtil.warning( field, 
"pageflow.warning.nonserializable-member-data", null );
+            }
+        }
+
+
+        // process the message resource tags
+        List tags = jpfClass.getDoc().getTags( MESSAGE_RESOURCES_TAG_FULL_NAME 
);
+        Iterator tagIter = tags.iterator();
+        while ( tagIter.hasNext() )
+        {
+            XTag tag = (XTag) tagIter.next();
+            PageflowTags.MSG_RES_TAG_GRAMMAR.validateTag( tag, jpfClass );
+            String resources = tag.getAttributeValue( RESOURCES_ATTR );
+            String key = tag.getAttributeValue( KEY_ATTR );
+            MessageResourcesModel mr = new MessageResourcesModel( resources, 
_strutsApp );
+            mr.setKey( key );
+            mr.setReturnNull( false );
+            _strutsApp.addMessageResources( mr );
+        }
+
+        // add global forwards and catches
+        checkForwardConflicts( jpfClass, jpfClass );
+        addForwards( jpfClass, _strutsApp, jpfClass );
+        addCatches( jpfClass, _strutsApp, jpfClass );
+    }
+
+    public void processActions( XClass jpfClass )
+        throws XDocletException
+    {
+        List methods = jpfClass.getMethods();
+        Iterator methodIter = methods.iterator();
+        while ( methodIter.hasNext() )
+        {
+            XMethod method = (XMethod) methodIter.next();
+            XTag actionTag = method.getDoc().getTag( ACTION_TAG_FULL_NAME );
+            if ( actionTag != null )
+            {
+                PageflowTags.ACTION_TAG_GRAMMAR.validateTag( actionTag, 
jpfClass );
+                List params = method.getParameters();
+                FormBeanModel formBean = null;
+                XClass paramType = null;
+                if ( params.size() > 0 )
+                {
+                    XParameter param = (XParameter) params.get(0);
+                    paramType = param.getType();
+                    boolean ok = true;
+                    if ( params.size() > 1 )
+                        ok = false;
+                    if ( ok )
+                    {
+                        if ( !paramType.isA( FORM_CLASS_NAME, true ) )
+                            ok = false;
+                    }
+                    if ( !ok )
+                        CompilerUtil.error( actionTag, 
"pageflow.error.action-method-wrong-arg",
+                                new String[] {FORM_CLASS_NAME} );
+
+                    // if this action takes a form we haven't seen yet, add it 
to the map
+                    String formType = CompilerUtil.getQualifiedName( 
param.getType() );
+                    formBean = _strutsApp.getFormBeanByType( formType );
+                    if ( formBean == null )
+                    {
+                        formBean = addFormBean( param.getType() );
+                    }
+
+                }
+
+                // check the return type
+                XClass returnClass = method.getReturnType().getType();
+                if ( !returnClass.isA( FORWARD_CLASS_NAME, true ) )
+                    CompilerUtil.error( actionTag, 
"pageflow.error.method-wrong-return-type",
+                            new String[] {FORWARD_CLASS_NAME} );
+
+                ActionModel action = new ActionModel( "/" + method.getName(), 
_strutsApp );
+                action.setType( jpfClass.getQualifiedName() );
+                if ( formBean != null )
+                    action.setFormBeanName( formBean.getName() );
+                action.setRoles( getActionRoles( actionTag, jpfClass ) );
+                action.setScope( actionTag.getAttributeValue( "scope" ) ); // 
TODO: constant?
+
+                Boolean readonly = null;
+                String readonlyVal = actionTag.getAttributeValue( 
READONLY_ATTR );
+                if ( readonlyVal != null )
+                {
+                    readonly = new Boolean( readonlyVal );
+                }
+                else
+                {
+                    readonlyVal = getControllerAttribute( jpfClass, 
READONLY_ATTR );
+                    if ( readonlyVal != null && readonlyVal.equalsIgnoreCase( 
"true" ) )
+                    {
+                        readonly = new Boolean( true );
+                    }
+                }
+                action.setReadonly( readonly != null ? readonly.booleanValue() 
: false );
+
+                String formMember = actionTag.getAttributeValue( FORM_ATTR );
+                if ( formMember != null )
+                {
+                    // make sure the action is not readonly
+                    if ( readonly != null && readonly.booleanValue() )
+                    {
+                        CompilerUtil.error( actionTag, 
"pageflow.error.readonly-writable-field-member",
+                                new String[] { FORM_ATTR } );
+                    }
+
+                    // need to get the fully qualified type of the field
+                    XField formField = jpfClass.getField( formMember );
+                    if ( formField == null )
+                        CompilerUtil.error( actionTag, 
"pageflow.error.unresolved-field",
+                                new String[] { formMember } );
+                    XClass formClass = formField.getType();
+                    if ( !formClass.isA( FORM_CLASS_NAME, true ) )
+                        CompilerUtil.error( actionTag, 
"pageflow.error.wrong-field-type",
+                                new String[] { formMember, FORM_CLASS_NAME } );
+                    
+                    // if we have a valid form attribute, make sure we take a 
parameter of the same type
+                    if ( formBean == null || paramType == null ||
+                            !paramType.isA( formClass.getQualifiedName(), true 
) )
+                    {
+                        CompilerUtil.error( actionTag, 
"pageflow.error.action-mismatched-form",
+                                new String[] { formMember, formClass.getName() 
} );
+                    }
+                    
+                    action.setFormMember( formMember);
+                }
+
+                Boolean loginRequired = null;
+                String loginRequiredVal = actionTag.getAttributeValue( 
LOGIN_REQUIRED_ATTR );
+                if ( loginRequiredVal != null )
+                {
+                    loginRequired = new Boolean( loginRequiredVal );
+                }
+                else
+                {
+                    loginRequiredVal = getControllerAttribute( jpfClass, 
LOGIN_REQUIRED_ATTR );
+                    if ( loginRequiredVal != null && 
loginRequiredVal.equalsIgnoreCase( "true" ) )
+                    {
+                        loginRequired = new Boolean( true );
+                    }
+                }
+                action.setLoginRequired( loginRequired != null ? 
loginRequired.booleanValue() : false );
+
+                checkForwardConflicts( method, jpfClass );
+                addForwards( method, action, jpfClass );
+                addCatches( method, action, jpfClass );
+
+                // if we have a validation-error-page see if we need to make a 
new forward for it
+                String validationErrorPage = actionTag.getAttributeValue( 
VALIDATION_ERROR_PAGE_ATTR );
+                if ( validationErrorPage != null )
+                {
+                    String inputFwd = null;
+                    List fwdTags = method.getDoc().getTags( 
FORWARD_TAG_FULL_NAME );
+                    Iterator fwdTagIter = fwdTags.iterator();
+                    boolean found = false;
+                    while ( !found && fwdTagIter.hasNext() )
+                    {
+                        XTag tag = (XTag) fwdTagIter.next();
+                        String fwdPath = tag.getAttributeValue( PATH_ATTR );
+                        if ( fwdPath != null && fwdPath.equals( 
validationErrorPage ) )
+                        {
+                            inputFwd = tag.getAttributeValue( NAME_ATTR );
+                            found = true;
+                        }
+                    }
+
+                    if ( !found )
+                    {
+                        inputFwd = VALIDATION_ERROR_PAGE_FWD_NAME;
+                        ForwardModel forward = new ForwardModel( inputFwd,
+                                getValidPath(validationErrorPage), _strutsApp 
);
+                        warnIfPathNotFound(actionTag, validationErrorPage);
+                        action.addForward( forward );
+                    }
+
+                    action.setInput( inputFwd );
+                }
+
+                // add a validation-error-forward if there is one, and make 
sure there is only one
+                XTag errorFwd = method.getDoc().getTag( 
VALIDATION_ERROR_FORWARD_TAG_FULL_NAME );
+                if ( errorFwd != null )
+                {
+                    
PageflowTags.VALIDATION_ERROR_FORWARD_TAG_GRAMMAR.validateTag( errorFwd, 
jpfClass );
+
+                    // also check for other regular forwards with the same name
+                    String name = errorFwd.getAttributeValue( NAME_ATTR );
+                    List otherFwds = method.getDoc().getTags( 
FORWARD_TAG_FULL_NAME );
+                    Iterator iter = otherFwds.iterator();
+                    while ( iter.hasNext() )
+                    {
+                        XTag otherFwd = (XTag) iter.next();
+                        String otherName = otherFwd.getAttributeValue( 
NAME_ATTR );
+                        if ( otherName != null && otherName.equals( name ) )
+                            CompilerUtil.error( errorFwd, 
"compiler.error.duplicate.errorFwd.fwd",
+                                    new String[] {name} );
+                    }
+
+                    List fwdList = new ArrayList();
+                    fwdList.add( errorFwd );
+                    addForwards( method, action, jpfClass, fwdList, null, null 
);
+                    action.setInput( name );
+                }
+
+                _strutsApp.addActionMapping( action );
+            }
+        }
+    }
+
+    protected List addForwards( XProgramElement xpe, ForwardContainer 
container, XClass jpfClass )
+        throws XDocletException
+    {
+        XDoc doc = xpe.getDoc();
+
+        // get explicit forward tags for this element
+        List forwardTags = doc.getTags( FORWARD_TAG_FULL_NAME );
+        List otherForwards = addForwards( xpe, container, jpfClass, 
forwardTags, null, null );
+
+        // get forwards from exception-handler methods referenced in jpf:catch 
tags
+        forwardTags = new ArrayList();
+        List exTags = doc.getTags( CATCH_TAG_FULL_NAME );
+        Map handlers = getExceptionHandlers( jpfClass );
+        Iterator exIter = exTags.iterator();
+        while ( exIter.hasNext() )
+        {
+            XTag exTag = (XTag) exIter.next();
+            String methodName = exTag.getAttributeValue( METHOD_ATTR );
+            if ( methodName != null )
+            {
+                XMethod handler = (XMethod) handlers.get( methodName );
+                if ( handler == null )
+                    CompilerUtil.error( exTag, 
"pageflow.error.unresolved-exception-handler",
+                            new String[] { methodName } );
+
+                List handlerFwdTags = handler.getDoc().getTags( 
FORWARD_TAG_FULL_NAME );
+                addForwards( xpe, container, jpfClass, handlerFwdTags, 
handler.getName(), otherForwards );
+            }
+        }
+        
+        return otherForwards;
+    }
+
+    protected List addForwards( XProgramElement xpe, ForwardContainer 
container,
+                                XClass jpfClass, List forwardTags, String 
handler, List currentForwards )
+        throws XDocletException
+    {
+        if ( currentForwards == null )
+            currentForwards = new ArrayList();
+
+        // see if we're in a nested pageflow
+        XTag jpfTag = jpfClass.getDoc().getTag( CONTROLLER_TAG_FULL_NAME );
+        boolean nested = false;
+        if ( jpfTag != null )
+        {
+            String nestedValue = jpfTag.getAttributeValue( NESTED_ATTR );
+            nested = new Boolean( nestedValue ).booleanValue();
+        }
+
+        // iterate over all the forwards and process them
+        Iterator fwdIter = forwardTags.iterator();
+        while ( fwdIter.hasNext() )
+        {
+            XTag fwdTag = (XTag)fwdIter.next();
+            PageflowTags.FORWARD_TAG_GRAMMAR.validateTag( fwdTag, jpfClass );
+            String name = fwdTag.getAttributeValue( NAME_ATTR );
+
+            String path = fwdTag.getAttributeValue( PATH_ATTR );
+            warnIfPathNotFound( fwdTag, path );
+
+            ForwardModel forward = new ForwardModel( name, getValidPath(path), 
_strutsApp );
+
+            if ( handler != null )
+            {
+                forward.setComment( "forward \"" + forward.getName() + "\"" + 
" from exception-handler " + handler );  // @TODOsp1 I18N the comment
+            }
+
+            String redirect = fwdTag.getAttributeValue( REDIRECT_ATTR );
+            if ( redirect == null )
+                forward.setRedirect( false, false );
+            else
+                forward.setRedirect( new Boolean( redirect ).booleanValue(), 
true );
+
+            forward.setContextRelative( path != null && path.startsWith( "/" ) 
);
+            String returnTo = fwdTag.getAttributeValue( RETURN_TO_ATTR );
+            if ( returnTo != null )
+            {
+                if ( returnTo.equals( RETURN_TO_PAGE_LEGACY_STR ) ||
+                        returnTo.equals( RETURN_TO_CURRENT_PAGE_STR ) ||
+                        returnTo.equals( RETURN_TO_PREVIOUS_PAGE_STR ) )
+                    forward.setReturnToPage( true );
+                else if ( returnTo.equals( RETURN_TO_ACTION_LEGACY_STR ) ||
+                        returnTo.equals( RETURN_TO_PREVIOUS_ACTION_STR ) )
+                    forward.setReturnToAction( true );
+                forward.setPath( returnTo );
+            }
+            String returnAction = fwdTag.getAttributeValue( RETURN_ACTION_ATTR 
);
+            if ( returnAction != null )
+            {
+                // make sure we're in a nested pageflow
+                if ( !nested )
+                {
+                    CompilerUtil.error( fwdTag, 
"pageflow.error.only-valid-in-nested",
+                            new String[] { RETURN_ACTION_ATTR } );
+                }
+
+                // make sure this is a valid java identifier
+                if ( !isJavaIdentifier( returnAction ) )
+                    CompilerUtil.error( fwdTag, 
"pageflow.error.attr-java-identifier",
+                            new String[] { RETURN_ACTION_ATTR } );
+
+                forward.setIsNestedReturn( true );
+                forward.setPath( returnAction );
+
+                // only check return form member/type for a return action
+                String returnFormType = fwdTag.getAttributeValue( 
RETURN_FORM_TYPE_ATTR );
+                if ( returnFormType != null )
+                {
+                    XClass q = jpfClass.qualify( returnFormType );
+                    if ( q == null || q.getClass().getName().endsWith( 
"UnknownClass" ) )
+                        CompilerUtil.error( fwdTag, 
"pageflow.error.unresolved-type", new String[] {returnFormType} );
+                    if ( !q.isA( FORM_CLASS_NAME, true ) )
+                        CompilerUtil.error( fwdTag, 
"compiler.error.wrong.type", new String[] {returnFormType, FORM_CLASS_NAME} );
+                    forward.setReturnFormType( CompilerUtil.getQualifiedName( 
q ) );
+                }
+
+                String returnFormMember = fwdTag.getAttributeValue( 
RETURN_FORM_ATTR );
+                if ( returnFormMember != null )
+                {
+                    // need to get the fully qualified type of the field
+                    XField returnFormField = jpfClass.getField( 
returnFormMember );
+                    if ( returnFormField == null )
+                        CompilerUtil.error( fwdTag, 
"pageflow.error.unresolved-field",
+                                new String[] { returnFormMember } );
+                    XClass returnFormClass = returnFormField.getType();
+                    if ( !returnFormClass.isA( FORM_CLASS_NAME, true ) )
+                        CompilerUtil.error( fwdTag, 
"pageflow.error.wrong-field-type",
+                                new String[] { returnFormMember, 
FORM_CLASS_NAME } );
+                    String returnFormClassName = 
CompilerUtil.getQualifiedName( returnFormClass );
+                    forward.setReturnFormType( returnFormClassName );
+                    forward.setReturnFormMember( returnFormMember );
+                }
+            }
+
+            container.addForward( forward );
+            currentForwards.add( fwdTag );
+        }
+
+        return currentForwards;
+    }
+
+    public void addCatches( XProgramElement xpe, ExceptionContainer container, 
XClass jpfClass )
+        throws XDocletException
+    {
+        XDoc doc = xpe.getDoc();
+        List exTags = doc.getTags( CATCH_TAG_FULL_NAME );
+        Map handlers = getExceptionHandlers( jpfClass );
+        Iterator exIter = exTags.iterator();
+        while ( exIter.hasNext() )
+        {
+            XTag exTag = (XTag) exIter.next();
+            PageflowTags.CATCH_TAG_GRAMMAR.validateTag( exTag, jpfClass );
+            String typeAttr = exTag.getAttributeValue( TYPE_ATTR );
+            
+            // xjavadoc sometimes does not understand '$' to denote inner 
classes, '.' is safer
+            typeAttr = typeAttr.replace( '$', '.' );
+            XClass q = jpfClass.qualify( typeAttr );
+            
+            if ( q == null || q.getClass().getName().endsWith( "UnknownClass" 
) )
+            {
+                // sometimes an inner class will not resolve correctly without 
the package name,
+                // so try again, assuming the exception is in the same package 
as the jpf
+                XPackage pkg = jpfClass.getContainingPackage();
+                q = jpfClass.qualify( pkg.getName() + "." +  typeAttr );
+                
+                if ( q == null || q.getClass().getName().endsWith( 
"UnknownClass" ) )                
+                    CompilerUtil.error( exTag, 
"pageflow.error.unresolved-type", new String[] {typeAttr} );
+            }
+            if ( !q.isA( THROWABLE_CLASS_NAME, true ) )
+                CompilerUtil.error( exTag, "compiler.error.wrong.type", new 
String[] {typeAttr, THROWABLE_CLASS_NAME} );
+            String type = CompilerUtil.getQualifiedName( q );
+
+            String pathAttr = exTag.getAttributeValue( PATH_ATTR );
+            warnIfPathNotFound( exTag, pathAttr );
+            String path = null;
+            if ( pathAttr != null )
+                path = getValidPath( pathAttr );
+            String handler = exTag.getAttributeValue( METHOD_ATTR );
+            if ( handler != null )
+            {
+                // check that the method handles the right exception type
+                XMethod method = (XMethod) handlers.get( handler );
+                if ( method == null )
+                    CompilerUtil.error( exTag, 
"pageflow.error.unresolved-exception-handler",
+                            new String[] { handler } );
+                XParameter firstParam = 
(XParameter)method.getParameters().get(0);                
+                if ( !q.isA( firstParam.getType().getQualifiedName() ) )
+                    CompilerUtil.error( exTag, 
"pageflow.error.incompatible-exception-handler",
+                            new String[] { handler, q.getQualifiedName() } );
+            }
+            String key = exTag.getAttributeValue( MESSAGE_KEY_ATTR );
+            String message = exTag.getAttributeValue( MESSAGE_ATTR );
+
+            ExceptionModel ex = new ExceptionModel( type, path, handler, 
message, key, _strutsApp );
+            container.addException( ex );
+        }
+    }
+
+    protected Map getExceptionHandlers( XClass jpfClass )
+        throws XDocletException
+    {
+        if ( _exceptionHandlers == null )
+        {
+            _exceptionHandlers = new HashMap();
+            List methods = jpfClass.getMethods();
+            Iterator iter = methods.iterator();
+            while ( iter.hasNext() )
+            {
+                XMethod method = (XMethod) iter.next();
+                XTag exTag = method.getDoc().getTag( 
EXCEPTION_HANDLER_TAG_FULL_NAME );
+                if ( exTag != null )
+                {
+                    PageflowTags.EX_HANDLER_TAG_GRAMMAR.validateTag( exTag, 
jpfClass );
+                    
+                    // make sure there is no catch tag on the exception handler
+                    XTag catchTag = method.getDoc().getTag( 
CATCH_TAG_FULL_NAME );
+                    if ( catchTag != null )
+                    {
+                        CompilerUtil.error( exTag, 
"pageflow.error.exception-handler-catch",
+                                new String[] { CATCH_TAG_FULL_NAME } );
+                    }
+                    
+                    // now check parameters on the handler method
+                    List params = method.getParameters();
+                    if ( params.size() != 4 )
+                    {
+                        CompilerUtil.error( exTag, 
"pageflow.error.exception-method-wrong-arg-count", new String[] {"4"} );
+                    }
+                    else
+                    {
+                        if ( !((XParameter)params.get(0)).getType().isA( 
THROWABLE_CLASS_NAME, true ) )
+                            CompilerUtil.error( exTag, 
"pageflow.error.exception-method-wrong-exception-arg",
+                                    new String[] { THROWABLE_CLASS_NAME } );
+                        else if ( !((XParameter)params.get(1)).getType().isA( 
STRING_CLASS_NAME ) )
+                            CompilerUtil.error( exTag, 
"pageflow.error.exception-method-wrong-arg-type",
+                                    new String[] { "2", STRING_CLASS_NAME } );
+                        else if ( !((XParameter)params.get(2)).getType().isA( 
STRING_CLASS_NAME ) )
+                            CompilerUtil.error( exTag, 
"pageflow.error.exception-method-wrong-arg-type",
+                                    new String[] { "3", STRING_CLASS_NAME } );
+                        else if ( !((XParameter)params.get(3)).getType().isA( 
FORM_CLASS_NAME, true ) )
+                            CompilerUtil.error( exTag, 
"pageflow.error.exception-method-wrong-arg-type2",
+                                    new String[] { "4", FORM_CLASS_NAME, 
NETUI_FORM_CLASS_NAME } );
+                    }
+
+                    // check the return type
+                    XClass returnClass = method.getReturnType().getType();
+                    if ( !returnClass.isA( FORWARD_CLASS_NAME, true ) )
+                        CompilerUtil.error( exTag, 
"pageflow.error.method-wrong-return-type",
+                                new String[] {FORWARD_CLASS_NAME} );
+
+                    if ( _exceptionHandlers.get( method.getName() ) != null )
+                    {
+                        CompilerUtil.error( exTag, 
"pageflow.error.duplicate-exception-handler", null );
+                    }
+                    _exceptionHandlers.put( method.getName(), method );
+                }
+            }
+        }
+        return _exceptionHandlers;
+    }
+
+    protected String getControllerAttribute( XClass jpfClass, String attrName )
+        throws XDocletException
+    {
+        String value = null;
+        XTag jpfTag = jpfClass.getDoc().getTag( CONTROLLER_TAG_FULL_NAME );
+        if ( jpfTag != null )
+        {
+            value = jpfTag.getAttributeValue( attrName );
+        }
+        return value;
+    }
+
+    protected String getActionRoles( XTag actionTag, XClass jpfClass )
+    {
+        String rolesAllowed = null;
+        String actionRolesAllowed = actionTag.getAttributeValue( 
ROLES_ALLOWED_ATTR );
+
+        String jpfRolesAllowed = null;
+        XTag jpfTag = jpfClass.getDoc().getTag( CONTROLLER_TAG_FULL_NAME );
+        if ( jpfTag != null )
+            jpfRolesAllowed = jpfTag.getAttributeValue( ROLES_ALLOWED_ATTR );
+
+        if ( actionRolesAllowed != null || jpfRolesAllowed != null )
+        {
+            if ( actionRolesAllowed == null && jpfRolesAllowed != null )
+            {
+                rolesAllowed = jpfRolesAllowed;
+            }
+            else if ( actionRolesAllowed != null && jpfRolesAllowed == null )
+            {
+                rolesAllowed = actionRolesAllowed;
+            }
+            else
+            {
+                // merge the lists
+                List roles = new ArrayList();
+                StringBuffer buf = new StringBuffer();
+                StringTokenizer actionSt = new StringTokenizer( 
actionRolesAllowed );
+                while ( actionSt.hasMoreElements() )
+                {
+                    roles.add( actionSt.nextToken() );
+                }
+                StringTokenizer jpfSt = new StringTokenizer( jpfRolesAllowed );
+                while ( jpfSt.hasMoreElements() )
+                {
+                    String role = jpfSt.nextToken();
+                    if ( !roles.contains( role ) )
+                        roles.add( role );
+                }
+                for ( int i=0; i<roles.size(); i++ )
+                {
+                    if ( i>0 )
+                        buf.append( "," );
+                    buf.append( (String)roles.get(i) );
+                }
+                rolesAllowed = buf.toString();
+            }
+        }
+        return rolesAllowed;
+    }
+
+    public void processFormBeans( XClass jpfClass )
+        throws XDocletException
+    {
+        List formBeans = new ArrayList();
+
+        // get the form bean inner classes
+        List innerClasses = jpfClass.getInnerClasses();
+        Iterator innerIter = innerClasses.iterator();
+        while ( innerIter.hasNext() )
+        {
+            XClass innerClass = (XClass)innerIter.next();
+            if ( innerClass.isA( FORM_CLASS_NAME, true ) )
+                formBeans.add( innerClass );
+        }
+
+        Iterator formIter = formBeans.iterator();
+        while ( formIter.hasNext() )
+        {
+            XClass formClass = (XClass)formIter.next();
+            addFormBean( formClass );
+        }
+    }
+
+    private FormBeanModel addFormBean( XClass formClass )
+    {
+        String formType = CompilerUtil.getQualifiedName( formClass );
+        String formBeanName = _strutsApp.getFormNameForType( formType );
+        FormBeanModel formBean = new FormBeanModel( formBeanName, formType, 
_strutsApp );
+        _strutsApp.addFormBean( formBean );
+        return formBean;
+    }
+    
+    private void checkForwardConflicts( XProgramElement xpe, XClass jpfClass )
+        throws XDocletException
+    {
+        XDoc doc = xpe.getDoc();
+
+        // get explicit forward tags for this element
+        List elementFwdTags = doc.getTags( FORWARD_TAG_FULL_NAME );
+        
+        // get forwards from any handlers
+        Map handlerForwards = getForwardsFromCatches( xpe, jpfClass );
+        
+        // if this is not the controller class itself, add all the global 
forwards
+        // to a separate map; we need them to check local forwards for name 
conflicts,
+        // but not to check forwards from handlers for forward conflicts 
+        Map combinedForwards = new HashMap();
+        combinedForwards.putAll( handlerForwards );
+        if ( xpe != jpfClass )
+        {
+            combinedForwards.putAll( getForwardsFromCatches( jpfClass, 
jpfClass ) );
+        }
+            
+        // check name conflicts between explicit forwards and forwards from 
handlers
+        // NOTE: doing all these nested loops to keep track of what handler's 
forwards
+        //       are being considered so that we can fill out the error 
message correctly
+        Iterator fwdTagIter = elementFwdTags.iterator();
+        while ( fwdTagIter.hasNext() )
+        {
+            XTag tag = (XTag) fwdTagIter.next();
+            String name = tag.getAttributeValue( NAME_ATTR );
+            
+            Iterator handlerIter = combinedForwards.keySet().iterator();
+            while ( handlerIter.hasNext() )
+            {
+                XTag handlerTag = (XTag)handlerIter.next();
+                String handler = handlerTag.getAttributeValue( METHOD_ATTR );
+                List handlerFwdTags = (List)combinedForwards.get( handlerTag );
+                
+                Iterator handlerFwdIter = handlerFwdTags.iterator();
+                while ( handlerFwdIter.hasNext() )
+                {
+                    XTag handlerFwdTag = (XTag) handlerFwdIter.next();
+                    String otherName = handlerFwdTag.getAttributeValue( 
NAME_ATTR );
+                    if ( name.equals( otherName ) )
+                    {
+//                        pageflow.error.duplicate-attr2 = Duplicate {0} tag 
on method {3} (referenced from {4}) with {1}="{2}".
+                        CompilerUtil.error( tag, 
"pageflow.error.duplicate-attr2", 
+                                new String[] { FORWARD_TAG_NAME, NAME_ATTR, 
name, handler, CATCH_TAG_FULL_NAME } );
+                    }
+                }
+            }
+        }
+        
+        // check conflicts between forwards on handlers: for each handler on 
this program element,
+        // check each of its forwards against the list of forwards from other 
handlers
+        Iterator handlerIter = handlerForwards.keySet().iterator();
+        while ( handlerIter.hasNext() )
+        {
+            XTag handlerTag = (XTag)handlerIter.next();
+            String handler = handlerTag.getAttributeValue( METHOD_ATTR );
+            List handlerFwdTags = (List)handlerForwards.get( handlerTag );
+                
+            Iterator handlerFwdIter = handlerFwdTags.iterator();
+            while ( handlerFwdIter.hasNext() )
+            {
+                XTag tag = (XTag) handlerFwdIter.next();
+                
+                Iterator otherHandlers = handlerForwards.keySet().iterator();
+                while ( otherHandlers.hasNext() )
+                {
+                    XTag otherHandlerTag = (XTag) otherHandlers.next();
+                    String otherHandler = otherHandlerTag.getAttributeValue( 
METHOD_ATTR );
+                    if ( !handler.equals( otherHandler ) )
+                    {
+                        List otherHandlerFwdTags = (List)handlerForwards.get( 
otherHandlerTag );
+//                        pageflow.error.duplicate-exception-handler-forwards 
= \
+//                        The specified exception-handler method {0} contains 
a forward named "{2}" which conflicts with a forward in \
+//                        exception-handler {1}.
+                        String conflictingFwd = findConflictingForward( tag, 
otherHandlerFwdTags );
+                        if ( conflictingFwd != null  )
+                            CompilerUtil.error( handlerTag, 
"pageflow.error.duplicate-exception-handler-forwards",
+                                    new String[] { handler, otherHandler, 
conflictingFwd } );
+                    }
+                }
+            }
+        }
+        
+        
+    }
+
+    private Map getForwardsFromCatches( XProgramElement xpe, XClass jpfClass )
+        throws XDocletException
+    {
+        Map handlers = getExceptionHandlers( jpfClass );
+        Map forwards = new HashMap();
+        
+        XDoc doc = xpe.getDoc();
+        
+        // TODO: refactor to share code with addForwards?
+        List catchTags = doc.getTags( CATCH_TAG_FULL_NAME );
+        
+        Iterator iter = catchTags.iterator();
+        while ( iter.hasNext() )
+        {
+            XTag tag = (XTag) iter.next();
+            String handlerName = tag.getAttributeValue( METHOD_ATTR );
+            if ( handlerName != null )
+            {
+                XMethod handler = (XMethod)handlers.get( handlerName );
+                
+                if ( handler == null )
+                    CompilerUtil.error( tag, 
"pageflow.error.unresolved-exception-handler",
+                            new String[] { handlerName } );
+
+                List handlerFwdTags = handler.getDoc().getTags( 
FORWARD_TAG_FULL_NAME );
+                forwards.put( tag, handlerFwdTags );
+            }
+        }
+        
+        return forwards;
+    }
+
+    private String findConflictingForward(XTag fwdTag, List currentForwards)
+    {
+        if ( currentForwards.size() == 0 )
+            return null;
+        
+        String name = fwdTag.getAttributeValue( NAME_ATTR );
+        Collection attrs = fwdTag.getAttributeNames();
+        Iterator iter = currentForwards.iterator();
+        while ( iter.hasNext() )
+        {
+            XTag otherTag = (XTag) iter.next();
+            String otherName = otherTag.getAttributeValue( NAME_ATTR );
+            
+            // only check forwards of the same name
+            if ( otherName.equals( name ) )
+            {
+                Collection otherAttrs = otherTag.getAttributeNames();
+                
+                // if they have different number of attributes, they are 
conflicting
+                if ( otherAttrs.size() != attrs.size() )
+                    return name;
+                
+                Iterator attrIter = attrs.iterator();
+                while ( attrIter.hasNext() )
+                {
+                    String attr = (String)attrIter.next();
+                    String value = fwdTag.getAttributeValue( attr );
+                    String otherValue = otherTag.getAttributeValue( attr );
+                    
+                    // as soon as we find a difference, we have a conflict
+                    if ( otherValue == null || !otherValue.equals( value ) )
+                        return name;
+                }
+            }
+        }
+        return null;
+    }
+    
+    private void warnIfPathNotFound( XTag tag, String path )
+    {
+        if ( path == null || isAbsoluteURL(path) ||
+                ( !path.endsWith(JSP_EXTENSION) && 
!path.endsWith(HTM_EXTENSION) &&
+                  !path.endsWith(HTML_EXTENSION) && 
!path.endsWith(PAGEFLOW_EXTENSION) ) )
+            return;
+
+        String base = null;
+        if ( path.startsWith( "/" ) )
+        {
+            base = _strutsApp.getWebappRootPath();
+        }
+        else
+        {
+            try
+            {
+                base = _strutsApp.getOriginalJpfSourceFile().getParent();
+            }
+            catch ( Exception e )
+            {
+                //ignore
+            }
+        }
+
+        if ( base != null )
+        {
+            File test = new File( base + File.separatorChar + path );
+            if ( !test.exists() )
+                CompilerUtil.warning( tag, "pageflow.warning.file-not-found", 
new String[] { path } );
+        }
+    }
+
+    private String getValidPath( String path )
+    {
+        String result = null;
+
+        if ( path == null || path.length() == 0 )
+            result = "";
+        else if ( path.startsWith( "/" ) || isAbsoluteURL( path ) )
+            result = path;
+        else
+            result = "/" + path;
+        return result;
+    }
+
+    public static boolean isAbsoluteURL( String path )
+    {
+        try
+        {
+            return new URI( path ).getScheme() != null;
+        }
+        catch ( URISyntaxException e )
+        {
+            // ignore
+        }
+
+        return false;
+    }
+
+    public static boolean isJavaIdentifier(String s)
+    {
+        if (s.length() == 0 || !Character.isJavaIdentifierStart(s.charAt(0)))
+        {
+            return false;
+        }
+        for (int i=1; i<s.length(); i++)
+        {
+            if (!Character.isJavaIdentifierPart(s.charAt(i)))
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public XDocletStrutsApp getStrutsApp() { return _strutsApp; }
+
+    private String getAlternateLocation( String webappRootPath, File file )
+        throws XDocletException
+    {
+        File webXmlFile = new File( webappRootPath + "/" + WEBINF_DIR_NAME + 
"/web.xml" );
+        
+        try
+        {
+            WebAppDocument webXml = WebAppDocument.Factory.parse( webXmlFile );
+            WebAppDocument.WebApp.Servlet[] servlets =  
webXml.getWebApp().getServletArray();
+            
+            for ( int i = 0; i < servlets.length; i++ )
+            {
+                WebAppDocument.WebApp.Servlet servlet = servlets[i];
+                
+                if ( servlet.getServletName().equals( "action" ) )
+                {
+                    InitParamType[] initParams = servlet.getInitParamArray();
+                    
+                    for ( int j = 0; j < initParams.length; j++ )
+                    {
+                        String paramValue = initParams[j].getParamValue();
+
+                        //
+                        // If the referenced struts-config file has the same 
name as the file
+                        // we're going to generate, use the referenced file 
(its location may be
+                        // different than our default location).
+                        //
+                        if ( paramValue.indexOf( file.getName() ) != -1 )
+                        {
+                            //
+                            // This may be a comma-separated list of files.  
Find the right one.
+                            //
+                            if ( paramValue.indexOf( "," ) != -1 )
+                            {
+                                String[] files = paramValue.split( "," );
+                                for ( int k = 0; k < files.length; ++k )
+                                {
+                                    if ( files[k].indexOf( file.getName() ) != 
-1 )
+                                    {
+                                        return files[k].trim();
+                                    }
+                                }
+                            }
+                            else
+                            {
+                                return paramValue;
+                            }
+                        }
+                    }
+                }
+            }            
+        }
+        catch ( Exception e )
+        {
+            CompilerUtil.error( "Could not read web.xml at " + webXmlFile + ": 
" + e.getMessage() );
+        }
+        
+        return null;
+    }
+    
+    private boolean atLeastOneTagHasAttribute( List tags, String attribute )
+    {
+        Iterator tagIter = tags.iterator();
+        boolean foundTag = false;
+        while ( !foundTag && tagIter.hasNext() )
+        {
+            XTag fwdTag = (XTag) tagIter.next();
+            if ( fwdTag.getAttributeValue( attribute ) != null )
+                foundTag = true;
+        }
+        return foundTag;
+    }
+    */
+    
+    
+    public static NetuiSubTask get()
+    {
+        SubTask subtask = DocletContext.getInstance().getActiveSubTask();
+        assert subtask instanceof NetuiSubTask : subtask.getClass().getName();
+        return ( NetuiSubTask ) subtask;
+    }
+
+    public XJavaDoc getXJavaDoc()
+    {
+        return super.getXJavaDoc();
+    }
+
+    public SourceClass getCurrentSourceClass()
+    {
+        return _currentSourceClass;
+    }
+}

Propchange: 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/NetuiSubTask.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/XDocletCompilerUtils.java
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/XDocletCompilerUtils.java?view=auto&rev=157713
==============================================================================
--- 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/XDocletCompilerUtils.java
 (added)
+++ 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/XDocletCompilerUtils.java
 Tue Mar 15 23:14:32 2005
@@ -0,0 +1,95 @@
+/*
+ * 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.xdoclet;
+
+import org.apache.beehive.netui.compiler.typesystem.util.SourcePosition;
+import xjavadoc.SourceClass;
+import xjavadoc.XClass;
+import xjavadoc.XJavaDoc;
+import xjavadoc.XPackage;
+
+import java.text.MessageFormat;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ResourceBundle;
+
+public class XDocletCompilerUtils
+{
+    private static final ResourceBundle MESSAGES =
+            ResourceBundle.getBundle( 
XDocletCompilerUtils.class.getPackage().getName() + ".Messages" );
+    
+    public static void addError( SourcePosition sourcePosition, String 
messageKey, String[] args )
+    {
+        assert sourcePosition != null;
+        String message = getMessage( messageKey, args );
+        NetuiDocletTask.addError( message, sourcePosition );
+    }
+    
+    public static void addWarning( SourcePosition sourcePosition, String 
messageKey, String[] args )
+    {
+        assert sourcePosition != null;
+        String message = getMessage( messageKey, args );
+        NetuiDocletTask.addWarning( message, sourcePosition );
+    }
+    
+    public static String getMessage( String messageKey, String[] args )
+    {
+        String message = MESSAGES.getString( messageKey );
+        if ( args != null ) message = MessageFormat.format( message, args );
+        return message;
+    }
+    
+    public static XClass getXClass( String typeName )
+    {
+        if ( typeName.endsWith( ".class" ) ) typeName = typeName.substring( 0, 
typeName.length() - 6 );
+        XJavaDoc xJavaDoc = NetuiSubTask.get().getXJavaDoc();
+        XClass type = xJavaDoc.getXClass( typeName );
+        if ( isUnknownClass( type ) ) type = xJavaDoc.getXClass( "java.lang." 
+ typeName );
+        
+        //
+        // If it's still unknown, try to resolve it against imports in the 
current source file.
+        //
+        if ( isUnknownClass( type ) && typeName.indexOf( '.' ) == -1 )
+        {
+            SourceClass sourceClass = 
NetuiSubTask.get().getCurrentSourceClass();
+            List importedClasses = sourceClass.getImportedClasses();
+            
+            for ( Iterator i = importedClasses.iterator(); i.hasNext(); )
+            {
+                XClass importedClass = ( XClass ) i.next();
+                if ( importedClass.getName().equals( typeName ) ) return 
importedClass;
+            }
+            
+            List importedPackages = sourceClass.getImportedPackages();
+            
+            for ( Iterator i = importedPackages.iterator(); i.hasNext(); )
+            {
+                XPackage importedPackage = ( XPackage ) i.next();
+                type = xJavaDoc.getXClass( importedPackage.getName() + '.' + 
typeName );
+                if ( ! isUnknownClass( type ) ) return type;
+            }
+        }
+        
+        return type;
+    }
+    
+    public static boolean isUnknownClass( XClass xclass )
+    {
+        return xclass == null || xclass.getClass().getName().equals( 
"xjavadoc.UnknownClass" );
+    }
+}

Propchange: 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/XDocletCompilerUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/XDocletUtils.java
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/XDocletUtils.java?view=auto&rev=157713
==============================================================================
--- 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/XDocletUtils.java
 (added)
+++ 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/XDocletUtils.java
 Tue Mar 15 23:14:32 2005
@@ -0,0 +1,36 @@
+/*
+ * 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.xdoclet;
+
+import xjavadoc.XClass;
+import xjavadoc.XProgramElement;
+
+public class XDocletUtils
+{
+    public static XClass getOutermostClass( XProgramElement element )
+    {
+        XClass containingClass;
+        while ( ( containingClass = element.getContainingClass() ) != null )
+        {
+            element = containingClass;
+        }
+        
+        assert element instanceof XClass : element.getClass().getName();
+        return ( XClass ) element;
+    }
+}

Propchange: 
incubator/beehive/trunk/netui/src/compiler-xdoclet/org/apache/beehive/netui/xdoclet/XDocletUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to