All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.coos.util.macro.MacroSubstituter Maven / Gradle / Ivy

There is a newer version: 1.3.1
Show newest version
/**
 * COOS - Connected Objects Operating System (www.connectedobjects.org).
 *
 * Copyright (C) 2009 Telenor ASA and Tellu AS. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 *
 * You may also contact one of the following for additional information:
 * Telenor ASA, Snaroyveien 30, N-1331 Fornebu, Norway (www.telenor.no)
 * Tellu AS, Hagalokkveien 13, N-1383 Asker, Norway (www.tellu.no)
 */
package org.coos.util.macro;

import java.util.HashMap;
import java.util.Map;

/**
 * Substitute macros in strings and accumulate property values according to
 * macro substitution rules.
 * 
 * @author Robert Bjarum, Tellu AS
 * 
 */
public class MacroSubstituter {
	private Map properties = null;
	private Map foundMacros = new HashMap();
	private boolean dryRun = false;
	private int unresolved = 0;

	public MacroSubstituter() {
		super();
	}

	public MacroSubstituter(Map defaultProperties) {
		super();
		setDefaultProperties(defaultProperties);
	}

	/**
	 * Get the set of macros found so far.
	 * 
	 * @see clear()
	 * @return sorted set of key values
	 */
	public Map getFoundMacros() {
		return foundMacros;
	}

	public boolean isDryRun() {
		return dryRun;
	}

	public void setDryRun(boolean dryRun) {
		this.dryRun = dryRun;
	}

	/**
	 * Return the accumulated number of unresolved macro definitions.
	 * 
	 * @return number > 0 if macros are unresolved
	 */
	public int getUnresolved() {
		return unresolved;
	}

	public void setUnresolved(int unresolved) {
		this.unresolved = unresolved;
	}

	public Map getDefaultProperties() {
		return properties;
	}

	public void setDefaultProperties(Map defaultProperties) {
		properties = new HashMap(defaultProperties);
	}

	public String process(String s) {
		return process(s, false);
	}

	/**
	 * Substitute macro name in string with values found in properties.
	 * Optionally make a new file where the macros have values from property
	 * 
	 * @return string with macros substituted
	 */
	public String process(String s, boolean makeTemplate) {
		StringBuilder b = null;
		String key;
		String value;
		int pos = 0;
		int index0;
		int index1;

		if (!isDryRun()) {
			b = new StringBuilder();
		}

		while (pos < s.length()) {
			index0 = s.indexOf(MacroConstants.MACRO_PREFIX, pos);

			if (index0 >= pos) {
				if (!isDryRun()) {
					b.append(s.substring(pos, index0));
				}

				/*
				 * Skip MACRO_SUFFIX when escaped.
				 */
				index1 = -1;
				int temp = index0;
				while (index1 < 0 && temp < s.length()) {
	                index1 = s.indexOf(MacroConstants.MACRO_SUFFIX, temp);
	                if (index1 > temp) {
	                    if (s.charAt(index1 -1) == MacroConstants.ESCAPE_CHAR) {
	                        temp = index1 + 1;
	                        index1 = -1;
	                    }
	                } else {
	                    temp = s.length();
	                }
				}

				if (index1 < 0) {
					throw new MacroUtilityException("Could not find maching macro end-token, near <"
							+ s.substring(index0, Math.min(s.length(), index0 + 10)) + ">");
				}

				pos = index1 + 1;
				index0 += MacroConstants.MACRO_PREFIX.length();
				index1 -= MacroConstants.MACRO_SUFFIX.length();
				key = s.substring(index0, index1 + 1);
				value = processMacro(key);

				if (!isDryRun()) {
					if (value != null) {
						if (makeTemplate) {
							b.append(MacroConstants.MACRO_PREFIX);
							int keyKeyPos = key.indexOf(MacroConstants.EXPAND_COLON);
							if (keyKeyPos >= 0)
								b.append(key.substring(0, keyKeyPos));
							else
								b.append(key);
							b.append(MacroConstants.EXPAND_USE);
						}
						b.append(value);
						if (makeTemplate)
							b.append(MacroConstants.MACRO_SUFFIX);
					} else {
						b.append(MacroConstants.MACRO_PREFIX);
						b.append(key);
						b.append(MacroConstants.MACRO_SUFFIX);
					}
				}
			} else {
				if (!isDryRun()) {
					b.append(s.substring(pos, s.length()));
				}

				pos = s.length();
			}
		}

		if (isDryRun()) {
			return s;
		} else {
			return b.toString();
		}
	}

	private String processMacro(String macro) {
		String value = null;
		String att = null;
		int index;

		String key = macro;
		String cmd = null;
		index = macro.indexOf(MacroConstants.EXPAND_COLON);

		if (index >= 0) {
			cmd = macro.substring(index, index + 2);
			key = macro.substring(0, index);
			att = macro.substring(index + 2);
			if (att == null) {
				att = "";
			} else {
			    att = stripEscapeChars(att);
			}
		}

		/* First check if value is set in default properties */
		value = getProperty(key);

		/* No property found: process macro command */
		if (value == null) {
			if (cmd != null) {
				if (cmd.equals(MacroConstants.EXPAND_ASSIGN)) {
					putProperty(key, att);
					value = att;

					/* Overwrite value even if it already exists */
					foundMacros.put(key, value);
				} else if (cmd.equals(MacroConstants.EXPAND_USE)) {
					value = att;

					/*
					 * Do not overwrite value if it already exists. Keep
					 * EXPAND_ASSIGN
					 */
					if (!foundMacros.containsKey(key)) {
						foundMacros.put(key, value);
					}
				} else {
					throw new MacroUtilityException("Macro substitution for expression ${macro-name" + cmd
							+ "defval} not implemented");
				}
			} else {
				/* Macro could not be resolved */
				unresolved++;
				/* Still a macro */
				foundMacros.put(key, null);
			}
		} else {
			foundMacros.put(key, value);
		}

		return value;
	}
	
	protected String stripEscapeChars(String s) {
	    StringBuilder sb = new StringBuilder();
	    int i = 0;
	    while (i < s.length()) {
	        if (s.charAt(i) == MacroConstants.ESCAPE_CHAR) {
	            i++;
	        }
	        sb.append(s.charAt(i++));
	    }
	    return sb.toString();
	}

	private String getProperty(String key) {
		if (properties == null) {
			return null;
		} else {
			return properties.get(key);
		}
	}

	private void putProperty(String key, String value) {
		if (properties == null) {
			properties = new HashMap();
		}

		properties.put(key, value);
	}

	/**
	 * Clear data to prepare for fresh substitution job. This will clear
	 * defaultProperties, foundMacros and unresolved-count.
	 */
	public void clear() {
		if (properties != null) {
			properties.clear();
		}

		foundMacros.clear();
		unresolved = 0;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy