Coverage Report - org.simpleframework.xml.core.TemplateEngine
 
Classes in this File Line Coverage Branch Coverage Complexity
TemplateEngine
96%
50/52
80%
16/20
2.5
 
 1  
 /*
 2  
  * TemplateEngine.java May 2005
 3  
  *
 4  
  * Copyright (C) 2005, Niall Gallagher <niallg@users.sf.net>
 5  
  *
 6  
  * Licensed under the Apache License, Version 2.0 (the "License");
 7  
  * you may not use this file except in compliance with the License.
 8  
  * You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
 15  
  * implied. See the License for the specific language governing 
 16  
  * permissions and limitations under the License.
 17  
  */
 18  
 
 19  
 package org.simpleframework.xml.core;
 20  
 
 21  
 import org.simpleframework.xml.filter.Filter;
 22  
 
 23  
 /**
 24  
  * The <code>TemplateEngine</code> object is used to create strings
 25  
  * which have system variable names replaced with their values.
 26  
  * This is used by the <code>Source</code> context object to ensure
 27  
  * that values taken from an XML element or attribute can be values
 28  
  * values augmented with system or environment variable values.
 29  
  * <pre>
 30  
  *
 31  
  *    tools=${java.home}/lib/tools.jar
 32  
  * 
 33  
  * </pre>
 34  
  * Above is an example of the use of an system variable that
 35  
  * has been inserted into a plain Java properties file. This will
 36  
  * be converted to the full path to tools.jar when the system
 37  
  * variable "java.home" is replaced with the matching value.
 38  
  * 
 39  
  * @author Niall Gallagher
 40  
  */ 
 41  
 class TemplateEngine {
 42  
   
 43  
    /**
 44  
     * This is used to store the text that are to be processed.
 45  
     */
 46  
    private Template source;
 47  
    
 48  
    /**
 49  
     * This is used to accumulate the bytes for the variable name.
 50  
     */         
 51  
    private Template name;
 52  
 
 53  
    /**
 54  
     * This is used to accumulate the transformed text value.
 55  
     */ 
 56  
    private Template text;
 57  
 
 58  
    /**
 59  
     * This is the filter used to replace templated variables.
 60  
     */
 61  
    private Filter filter;
 62  
    
 63  
    /**
 64  
     * This is used to keep track of the buffer seek offset.
 65  
     */ 
 66  
    private int off;
 67  
    
 68  
    /**
 69  
     * Constructor for the <code>TemplateEngine</code> object. This is 
 70  
     * used to create a parsing buffer, which can be used to replace
 71  
     * filter variable names with their corrosponding values.
 72  
     * 
 73  
     * @param filter this is the filter used to provide replacements 
 74  
     */ 
 75  98473
    public TemplateEngine(Filter filter) {
 76  98473
       this.source = new Template();
 77  98473
       this.name = new Template();            
 78  98473
       this.text = new Template();
 79  98473
       this.filter = filter;
 80  98473
    }
 81  
    
 82  
    /**
 83  
     * This method is used to append the provided text and then it
 84  
     * converts the buffered text to return the corrosponding text.
 85  
     * The contents of the buffer remain unchanged after the value
 86  
     * is buffered. It must be cleared if used as replacement only. 
 87  
     * 
 88  
     * @param value this is the value to append to the buffer
 89  
     * 
 90  
     * @return returns the value of the buffer after the append
 91  
     */
 92  
    public String process(String value) {
 93  1714125
       if(value.indexOf('$') < 0) {
 94  1554042
          return value;
 95  
       }
 96  
       try {
 97  160083
          source.append(value);         
 98  160083
          parse();
 99  160083
          return text.toString();
 100  
       }finally {
 101  160083
          clear();
 102  
       }
 103  
    }
 104  
    
 105  
    /**
 106  
     * This extracts the value from the Java properties text. This
 107  
     * will basically ready any text up to the first occurance of
 108  
     * an equal of a terminal. If a terminal character is read
 109  
     * this returns without adding the terminal to the value.
 110  
     */
 111  
    private void parse(){
 112  5845050
       while(off < source.count){
 113  5684967
          char next = source.buf[off++];
 114  
          
 115  5684967
          if(next == '$') {
 116  200113
             if(off < source.count)
 117  200113
                if(source.buf[off++] == '{') {
 118  200081
                   name();         
 119  200081
                   continue;
 120  
                } else {
 121  32
                   off--;                       
 122  
                }         
 123  
          } 
 124  5484886
          text.append(next);
 125  5484886
       }
 126  160083
    }
 127  
 
 128  
    /**
 129  
     * This method is used to extract text from the property value
 130  
     * that matches the pattern "${ *TEXT }". Such patterns within 
 131  
     * the properties file are considered to be system 
 132  
     * variables, this will replace instances of the text pattern
 133  
     * with the matching system variable, if a matching
 134  
     * variable does not exist the value remains unmodified.
 135  
     */ 
 136  
    private void name() {
 137  2560954
       while(off < source.count) {
 138  2560954
          char next = source.buf[off++];              
 139  
 
 140  2560954
          if(next == '}') {
 141  200081
             replace();                 
 142  200081
             break;
 143  
          } else {
 144  2360873
             name.append(next);
 145  
          }            
 146  2360873
       }      
 147  200081
       if(name.length() >0){
 148  0
          text.append("${");
 149  0
          text.append(name);              
 150  
       }     
 151  200081
    }
 152  
 
 153  
    /**
 154  
     * This will replace the accumulated for an system variable
 155  
     * name with the value of that system variable. If a value
 156  
     * does not exist for the variable name, then the name is put
 157  
     * into the value so that the value remains unmodified.
 158  
     */ 
 159  
    private void replace() {
 160  200081
       if(name.length() > 0) {
 161  200081
          replace(name);
 162  
       }           
 163  200081
       name.clear();
 164  200081
    }
 165  
 
 166  
    /**
 167  
     * This will replace the accumulated for an system variable
 168  
     * name with the value of that system variable. If a value
 169  
     * does not exist for the variable name, then the name is put
 170  
     * into the value so that the value remains unmodified.
 171  
     *
 172  
     * @param name this is the name of the system variable
 173  
     */ 
 174  
    private void replace(Template name) {
 175  200081
       replace(name.toString());
 176  200081
    }
 177  
 
 178  
    /**
 179  
     * This will replace the accumulated for an system variable
 180  
     * name with the value of that system variable. If a value
 181  
     * does not exist for the variable name, then the name is put
 182  
     * into the value so that the value remains unmodified.
 183  
     *
 184  
     * @param name this is the name of the system variable
 185  
     */ 
 186  
    private void replace(String name) {
 187  200081
       String value = filter.replace(name);
 188  
    
 189  200081
       if(value == null) {
 190  100025
          text.append("${");
 191  100025
          text.append(name);
 192  100025
          text.append("}");
 193  
       }else {
 194  100056
          text.append(value);              
 195  
       }
 196  200081
    }
 197  
 
 198  
    /**
 199  
     * This method is used to clear the contents of the buffer. This
 200  
     * includes the contents of all buffers used to transform the
 201  
     * value of the buffered text with system variable values.
 202  
     * Once invoked the instance can be reused as a clean buffer.
 203  
     */ 
 204  
    public void clear() {
 205  160083
       name.clear();
 206  160083
       text.clear();    
 207  160083
       source.clear();
 208  160083
       off = 0;  
 209  160083
    }
 210  
 }