/**
 *   Copyright 2007 Y.Murakamin
 *
 *  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.
 */
package net.murakamin.sticker.commands.util;

import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.murakamin.sticker.StickerContext;
import net.murakamin.sticker.commands.VariableCommand;

import org.apache.commons.lang.SystemUtils;

/**
 * 
 * Utility class that collected methods of relations to operation of
 * {@link net.murakamin.sticker.StickerContext} of utility
 * 
 * @see net.murakamin.sticker.StickerContext
 * @author Y.Murakamin
 */
public class StickerContextUtil
{
	public synchronized static String applyContextVariable(
	        final StickerContext context, final String target)
	{
		if (context == null)
		{
			return target;
		}

		Pattern pattern = Pattern.compile("\\{\\S+?\\}");
		Matcher matcher = pattern.matcher(target);

		// exists replacement key in StickerContext?
		while (matcher.find())
		{
			String key = matcher.group();
			String concreteKey = key.substring(1, key.length() - 1);
			if (!context.containsKey(VariableCommand.CONTEXT_VARIABLE_PREFIX
			        + concreteKey))
			{
				throw new IllegalStateException("不明な置換文字列  " + target
				        + " が見つかりました。<variable>タグの定義を見直してください"
				        + SystemUtils.LINE_SEPARATOR + target);
			}
		}

		Set<String> contextKeys = context.keySet();
		String result = new String(target);

		java.util.Iterator<String> ite = contextKeys.iterator();
		while (ite.hasNext())
		{
			String key = ite.next();
			if (key.startsWith(VariableCommand.CONTEXT_VARIABLE_PREFIX))
			{
				result = result.replaceAll("\\{"
				        + key.substring(VariableCommand.CONTEXT_VARIABLE_PREFIX
				                .length()) + "\\}", (String) context.get(key));
			}
		}
		return result;
	}

	/**
	 * The content of the character string passed by the argument according to a
	 * set value in the context is substituted.
	 * 
	 * @see net.murakamin.sticker.commands.CursorCommand
	 * @see net.murakamin.sticker.commands.ForCommand
	 * @see net.murakamin.sticker.commands.IfCommand
	 * @see net.murakamin.sticker.commands.SqlCommand
	 * @see net.murakamin.sticker.commands.ImportCommand
	 * @see net.murakamin.sticker.commands.ExportCommand
	 * @see net.murakamin.sticker.commands.QueryExportCommand
	 * @see net.murakamin.sticker.commands.InfoCommand
	 * @see net.murakamin.sticker.StickerContext
	 * 
	 * @param context
	 *            Sticker Context object
	 * @param before
	 *            Substitution above sentence Gerets. It is substituted if there
	 *            is a character string enclosed with "_$$" and "$$_" in this.
	 * @return Character string after it substitutes it.
	 * 
	 */
	public synchronized static String getReplacementString(
	        final StickerContext context, final String before)
	{
		StringBuffer result = new StringBuffer();
		Pattern pattern = Pattern.compile(Messages
		        .getString("StickerContextUtil.pattern")); //$NON-NLS-1$
		Matcher matcher = pattern.matcher(before);

		boolean findResult = matcher.find();
		while (findResult)
		{

			String placeHolder = matcher.group();

			String replaceKey = placeHolder
			        .substring(
			                Messages
			                        .getString(
			                                "StickerContextUtil.placeholder.start").length(), //$NON-NLS-1$
			                placeHolder.length()
			                        - Messages
			                                .getString(
			                                        "StickerContextUtil.placeholder.end").length()); //$NON-NLS-1$
			Object replaceValue = context.peekFieldStack().get(
			        replaceKey.toUpperCase());

			matcher.appendReplacement(result, replaceValue.toString());
			findResult = matcher.find();
		}
		matcher.appendTail(result);

		return result.toString();
	}

	protected StickerContextUtil()
	{
		super();
	}
}
