Friday, November 28, 2014

The Commented Source

Team. commenting the source took me exactly one-hour. Remember. I use the bird foraging approach when working on a computer. Hunt-Peck-Think. It works fairly well although I found a few typos in the meager source comments which I had already provided.

I hope you enjoyed your Thanksgiving. If you get a chance consider doing some community service over the holidays. It can be very rewarding. We should be more than one dimensional as software engineers and have a social conscience. Remember, "there but for the Grace of God go I", the next time you see someone pushing all of their possessions in a shopping cart. This world is not always fair and just.

The source is below. So Have a Great Weekend. It is great working with you. La-La.

//BEGIN JAVA SOURCE
//CONTROLLER APPLICATION BUNDLE (CAB)
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cab;
/**
 * The CAB eventually will be the kernel of the CABOOSE general purpose servlet.
 * Implicit Contract Requirements and Guidelines:
 * The CAB contracts with support classes that have rendering methods which
 * return String content. These methods also must have the signature
 *  public String methodName( java.util.HashMap<String,String> aMapParameter )
 * by implicit contract. If they do not, the reflection activities which
 * automatically invoke them will fail since they cannot find the requested
 * method. Class, method, tile replacement, and stencil filename identifiers are
 * all stored in a file called directory.xml which contain a mapping between
 * each item.
 *
 * @author Jody Sharpe
 */
public class CAB {
    //Simulated URL String. We will eventually get all of our input from the
    //the servlet's Request object.
    String request = "?project=caboose&module=skeleton&create_date=10.30.2014";
    //A data structure for holding a description of the page, stencil, and tile
    //directory. It is keyed by the page name. Each value in the structure is a
    //ViewModel. See the description of this inner class for information on its
    //content and structure.
    java.util.HashMap<String,ViewModel> aDirectoryMap = null;
   
    //private inner class representing a model of a single view which the
    //controller can return.
    private class ViewModel {
        //The stencil filename.
        private String theStencilName = null;
        //A data structure which holds the tile identifier as a key and the name
        //of the class and method for rendering the the tile as a
        //comma seperated value
        private java.util.HashMap<String,String> theTileRendererMappings = null;
       
        //This method assigns the stencil filename
        void settingTheStencilName( String aStencilName ){
            theStencilName = aStencilName;           
        }
       
        //This method assigns the tile renderer mappings
        void settingTheTileRendererMappings( java.util.HashMap<String,String> aSetOfTileRendererMappings ){
            theTileRendererMappings = aSetOfTileRendererMappings;           
        }
       
        //This method returns the stencil file name
        String gettingTheStencilName(){
            return( theStencilName );           
        }
       
        //This method retruns the tile renderer mappings data structure
        java.util.HashMap<String,String> gettingTheTileRendererMappings(){
            return( theTileRendererMappings );           
        }
    }
   
    //This method extracts the content of a stencil from the file system based
    //upon a file name. In the future this method will need adapting so it
    //retrieves the proper file in a web server's file system using
    //the servlet context.
    String gettingTheResponseStencil(String aViewFileName) throws Exception {
        java.io.BufferedReader aStencilReader = new java.io.BufferedReader(new java.io.FileReader(aViewFileName));
        String theStencilContent = "", theNextLine = null;
        while ((theNextLine = aStencilReader.readLine()) != null) {
            theStencilContent += theNextLine;
        }
        return (theStencilContent);
    }
    //This method extracts the name and value pairs from the input query string.
    //We assume that it is not url encoded. For the generic servlet edition of
    //the cab, this method will not be useful. But it might be of use for a
    //command-line based edition of the cab for report writing or rendering
    //windowing applications.
    java.util.HashMap<String, String> mappingTheRequestNameValuePairs(String aRequest) {
        java.util.HashMap<String, String> aMap = new java.util.HashMap<String, String>();
        aRequest = aRequest.replace("?", "");
        String[] theNameValuePairs = aRequest.split("&");
        for (String aNameValuePair : theNameValuePairs) {
            final int theName = 0, theValue = 1;
            String[] aTuple = aNameValuePair.split("=");
            aMap.put(aTuple[theName], aTuple[theValue]);
        }
        return aMap;
    }
    //This model populates a view stencil with the content generated by
    //dynamically invoking reendering methods and replacing their associated
    //user-defined tile identifiers ( a.k.a stencil replacement variables ).
    //See the contract guideline in the header comments of this document.
    String preparingTheResponse(String theViewId, java.util.HashMap<String, String> aRequestMap) throws Exception {
       
        ViewModel aViewModel = (ViewModel) aDirectoryMap.get( theViewId );
        if ( aViewModel == null ) throw new Exception("View Model Not Found");
       
        String [] aTileClassAndMethod = null;       
       
        String theStencilContent = gettingTheResponseStencil( aViewModel.gettingTheStencilName() );
        java.util.HashMap<String,String> someTileRenderMappings = aViewModel.gettingTheTileRendererMappings();
       
        for( String aTileId : someTileRenderMappings.keySet()){       
           
            aTileClassAndMethod = ((String)someTileRenderMappings.get( aTileId )).split(",");                                   
           
            //Start Reflection Activities
            Class aClass = Class.forName( aTileClassAndMethod[0] );
            Class [] theFullyQualifiedParameterTypeClasses = new Class[1];
            theFullyQualifiedParameterTypeClasses[0] = (new java.util.HashMap<String,String>()).getClass();
            Object [] theParameterObjectList= new Object [1];                                   
            theParameterObjectList[0] = aRequestMap;
            theStencilContent = theStencilContent.replace( aTileId , (String) ( aClass.getMethod(aTileClassAndMethod[1],theFullyQualifiedParameterTypeClasses) ).invoke((aClass.getConstructor()).newInstance(), theParameterObjectList)); 
            //End Reflection Activities                        
           
        }
       
        return (theStencilContent);
    }
    //This model extracts the information from the directory.xml file using an
    //XML reader that creates a DOM from which the method creates a user-defined
    //map between view names and ViewModel objects. In the future, we might
    //utilize a SAX XML reader skipping the creation of the DOM and directly
    //create the ViewModel map data structure. This should result in a slight
    //processing speed up although we will only be during it once during a servlet
    //session and storing the utlimate view model map in the servlet's session
    //object. Directoy.xml represents a model mapping for the entire application.
    //Based upon the length of this method ( 50+ lines of code ) it should
    //likely be subdivided and invoke a few private utility methods for
    //completing its work.
    void readingTheDirectoryXMLFile(String theViewId) throws Exception {
              
        String aViewId = null;
        String aStencil = null;
        String aTileId = null;
        String aTileClass = null;
        String aTileMethod = null;
       
        aDirectoryMap = new java.util.HashMap<String, ViewModel>();
       
        javax.xml.parsers.DocumentBuilderFactory theDocumentBuilderFactory =
                javax.xml.parsers.DocumentBuilderFactory.newInstance();
        javax.xml.parsers.DocumentBuilder theDocumentBuilder = theDocumentBuilderFactory.newDocumentBuilder();
        java.io.File aFile = new java.io.File("./src/cab/directory.xml");
        org.w3c.dom.Document theDocument = theDocumentBuilder.parse(aFile);
        theDocument.getDocumentElement().normalize();
        org.w3c.dom.NodeList theModelNodeList = theDocument.getElementsByTagName("model");
        for (int aModelNodeIndex = 0; aModelNodeIndex < theModelNodeList.getLength(); aModelNodeIndex++) {
            org.w3c.dom.Node aModelNode = theModelNodeList.item(aModelNodeIndex);
            if (aModelNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                org.w3c.dom.Element aModelElement = (org.w3c.dom.Element) aModelNode;
                org.w3c.dom.NodeList theViewNodeList =
                        aModelElement.getElementsByTagName("view");
                for (int aViewNodeIndex = 0; aViewNodeIndex < theViewNodeList.getLength(); aViewNodeIndex++) {
                    org.w3c.dom.Node aViewNode = (org.w3c.dom.Node) theViewNodeList.item(aViewNodeIndex);
                    if (aViewNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                        org.w3c.dom.Element aViewElement = (org.w3c.dom.Element) aViewNode;
                        ViewModel aViewModel = new ViewModel();
                       
                        aViewId = aViewElement.getAttribute("id");
                       
                        aStencil = aViewElement.getAttribute("stencil");
                       
                        aViewModel.settingTheStencilName(aStencil);
                        java.util.HashMap<String,String> someTileRendererMappings = new java.util.HashMap<String,String>();
                        org.w3c.dom.NodeList theTileNodeList = aViewElement.getElementsByTagName("tile");
                            for (int aTileNodeIndex = 0; aTileNodeIndex < theTileNodeList.getLength(); aTileNodeIndex++) {
                               
                                org.w3c.dom.Node aTileNode = (org.w3c.dom.Node) theTileNodeList.item(aTileNodeIndex);
                                if (aTileNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                                    org.w3c.dom.Element aTileElement = (org.w3c.dom.Element) aTileNode;
                                   
                                    aTileId = aTileElement.getAttribute("id");
                                    aTileClass = aTileElement.getAttribute("class");
                                    aTileMethod = aTileElement.getAttribute("method");
                                   
                                    someTileRendererMappings.put( aTileId, aTileClass + "," + aTileMethod );
                                   
                                }
                               
                            }            
                            aViewModel.settingTheTileRendererMappings(someTileRendererMappings);
                                aDirectoryMap.put(aViewId, aViewModel);
                           
                    }
                }
            }
        }  
    }
    /**
     * @param args the command line arguments
     * This is the main entry point of the application. It builds the request
     * map from the the "temporary" query string. It then build the view model
     * mappings from the directory.xml file by side-effect. Finally it prepares
     * and presents a response. All in less than 0.5 KLOC including
     * the comments. The number of lines of code are not critical in application.
     * The features it provides in the lines it has is most important.
     */
    public static void main(String[] args) {
        // TODO code application logic here
        CAB aCAB = new CAB();
        java.util.HashMap<String, String> aRequestMap = aCAB.mappingTheRequestNameValuePairs(aCAB.request);
        try {
            aCAB.readingTheDirectoryXMLFile("test_page");
            System.out.println(aCAB.preparingTheResponse("test_page", aRequestMap));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
//STENCIL HANDLER
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cab;
/**
 * An example stencil handler class. For each unique instance of a CABOOSE
 * application, these will be user defined.
 * @author Jody Sharpe
 */
public class StencilHandler {
   
    //Renderer for supplying content about the create date
    public String createDateRenderer( java.util.HashMap<String,String> aRequestMap){
        return( aRequestMap.get("create_date") ); 
    }
    //Renderer for supplying content about the module
    public String moduleRenderer( java.util.HashMap<String,String> aRequestMap){
        return( aRequestMap.get("module") ); 
    }
    //Renderer for supplying content about the project
    public String projectRenderer( java.util.HashMap<String,String> aRequestMap){
        return( aRequestMap.get("project") ); 
    }
}
//END JAVA SOURCE
//BEGIN XHTML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>CABOOSE Embryo</title>
    </head>
    <body>
        <!--
        I chose that my tile replacement identifiers would
        follow the pattern #ALL_CAPS_JAVA_IDENTIFIER#. This
        is only a convention and not strictly enforced by the
        cab. Obviously, the string used should not collide with
        any other one that might be found in a markup document.
        -->
        <p>#PROJECT#</p>
        <p>#MODULE#</p>
        <p>#CREATE_DATE#</p>
    </body>
</html>
//END XHTML
//BEGIN XML
<?xml version="1.0" encoding="UTF-8"?>
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
the model is for the entire application. one view associates
with one page of markup. As attributes this element has an id and a stencil
which is a the filename of the markup. Each view has zero or more replacement
tile child elements associated with it. The tile id attribute appears in the
markup and will be replaced by the String content rendered by the method
uniquely described by the class and method attributes of the tile element.
-->
<model>   
 <view id="test_page" stencil="./src/cab/xstencil.xhtml">
            <tile id="#PROJECT#" class="cab.StencilHandler" method="projectRenderer"/>
            <tile id="#MODULE#" class="cab.StencilHandler" method="moduleRenderer"/>
            <tile id="#CREATE_DATE#" class="cab.StencilHandler" method="createDateRenderer"/>
 </view>
</model>
//END XML

Wednesday, November 26, 2014

Pardon the Skipped Day.

Team. The commented source will be posted on Friday, 11/28/2014. I apologize for not posting content on Tuesday, 11/25/2014, but I was unusually busy all day. I imagine that generating all of the comments will take at least an hour. As you develop software, you will probably find that writing well-crafted comments will take nearly as long as generating the source code. This is why most products are poorly documented in this manner. Developers simply are not allotted enough time for doing so. I will not have the free time for commenting the source until Thanksgiving day, 11/27/2014. I probably will not post again until Friday. Have a Great Holiday. La-La.

Monday, November 24, 2014

Thankful for being ahead of schedule during a short week.

Team. Last week we accomplished the development goals for a pair of weeks. So, we can relax some this week. We are still on schedule. With Thanksgiving on Thursday, we will probably simply work on commenting the prototype well. There might not be any posts of Thursday and Friday of this week. So, keep catching up if you are a little behind. Let's be thankful that we have made it this far. Enjoy your Week. La-La.

Friday, November 21, 2014

Catching up

Team. This is a day for catching up. So, review the source code. That's all. Have a Great weekend. La-La.

Thursday, November 20, 2014

Planning for formality

Team. Our embryo is taking shape. We will spend some time commenting it before we go any further. This is so we do not forget why we have made some of our programming choices. We should also be planning for a more formal  specification of the final product from the prototype on which we are working. This will be useful when we add our contracts and exception handling. So, do a little reading on algebraic specification, programming-by-contract, and JAVA exception handling such as creating Exceptions and etc. Have a Great Day. La-La.

Wednesday, November 19, 2014

Trimming the Fat

Team. This is the second stage of the source for this week. It has the redundant XML file reading removed. The logic is slightly different. The entire XML file is read and placed in a HashMap and class structure called a ViewModel which itself contains a mapping of stencil replacement tiles and renderer methods. Then the method which prepares the stencil content reads this and utilizes reflection for generating the final view. Remember that this is for a layered Schema-II Model-View-Controller architecture. Look over the source. If you have any questions, post them in the forum at https://java.net/projects/caboose. In future post, we will likely redefine any of the large methods so they consist of less than fifty lines of code. Also, we should improve the commenting. This source represents the crux of the controller's logic. Have a Wonderful Day. La-La.

//BEGIN CAB JAVA Source
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cab;
/**
 * The CAB will eventually for the kernel of the CABOOSE general purpose servlet
 *
 * @author Jody Sharpe
 */
public class CAB {
    //Simulated URL String. We will eventually get all of our input from the
    //the servlet,s Request object.
    String request = "?project=caboose&module=skeleton&create_date=10.30.2014";
    java.util.HashMap<String,ViewModel> aDirectoryMap = null;
   
    private class ViewModel {
        private String theStencilName = null;
        private java.util.HashMap theTileRendererMappings = null;
        void settingTheStencilName( String aStencilName ){
            theStencilName = aStencilName;           
        }
        void settingTheTileRendererMappings( java.util.HashMap<String,String> aSetOfTileRendererMappings ){
            theTileRendererMappings = aSetOfTileRendererMappings;           
        }
        String gettingTheStencilName(){
            return( theStencilName );           
        }
        java.util.HashMap<String,String> gettingTheTileRendererMappings(){
            return( theTileRendererMappings );           
        }
    }
   
    String gettingTheResponseStencil(String aViewFileName) throws Exception {
        java.io.BufferedReader aStencilReader = new java.io.BufferedReader(new java.io.FileReader(aViewFileName));
        String theStencilContent = "", theNextLine = null;
        while ((theNextLine = aStencilReader.readLine()) != null) {
            theStencilContent += theNextLine;
        }
        return (theStencilContent);
    }
    java.util.HashMap<String, String> mappingTheRequestNameValuePairs(String aRequest) {
        java.util.HashMap<String, String> aMap = new java.util.HashMap<String, String>();
        aRequest = aRequest.replace("?", "");
        String[] theNameValuePairs = aRequest.split("&");
        for (String aNameValuePair : theNameValuePairs) {
            final int theName = 0, theValue = 1;
            String[] aTuple = aNameValuePair.split("=");
            aMap.put(aTuple[theName], aTuple[theValue]);
        }
        return aMap;
    }
   
    String preparingTheResponse(String theViewId, java.util.HashMap<String, String> aRequestMap) throws Exception {
       
        ViewModel aViewModel = (ViewModel) aDirectoryMap.get( theViewId );
        if ( aViewModel == null ) throw new Exception("View Model Not Found");
       
        String [] aTileClassAndMethod = null;       
       
        String theStencilContent = gettingTheResponseStencil( aViewModel.gettingTheStencilName() );
        java.util.HashMap<String,String> someTileRenderMappings = aViewModel.gettingTheTileRendererMappings();
       
        for( String aTileId : someTileRenderMappings.keySet()){       
            aTileClassAndMethod = ((String)someTileRenderMappings.get( aTileId )).split(",");                                   
            //Start Reflection Activities
            Class aClass = Class.forName( aTileClassAndMethod[0] );
            Class [] theFullyQualifiedParameterTypeClasses = new Class[1];
            theFullyQualifiedParameterTypeClasses[0] = (new java.util.HashMap<String,String>()).getClass();
            Object [] theParameterObjectList= new Object [1];                                   
            theParameterObjectList[0] = aRequestMap;
            theStencilContent = theStencilContent.replace( aTileId , (String) ( aClass.getMethod(aTileClassAndMethod[1],theFullyQualifiedParameterTypeClasses) ).invoke((aClass.getConstructor()).newInstance(), theParameterObjectList));  
            //End Reflection Activities                        
        }
       
        return (theStencilContent);
    }
    void readingTheDirectoryXMLFile(String theViewId) throws Exception {
              
        String aViewId = null;
        String aStencil = null;
        String aTileId = null;
        String aTileClass = null;
        String aTileMethod = null;
       
        aDirectoryMap = new java.util.HashMap<String, ViewModel>();
       
        javax.xml.parsers.DocumentBuilderFactory theDocumentBuilderFactory =
                javax.xml.parsers.DocumentBuilderFactory.newInstance();
        javax.xml.parsers.DocumentBuilder theDocumentBuilder = theDocumentBuilderFactory.newDocumentBuilder();
        java.io.File aFile = new java.io.File("./src/cab/directory.xml");
        org.w3c.dom.Document theDocument = theDocumentBuilder.parse(aFile);
        theDocument.getDocumentElement().normalize();
        org.w3c.dom.NodeList theModelNodeList = theDocument.getElementsByTagName("model");
        for (int aModelNodeIndex = 0; aModelNodeIndex < theModelNodeList.getLength(); aModelNodeIndex++) {
            org.w3c.dom.Node aModelNode = theModelNodeList.item(aModelNodeIndex);
            if (aModelNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                org.w3c.dom.Element aModelElement = (org.w3c.dom.Element) aModelNode;
                org.w3c.dom.NodeList theViewNodeList =
                        aModelElement.getElementsByTagName("view");
                for (int aViewNodeIndex = 0; aViewNodeIndex < theViewNodeList.getLength(); aViewNodeIndex++) {
                    org.w3c.dom.Node aViewNode = (org.w3c.dom.Node) theViewNodeList.item(aViewNodeIndex);
                    if (aViewNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                        org.w3c.dom.Element aViewElement = (org.w3c.dom.Element) aViewNode;
                        ViewModel aViewModel = new ViewModel();
                       
                        aViewId = aViewElement.getAttribute("id");
                       
                        aStencil = aViewElement.getAttribute("stencil");
                       
                        aViewModel.settingTheStencilName(aStencil);
                        java.util.HashMap<String,String> someTileRendererMappings = new java.util.HashMap<String,String>();
                        org.w3c.dom.NodeList theTileNodeList = aViewElement.getElementsByTagName("tile");
                            for (int aTileNodeIndex = 0; aTileNodeIndex < theTileNodeList.getLength(); aTileNodeIndex++) {
                               
                                org.w3c.dom.Node aTileNode = (org.w3c.dom.Node) theTileNodeList.item(aTileNodeIndex);
                                if (aTileNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                                    org.w3c.dom.Element aTileElement = (org.w3c.dom.Element) aTileNode;
                                   
                                    aTileId = aTileElement.getAttribute("id");
                                    aTileClass = aTileElement.getAttribute("class");
                                    aTileMethod = aTileElement.getAttribute("method");
                                   
                                    someTileRendererMappings.put( aTileId, aTileClass + "," + aTileMethod );
                                   
                                }
                               
                            }            
                            aViewModel.settingTheTileRendererMappings(someTileRendererMappings);
                                aDirectoryMap.put(aViewId, aViewModel);
                           
                    }
                }
            }
        }  
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        CAB aCAB = new CAB();
        java.util.HashMap<String, String> aRequestMap = aCAB.mappingTheRequestNameValuePairs(aCAB.request);
        try {
            aCAB.readingTheDirectoryXMLFile("test_page");
            System.out.println(aCAB.preparingTheResponse("test_page", aRequestMap));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
//END CAB JAVA Source

Tuesday, November 18, 2014

Hocus Pocus Invoke Us - Reflection Time

Team. Below is the source the first stage of this week's coding activity. When compiling and running, be certain that your source is in a package called cab. If not, adjust the class names in the "directory" XML file and remove the package statements. The portion of the source which uses reflection has been clearly marked. This is probably the most "advanced" portion of the development. If you understand it, you will not have a problem with any of the other portions. Basically you are invoking a method dynamically after being given its name and class location. There is an implicit contract between the CAB and the rendering methods which states that their only parameter will be a HashMap. In the future, it will support the HTTPRequest and HTTPResponse objects as parameters. This likely is enough for now. During the next stage this week, we will remove the redundant source code for reading the XML file. Talk with you later. La-La.

// BEGIN CAB JAVA Source
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cab;
/**
 * The CAB will eventually for the kernel of the CABOOSE general purpose servlet
 *
 * @author Jody Sharpe
 */
public class CAB {
    //Simulated URL String. We will eventually get all of our input from the
    //the servlet,s Request object.
    String request = "?project=caboose&module=skeleton&create_date=10.30.2014";
    String gettingTheResponseStencil(String aViewFileName) throws Exception {
        java.io.BufferedReader aStencilReader = new java.io.BufferedReader(new java.io.FileReader(aViewFileName));
        String theStencilContent = "", theNextLine = null;
        while ((theNextLine = aStencilReader.readLine()) != null) {
            theStencilContent += theNextLine;
        }
        return (theStencilContent);
    }
    java.util.HashMap<String, String> mappingTheRequestNameValuePairs(String aRequest) {
        java.util.HashMap<String, String> aMap = new java.util.HashMap<String, String>();
        aRequest = aRequest.replace("?", "");
        String[] theNameValuePairs = aRequest.split("&");
        for (String aNameValuePair : theNameValuePairs) {
            final int theName = 0, theValue = 1;
            String[] aTuple = aNameValuePair.split("=");
            aMap.put(aTuple[theName], aTuple[theValue]);
        }
        return aMap;
    }
   
    String preparingTheResponse(String theViewId, String theStencilName, java.util.HashMap<String, String> aRequestMap) throws Exception {
        String aViewId = null;      
        String aTileId = null;
        String aTileClass = null;
        String aTileMethod = null;
        String theStencilContent = gettingTheResponseStencil( theStencilName );
        javax.xml.parsers.DocumentBuilderFactory theDocumentBuilderFactory =
                javax.xml.parsers.DocumentBuilderFactory.newInstance();
        javax.xml.parsers.DocumentBuilder theDocumentBuilder = theDocumentBuilderFactory.newDocumentBuilder();
        java.io.File aFile = new java.io.File("./src/cab/directory.xml");
        org.w3c.dom.Document theDocument = theDocumentBuilder.parse(aFile);
        theDocument.getDocumentElement().normalize();
        org.w3c.dom.NodeList theModelNodeList = theDocument.getElementsByTagName("model");
        for (int aModelNodeIndex = 0; aModelNodeIndex < theModelNodeList.getLength(); aModelNodeIndex++) {
            org.w3c.dom.Node aModelNode = theModelNodeList.item(aModelNodeIndex);
            if (aModelNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                org.w3c.dom.Element aModelElement = (org.w3c.dom.Element) aModelNode;
                org.w3c.dom.NodeList theViewNodeList =
                        aModelElement.getElementsByTagName("view");
                for (int aViewNodeIndex = 0; aViewNodeIndex < theViewNodeList.getLength(); aViewNodeIndex++) {
                    org.w3c.dom.Node aViewNode = (org.w3c.dom.Node) theViewNodeList.item(aViewNodeIndex);
                    if (aViewNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                        org.w3c.dom.Element aViewElement = (org.w3c.dom.Element) aViewNode;
                        aViewId = aViewElement.getAttribute("id");
                        if (aViewId.equalsIgnoreCase(theViewId)) {
                            org.w3c.dom.NodeList theTileNodeList = aViewElement.getElementsByTagName("tile");
                            for (int aTileNodeIndex = 0; aTileNodeIndex < theTileNodeList.getLength(); aTileNodeIndex++) {
                                org.w3c.dom.Node aTileNode = (org.w3c.dom.Node) theTileNodeList.item(aTileNodeIndex);
                                if (aTileNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                                    org.w3c.dom.Element aTileElement = (org.w3c.dom.Element) aTileNode;
                                    aTileId = aTileElement.getAttribute("id");
                                    aTileClass = aTileElement.getAttribute("class");
                                    aTileMethod = aTileElement.getAttribute("method");
                                   
                                    //Start Reflection Activities
                                    Class aClass = Class.forName( aTileClass );
                                    Class [] theFullyQualifiedParameterTypeClasses = new Class[1];
                                    theFullyQualifiedParameterTypeClasses[0] = (new java.util.HashMap<String,String>()).getClass();
                                    Object [] theParameterObjectList= new Object [1];                                   
                                    theParameterObjectList[0] = aRequestMap;
                                    theStencilContent = theStencilContent.replace( aTileId , (String) ( aClass.getMethod(aTileMethod,theFullyQualifiedParameterTypeClasses) ).invoke((aClass.getConstructor()).newInstance(), theParameterObjectList));  
                                    //End Reflection Activities
                                }
                            }
                        }
                    }
                }
            }
        }
        return (theStencilContent);
    }
    String readingTheDirectoryXMLFile(String theViewId) throws Exception {
        String aViewId = null;
        String aStencil = null;
        javax.xml.parsers.DocumentBuilderFactory theDocumentBuilderFactory =
                javax.xml.parsers.DocumentBuilderFactory.newInstance();
        javax.xml.parsers.DocumentBuilder theDocumentBuilder = theDocumentBuilderFactory.newDocumentBuilder();
        java.io.File aFile = new java.io.File("./src/cab/directory.xml");
        org.w3c.dom.Document theDocument = theDocumentBuilder.parse(aFile);
        theDocument.getDocumentElement().normalize();
        org.w3c.dom.NodeList theModelNodeList = theDocument.getElementsByTagName("model");
        for (int aModelNodeIndex = 0; aModelNodeIndex < theModelNodeList.getLength(); aModelNodeIndex++) {
            org.w3c.dom.Node aModelNode = theModelNodeList.item(aModelNodeIndex);
            if (aModelNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                org.w3c.dom.Element aModelElement = (org.w3c.dom.Element) aModelNode;
                org.w3c.dom.NodeList theViewNodeList =
                        aModelElement.getElementsByTagName("view");
                for (int aViewNodeIndex = 0; aViewNodeIndex < theViewNodeList.getLength(); aViewNodeIndex++) {
                    org.w3c.dom.Node aViewNode = (org.w3c.dom.Node) theViewNodeList.item(aViewNodeIndex);
                    if (aViewNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                        org.w3c.dom.Element aViewElement = (org.w3c.dom.Element) aViewNode;
                        aViewId = aViewElement.getAttribute("id");
                        if (aViewId.equalsIgnoreCase(theViewId)) {
                            aStencil = aViewElement.getAttribute("stencil");
                        }
                    }
                }
            }
        }
        return (aStencil);
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        CAB aCAB = new CAB();
        java.util.HashMap<String, String> aRequestMap = aCAB.mappingTheRequestNameValuePairs(aCAB.request);
        try {
            System.out.println(aCAB.preparingTheResponse("test_page", aCAB.readingTheDirectoryXMLFile("test_page"), aRequestMap));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
//END CAB JAVA Source

//BEGIN StencilHandler JAVA Source
*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cab;
/**
 *
 * @author Jody Sharpe
 */
public class StencilHandler {
    public String createDateRenderer( java.util.HashMap<String,String> aRequestMap){
        return( aRequestMap.get("create_date") ); 
    }
    public String moduleRenderer( java.util.HashMap<String,String> aRequestMap){
        return( aRequestMap.get("module") ); 
    }
    public String projectRenderer( java.util.HashMap<String,String> aRequestMap){
        return( aRequestMap.get("project") ); 
    }
}
//END StencilHandler JAVA Source

//BEGIN directory.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<model>
 <view id="test_page" stencil="./src/cab/xstencil.xhtml">
            <tile id="#PROJECT#" class="cab.StencilHandler" method="projectRenderer"/>
            <tile id="#MODULE#" class="cab.StencilHandler" method="moduleRenderer"/>
            <tile id="#CREATE_DATE#" class="cab.StencilHandler" method="createDateRenderer"/>
 </view>
</model>
//END directory.xml

Monday, November 17, 2014

Time for Reflection without Epiphany

Team, this week we will create a method which parses our xml file for elements which contain a mapping between a replacement stencil and a JAVA method within in a class that will return the XHTML which replaces the stencil. This will not be the final version of the prototype since we are repeating some work in the methods which parse XML. We will likely factor out those actions and place them in their own method putting the XML data in a Map object which supports hashing.So there likely will be one or more JAVA source files listed in the weblog this week. Remember the best professional programmer's produce between twenty and thirty lines of verified and validated code in a day. This is when working and average of eight hours per day. I am working on average fifteen minutes per day. So, we are doing well if we produce slightly over one line of verified and validated code per day. No Rush. No Worries. The need for quality exceeds the need for volume. Review the Class and Method class descriptions in the JAVA reference. We will be using their reflection features and the invoke method for this week's source. I will supply that JAVA source file on Tuesday or Wednesday of this week. Keep up the good work and the learning effort. Have a Great Day. La-La.

Friday, November 14, 2014

Catching Up on a Missed Goal

Team, one of our promised goals was producing a XHTML document which was validated by the service http://validator.w3.org/. This goal was overlooked in the simple project plan. I have produced that today. The validator issues a warning about the DOCTYPE statement; however, it issues the same warning when given sample XHTML 1.1 documents listed on its site. So, we will accept this XHTML source for now, and we will revise it later if necessary. This new source will replace your current "xstencil.xhtml" file.You will see that it is very much like the last XHTML document. Spend sometime at w3schools reading about HTML, XHTML, and XML today. Have a Great Day. La-La.

//BEGIN XHTML

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE html PUBLIC
  "-//W3C//DTD XHTML 1.1//EN"
  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>CABOOSE Embryo</title>
    </head>
    <body>
        <p>#PROJECT#</p>
        <p>#MODULE#</p>
        <p>#CREATE_DATE#</p>
    </body>
</html>
//END XHTML

Thursday, November 13, 2014

Looking Backward and Forward ... Reflection

We have been in the process of creating a simple general purpose servlet for any JEE platform web application. At this point, our source could evolve in a number of directions. We could produce a controller for workstation-based graphical user interfaces or for internet-based applications from what we have. We will take the route of the internet-based application controller. Our next step is using our XML reader for extracting the name of a stencil replacement variable and its associated handler method from the directory.xml file. Once we have these pairs, we will use reflection for invoking the appropriate handler for each stencil variable. We might consider creating a de-facto standard format for the replacement variables which will allow for variable parameterization if needed. This would require processing with regular expressions. This feature might be included in the first iteration of the production life-cycle after creating our prototype from which we can reason. Also, such a feature might simply be unnecessary, and any functionality it adds might be achievable by some other means. I hope that you are enjoying this post. I must say that I am having quite a fun time working on this project. Continue your efforts and good work, Team. I realize that some of you are learning programming and/or the JAVA language as you read these pages. I truly do appreciate your work at understanding these concepts. I you have any suggestion I would enjoy hearing them in the forum pages at www.java.net/projects/caboose. Have a great week. La-La.

Wednesday, November 12, 2014

Serving IT up with XML.

I hope that your weeks are progressing well. This is the same source that serves up the XHTML, but it now has an XML configuration file which holds the name of the file being served. We will evolve this over the next few weeks so it determines how it should replace the stencil tags from the XML file also. The only new method is readingTheDirectoryXMLFile.

Read and process it carefully. It will be changing some in the coming weeks, but its basic function will be the same. NOTE: I place the directory.xml file in the same folder as the stencil XHTML file. We can adjust the CABOOSE system's file structure later. Continue your good work, Team. La-La.

//BEGIN JAVA SOURCE
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cab;
/**
 * The CAB will eventually for the kernel of the CABOOSE general purpose servlet
 *
 * @author Jody Sharpe
 */
public class CAB {
    //Simulated URL String. We will eventually get all of our input from the
    //the servlet,s Request object.
    String request = "?project=caboose&module=skeleton&create_date=10.30.2014";
    String gettingTheResponseStencil(String aViewFileName) throws Exception {
        java.io.BufferedReader aStencilReader = new java.io.BufferedReader(new java.io.FileReader(aViewFileName));
        String theStencilContent = "", theNextLine = null;
        while ((theNextLine = aStencilReader.readLine()) != null) {
            theStencilContent += theNextLine;
        }
        return (theStencilContent);
    }
    java.util.Map<String, String> mappingTheRequestNameValuePairs(String aRequest) {
        java.util.Map<String, String> aMap = new java.util.Hashtable<String, String>();
        aRequest = aRequest.replace("?", "");
        String[] theNameValuePairs = aRequest.split("&");
        for (String aNameValuePair : theNameValuePairs) {
            final int theName = 0, theValue = 1;
            String[] aTuple = aNameValuePair.split("=");
            aMap.put(aTuple[theName], aTuple[theValue]);
        }
        return aMap;
    }
    String preparingTheResponse(String aStencil, java.util.Map<String, String> aRequestMap) {
        aStencil = aStencil.replace("#PROJECT#", aRequestMap.get("project"));
        aStencil = aStencil.replace("#MODULE#", aRequestMap.get("module"));
        aStencil = aStencil.replace("#CREATE_DATE#", aRequestMap.get("create_date"));
        return (aStencil);
    }
    String readingTheDirectoryXMLFile(String theViewId) throws Exception {
        String aViewId = null;
        String aStencil = null;
       
        javax.xml.parsers.DocumentBuilderFactory theDocumentBuilderFactory =
                javax.xml.parsers.DocumentBuilderFactory.newInstance();
        javax.xml.parsers.DocumentBuilder theDocumentBuilder = theDocumentBuilderFactory.newDocumentBuilder();
       
        java.io.File aFile = new java.io.File("./src/cab/directory.xml");
       
        org.w3c.dom.Document theDocument = theDocumentBuilder.parse(aFile);
        theDocument.getDocumentElement().normalize();
        org.w3c.dom.NodeList theModelNodeList = theDocument.getElementsByTagName("model");
        for (int aModelNodeIndex = 0; aModelNodeIndex < theModelNodeList.getLength(); aModelNodeIndex++) {
           
            org.w3c.dom.Node aModelNode = theModelNodeList.item(aModelNodeIndex);
           
            if (aModelNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
               
                org.w3c.dom.Element aModelElement = (org.w3c.dom.Element) aModelNode;
                org.w3c.dom.NodeList theViewNodeList =
                        aModelElement.getElementsByTagName("view");
               
                for (int aViewNodeIndex = 0; aViewNodeIndex < theViewNodeList.getLength(); aViewNodeIndex++) {
                   
                    org.w3c.dom.Node aViewNode = (org.w3c.dom.Node) theViewNodeList.item(aViewNodeIndex);
                   
                    if (aViewNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                       
                        org.w3c.dom.Element aViewElement = (org.w3c.dom.Element) aViewNode;
                        aViewId = aViewElement.getAttribute("id");
                       
                        if ( aViewId.equalsIgnoreCase( theViewId )){
                            aStencil = aViewElement.getAttribute("stencil");
                        }
                    }
                }
            }
        }
       
        return (aStencil);
       
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        CAB aCAB = new CAB();
        java.util.Map<String, String> aRequestMap = aCAB.mappingTheRequestNameValuePairs(aCAB.request);
        try {
            System.out.println(aCAB.preparingTheResponse(aCAB.gettingTheResponseStencil(aCAB.readingTheDirectoryXMLFile("test_page")), aRequestMap));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
//END JAVA SOURCE

//BEGIN XML SOURE
<?xml version="1.0" encoding="UTF-8"?>
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<model>
 <view id="test_page" stencil="./src/cab/xstencil.xhtml">
 </view>
</model>
//END XML SOURCE

Tuesday, November 11, 2014

Getting Parameters from XML

Spend some time today doing background reading on XML and the JSE's DOM Parser. In the long-term, We might transfer the data from our XML file which is a directory of views in the XHTML entity class model and place it in a Map for quick access of the view's parameters based upon the view's name. In the short-term, we will simple read the name of our XHTML stencil from the XML file as an attribute of a view element. I will provide that source code in the morning.

Have a Great Day, Team. La-La.

Monday, November 10, 2014

A Simple Development Plan.

    As I promised, today I will deliver an informal project plan. It will outline the activities for each week with a single development goal for each. The plan might be revised over the next few weeks.

Week   Goal
0        Project Overview and Discussion
1        Create "Hello World"-style program which serves up internally stored XHTML
2        Create "Hello World"-style program which serves up externally stored XHTML
3        Create "Hello World"-style program which serves up externally stored XHTML
          whose filename we extract from an XML file
4        Extend the prototype so a method populates the #STENCIL_REPLACEMENT_VARIABLE#s
          in the XHTML page.
5        Extract the name of the method which populates the stencil replacement from an XML file
6        Consider converting between DOM and SAX XML reader for efficiency and user control over
         data structure which hold application configuration parameters.
7       Improve exception handling. Do not simply throw exceptions upward.
8       Add contracts for enforcing "program-correctness" within controller.
9       Deploy this first iteration of the evolutionary model at java.net/projects/caboose
10     Create life-cycle documents for development of the production product based on reasoning
         from this prototype

   The secondary goal for this week is the creation of an XML Reader for parsing the application's configuration file. We will initially use a Document Object Model (DOM) parser for reading and interpreting the file. This is probably simplest since, as a DOM reader parses an XML file, the reader place all of the attributes, elements, and etc. in a data structure, the DOM, from which one can read them. If a future week, we might create a more efficient, special-purpose structure for holding the elements and attributes using a SAX reader which does not store these values in data structure while processing it. We might save this for the second full iteration of the evolutionary process model.

That is all for today, Team. La-La.

Friday, November 7, 2014

Time for a Project Plan. Better Late than Never.

I will publish the official project plan as a list of features which we must realize over the next few months. This list will be available next Monday 11.10.2014. Our goal is that we have a working product which I can present at the local JAVA Users Group (JUG) meeting in January or February of 2015. We could rush and produce this product quickly, but I have found that as one works one should ruminate and daydream his way through development. Remember, be a bird brain; hunt, peck, think. It is not the number of lines of code which make a product valuable and worthwhile, but the features it supplies. Plus, hastily written software often results in code bloat with redundant programming idioms. Writing software is much like writing an essay, research paper, or theme. One must know when he should put his pen down, rest, and think. Of course, one can crank a product out quickly, but it will likely be poorly crafted and not fully achieve what the author desires. So, we will not rush. BlogSpot reports that  I have had a number of visitors, but I have not received any questions yet. Believing that everyone who has read these pages has a reasonable understanding, I will proceed with coding the next goal during the week of 11.10.2014. That is all for now. Enjoy the upcoming weekend, Team! La-La.

Thursday, November 6, 2014

Let's get IT started.

Today, I thought that I would post one of the best places for learning JAVA for programming professional who like the non-linear nature of hypertext. It is the Oracle JAVA tutorial at http://docs.oracle.com/javase/tutorial/index.html. Look over it. It is more than one can digest in a day so do not try reading it all. If you do not have much experience with JAVA, try the "Getting Started" section and the "Hello World!" application by the end of the day. The skills learned in that section will be essential for following this blog. That is all for now, Team. La-La.

Wednesday, November 5, 2014

Serve IT Up!

Team. As I promised, this week we will serve up some (X)HTML through the use of a buffered file reader as the next step in completing our CABOOSE.

If you copy this source and compile it on your desktop, be certain that you supply the proper name and file path for the hypertext stencil. I am using the NetBeans integrated development environment. For simplicity, I placed it in the same directory as CAB.java which is the "cab" package directory of the "src" folder.

Practice compiling this and run it once or twice. Be careful that you properly copy the JAVA source placing it in a "CAB.java" file and the XHTML putting it in a "xstencil.xhtml" file. Removing the "package cab;" statement might be necessary before successfully compiling it.

Copy the output placing it in an ASCII text editor, and then save it as "view.html" on your desktop. Finally, open your output with a browser. For those of you learning JAVA, carefully review the code.

As promised, there is only minimal exception handling which simplifies coding for the time being. I will continue commenting on this source and our next step on Thursday and Friday. For extra scripting practice, you can make sure that the XHTML file is validated against the W3 Consortium Standard. Make any adjustments in it that are necessary. Rerun the program, and open the validated output in a browser. This should be enough for now.

Speak with you later. La-La.

//BEGIN JAVA SOURCE
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cab;
/**
 * The CAB will eventually for the kernel of the CABOOSE general purpose servlet
 * @author Jody Sharpe
 */
public class CAB {
    //Simulated URL String. We will eventually get all of our input from the
    //the servlet,s Request object.
    String request = "?project=caboose&module=skeleton&create_date=10.30.2014";
    //Simple response in the form of an HTML page. We will supply any response
    //via the servlet's Response object.
    String response = "<html><head><title>CABOOSE Embryo</title></head>" +
            "<body>#PROJECT#<p>#MODULE#<p>#CREATE_DATE#<p></body></html>";
   
    String gettingTheResponseStencil( String aViewFileName ) throws Exception {
        java.io.BufferedReader aStencilReader = new java.io.BufferedReader( new java.io.FileReader( aViewFileName ));
        String theStencilContent = "", theNextLine = null;
        while( ( theNextLine = aStencilReader.readLine()) != null ) theStencilContent += theNextLine;
        return (theStencilContent);
    }
  
    java.util.Map<String,String> mappingTheRequestNameValuePairs( String request ){
        java.util.Map<String,String> aMap = new java.util.Hashtable<String,String>();
        request = request.replace("?","");
        String[] theNameValuePairs = request.split("&");
        for( String aNameValuePair : theNameValuePairs ){
            final int theName = 0, theValue = 1;
            String [] aTuple = aNameValuePair.split("=");
            aMap.put( aTuple[theName], aTuple[theValue]);
        }
        return aMap;
    }
   
    String preparingTheResponse( String stencil, java.util.Map<String,String> aRequestMap ){
  
        stencil = stencil.replace("#PROJECT#",aRequestMap.get("project"));
        stencil = stencil.replace("#MODULE#",aRequestMap.get("module"));
        stencil = stencil.replace("#CREATE_DATE#",aRequestMap.get("create_date"));
       
        return( stencil );
       
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        CAB aCAB = new CAB();
        java.util.Map<String,String> aRequestMap = aCAB.mappingTheRequestNameValuePairs( aCAB.request );       
        try {
           
            System.out.println( aCAB.preparingTheResponse( aCAB.gettingTheResponseStencil( "./src/cab/xstencil.xhtml" ), aRequestMap) );
        }catch( Exception e ){
            e.printStackTrace();
        }
    }
}
//END JAVA SOURCE

//BEGIN XHTML SOURCE
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>CABOOSE Embryo</title>
    </head>
    <body>
        <p>#PROJECT#</p>
        <p>#MODULE#</p>
        <p>#CREATE_DATE#</p>
    </body>
</html>
//END XHTML SOURCE

Tuesday, November 4, 2014

Slowing Down Some. No Rush. No Worries.


Team. While we let the embryo grow, let us look at the next step. Each step will be achieved a week at a time. This will allow sufficient learning time for the neophyte JAVA programmer. My goal is that no blog reader be left behind. This week’s step will be the processing of the output HTML file with a buffered file reader. This requires using some classes from the java.io.* package which handles file processing and the exceptions associated with files. For those of you who are not familiar with computing abstractions, one views every source of data or place which one puts data as a file. Each file has a special number which describes it location. This number is called the “file handle” since with it one can “handle” and control the follow of data in or out of a file.

In JAVA, one can get a handle on a file by creating a reader or writer for that entity. The file reader which JAVA provides does not allow for buffering which streamlines processing. So, one must wrap the file reader with an object which provides this:

java.io.BufferedReader aBufferedReader =

new java.io.BufferedReader( new java.io.FileReader( aXHTMLStencilFileName ) );

The fully qualified names for the objects are provided here. This reinforces the name and purpose of the packages from which they come. We will eventually rewrite our code with import statements and the above will become:

Import java.io.*;


BufferedReader aBufferedReader =

new BufferedReader( new FileReader( aXHTMLStencilFileName ) );

When one processes a file, certain exceptions can occur. One being the file is not found based on the name given. JAVA has mechanisms for handling such conditions when they arise. These are the subclasses of the exception object and the try-catch-finally construct. With this construct, one places any instructions which might generate an exception within the try portion and uses one or more catch portions for processing specific exception types. The finally portion is for any “final” housekeeping which must be done. However, we will not use this approach yet. For simplicity, we will let any exception which occurs be thrown upward until it reaches the top-level of our program and we will print an exception message stack trace at that point. This will increase the simplicity in development. We can increase the sophistication of the exception handling in the future.

Another goal for this week is creating a validated XHTML template which we will use as a basis for all of our front-end scripting. The HTML snippet in the current example is not based on a current valid XHTML standard.

So skim, the java.io.package (especially the BufferedReader and FileReader ) plus a simple quality XHTML tutorial. Also, try the XHTML validator at http://validator.w3.org/.
If you are a new programmer, I hope that by now you are on your second chapter of the Art & Science of JAVA and enjoying the SEE classes. Also if you are a professional programmer, you should have at least covered the chapters covering control statements, primitive types, and basic objects in Schildt’s JAVA text. Also, the professional might like the freshman refresher provided by the SEE JAVA course.

Next, week we will extract the XHTML stencil filename from an XML parameter file. The following week, we will generate the XHTML source using reflection and the XML  parameter file. Initially, those were the goals for this week, but I thought “Why rush it?” Let us do some ruminating and reasoning. The bird brain philosophy is best “hunt-peck-think”!

So let’s slow down some and do some learning along the way!

Talk with tomorrow. La-La.