/*
 * Copyright 2006 Takahiro Nakamura.
 *
 * 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 woolpack.visitor;

import org.w3c.dom.Element;
import org.w3c.dom.Node;

import woolpack.dom.DomConstants;

/**
 * 定数と静的メソッドの集まり。
 * 
 * @author nakamura
 * 
 */
public final class DomVisitorConstants {

	/**
	 * {@link Visitor#getContext()}を{@link Node}にキャストして、
	 * v をテキストノードに変換して追加する{@link Acceptable}。
	 */
	public static final Acceptable<Object> OBJECT = new Acceptable<Object>() {
		public void accept(final Visitor visitor, final Object v) {
			final Node node = (Node) visitor.getContext();
			node.appendChild(DomConstants.getDocumentNode(node).createTextNode(
					v.toString()));
		}
	};

	/**
	 * {@link Visitor#getContext()}を{@link Node}
	 * にキャストして、 一覧をカンマ区切りで追加する{@link Acceptable}。
	 */
	public static final Acceptable<Iterable> ITERABLE_COMMA
	= new Acceptable<Iterable>() {
		public void accept(final Visitor visitor, final Iterable v) {
			boolean flag = true;
			for (final Object e : v) {
				if (flag) {
					flag = false;
				} else {
					visitor.visit(", ");
				}
				visitor.visit(e);
			}
		}
	};

	private DomVisitorConstants() {
	} // カバレージがここを通過してはいけない

	/**
	 * {@link Visitor#getContext()}を{@link Element}にキャストして、
	 * エレメントを追加して委譲する{@link Acceptable}を返す。
	 * 
	 * @param <V>
	 *            汎用型。
	 * @param elementName
	 *            エレメント名。
	 * @param child
	 *            委譲先。
	 * @return エレメントを追加して委譲する{@link Acceptable}。
	 */
	public static <V> Acceptable<V> addElementAcceptable(
			final String elementName, final Acceptable<V> child) {
		return new Acceptable<V>() {
			public void accept(final Visitor visitor, final V v) {
				final Element node = (Element) visitor.getContext();
				final Element element = DomConstants.getDocumentNode(node)
						.createElement(elementName);
				node.appendChild(element);
				final Visitor newVisitor = visitor.copy();
				newVisitor.setContext(element);
				child.accept(newVisitor, v);
			}
		};
	}
}
