1  /*
     2   * Copyright the original author or authors.
     3   * 
     4   * Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   * 
     8   *      http://www.mozilla.org/MPL/MPL-1.1.html
     9   * 
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  import org.as2lib.core.BasicClass;
    18  import org.as2lib.data.holder.properties.SimpleProperties;
    19  import org.as2lib.data.holder.Properties;
    20  import org.as2lib.data.type.MultilineString;
    21  import org.as2lib.util.StringUtil;
    22  
    23  /**
    24   * {@code PropertiesParser} parses a properties source string into a {@link Properties}
    25   * instance.
    26   * 
    27   * <p>The source string contains simple key-value pairs. Multiple pairs are
    28   * separated by line terminators (\n or \r or \r\n). Keys are separated from
    29   * values with the characters '=', ':' or a white space character.
    30   * 
    31   * <p>Comments are also supported. Just add a '#' or '!' character at the
    32   * beginning of your comment-line.
    33   * 
    34   * <p>If you want to use any of the special characters in your key or value you
    35   * must escape it with a back-slash character '\'.
    36   * 
    37   * <p>The key contains all of the characters in a line starting from the first
    38   * non-white space character up to, but not including, the first unescaped
    39   * key-value-separator.
    40   * 
    41   * <p>The value contains all of the characters in a line starting from the first
    42   * non-white space character after the key-value-separator up to the end of the
    43   * line. You may of course also escape the line terminator and create a value
    44   * across multiple lines.
    45   * 
    46   * @author Martin Heidegger
    47   * @author Simon Wacker
    48   * @version 1.0
    49   */
    50  class org.as2lib.data.holder.properties.PropertiesParser extends BasicClass {
    51  	
    52  	/**
    53  	 * Constructs a new {@code PropertiesParser} instance.
    54  	 */
    55  	public function PropertiesParser(Void) {
    56  	}
    57  	
    58  	/**
    59  	 * Parses the given {@code source} and creates a {@code Properties} instance from
    60  	 * it.
    61  	 * 
    62  	 * @param source the source to parse
    63  	 * @return the properties defined by the given {@code source}
    64  	 */
    65  	public function parseProperties(source:String):Properties {
    66  		var result:Properties = new SimpleProperties();
    67  		var lines:MultilineString = new MultilineString(source);
    68  		var i:Number;
    69  		var c:Number = lines.getLineCount();
    70  		var key:String;
    71  		var value:String;
    72  		var formerKey:String;
    73  		var formerValue:String;
    74  		var useNextLine:Boolean = false;;
    75  		for (i=0; i<c; i++) {
    76  			var line:String = lines.getLine(i);
    77  			// Trim the line
    78  			line = StringUtil.trim(line);
    79  			// Ignore Comments
    80  			if ( line.indexOf("#") != 0 && line.indexOf("!") != 0 && line.length != 0) {
    81  				// Line break processing
    82  				if (useNextLine) {
    83  					key = formerKey;
    84  					value = formerValue+line;
    85  					useNextLine = false;
    86  				} else {
    87  					var sep:Number = getSeperation(line);
    88  					key = StringUtil.rightTrim(line.substr(0,sep));
    89  					value = line.substring(sep+1);
    90  					formerKey = key;
    91  					formerValue = value;
    92  				}
    93  				// Trim the content
    94  				value = StringUtil.leftTrim(value);
    95  				// Allow normal lines
    96  				if (value.charAt(value.length-1) == "\\") {
    97  					formerValue = value =  value.substr(0, value.length-1);
    98  					useNextLine = true;
    99  				} else {
   100  					// Commit Property
   101  					result.setProperty(key, value);
   102  				}
   103  			}
   104  		}
   105  		return result;
   106  	}
   107  	
   108  	/**
   109  	 * Returns the position at which key and value are separated.
   110  	 * 
   111  	 * @param line the line that contains the key-value pair
   112  	 * @return the position at which key and value are separated
   113  	 */
   114  	private function getSeperation(line:String):Number {
   115  		var i:Number;
   116  		var l:Number = line.length;
   117  		for (i=0; i<l; i++) {
   118  			var c:String = line.charAt(i);
   119  			if (c == "'") {
   120  				i++;
   121  			} else {
   122  				if (c == ":" || c == "=" || c == "\t") break;
   123  			}
   124  		}
   125  		return ( (i == l) ? line.length : i );
   126  	}
   127  	
   128  }