/*******************************************************************************
 * Copyright (c) 2009 itemis AG (http://www.itemis.eu) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package org.eclipse.xtext.xtext;

import org.eclipse.xtext.Keyword;
import org.eclipse.xtext.common.services.DefaultTerminalConverters;
import org.eclipse.xtext.conversion.IValueConverter;
import org.eclipse.xtext.conversion.ValueConverter;
import org.eclipse.xtext.conversion.ValueConverterException;
import org.eclipse.xtext.conversion.impl.AbstractNullSafeConverter;
import org.eclipse.xtext.conversion.impl.KeywordAlternativeConverter;
import org.eclipse.xtext.nodemodel.ILeafNode;
import org.eclipse.xtext.nodemodel.INode;

import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;

/**
 * @author Sebastian Zarnekow - Initial contribution and API
 */
@Singleton
public class XtextValueConverters extends DefaultTerminalConverters {

	@Inject
	private Provider<KeywordAlternativeConverter> validIDConverter;
	
	@ValueConverter(rule = "ValidID")
	public IValueConverter<String> ValidID() {
		return validIDConverter.get();
	}
	
	@ValueConverter(rule = "GrammarID")
	public IValueConverter<String> GrammarID() {
		return new AbstractNullSafeConverter<String>() {
			@Override
			protected String internalToValue(String string, INode node) throws ValueConverterException {
				StringBuilder result = new StringBuilder();
				for(ILeafNode leaf: node.getLeafNodes()) {
					if (!leaf.isHidden()) {
						if (leaf.getGrammarElement() instanceof Keyword)
							result.append(leaf.getText());
						else
							result.append(ID().toValue(leaf.getText(), leaf));
					}
				}
				return result.toString();
			}

			@Override
			protected String internalToString(String value) {
				String[] splitted = value.split("\\.");
				StringBuilder result = new StringBuilder(value.length());
				for(int i = 0; i < splitted.length; i++) {
					if (i != 0)
						result.append('.');
					result.append(ID().toString(splitted[i]));
				}
				return result.toString();
			}
		};
	}
	
	@ValueConverter(rule = "RuleID")
	public IValueConverter<String> RuleID() {
		return new AbstractNullSafeConverter<String>() {
			@Override
			protected String internalToValue(String string, INode node) throws ValueConverterException {
				StringBuilder result = new StringBuilder();
				for(ILeafNode leaf: node.getLeafNodes()) {
					if (!leaf.isHidden()) {
						if (leaf.getGrammarElement() instanceof Keyword)
							result.append(".");
						else
							result.append(ID().toValue(leaf.getText(), leaf));
					}
				}
				return result.toString();
			}

			@Override
			protected String internalToString(String value) {
				String[] splitted = value.split("\\.");
				StringBuilder result = new StringBuilder(value.length());
				for(int i = 0; i < splitted.length; i++) {
					if (i != 0)
						result.append("::");
					result.append(ID().toString(splitted[i]));
				}
				return result.toString();
			}
		};
	}
	
	@ValueConverter(rule = "LiteralValue")
	public IValueConverter<Boolean> LiteralValue() {
		return new AbstractNullSafeConverter<Boolean>() {
			@Override
			protected Boolean internalToValue(String string, INode node) throws ValueConverterException {
				return "+".equals(string);
			}

			@Override
			protected String internalToString(Boolean value) {
				return value.booleanValue() ? "+" : "!";
			}
		};
	}

}

@@ -1682,32 +1682,57 @@
 rterException %7B%0A
+%09%09%09%09if (node != null) %7B%0A%09
 %09%09%09%09StringBuilde
@@ -1759,35 +1759,37 @@
 gBuilder();%0A%09%09%09%09
+%09
 for
+ 
 (ILeafNode leaf:
@@ -1779,32 +1779,33 @@
  (ILeafNode leaf
+ 
 : node.getLeafNo
@@ -1810,32 +1810,33 @@
 Nodes()) %7B%0A%09%09%09%09%09
+%09
 if (!leaf.isHidd
@@ -1835,32 +1835,33 @@
 f.isHidden()) %7B%0A
+%09
 %09%09%09%09%09%09if (leaf.g
@@ -1891,32 +1891,33 @@
 anceof Keyword)%0A
+%09
 %09%09%09%09%09%09%09result.ap
@@ -1936,37 +1936,39 @@
 tText());%0A%09%09%09%09%09%09
+%09
 else%0A
+%09
 %09%09%09%09%09%09%09result.ap
@@ -2010,32 +2010,35 @@
 eaf));%0A%09%09%09%09%09
+%09
 %7D%0A
+%09
 %09%09%09%09%7D%0A
+%09
 %09%09%09%09return r
@@ -2047,32 +2047,347 @@
 ult.toString();%0A
+%09%09%09%09%7D else %7B%0A%09%09%09%09%09String%5B%5D splitted = string.split(%22%5C%5C.%22);%0A%09%09%09%09%09StringBuilder result = new StringBuilder(string.length());%0A%09%09%09%09%09for (int i = 0; i %3C splitted.length; i++) %7B%0A%09%09%09%09%09%09if (i != 0)%0A%09%09%09%09%09%09%09result.append('.');%0A%09%09%09%09%09%09result.append(ID().toValue(splitted%5Bi%5D, null));%0A%09%09%09%09%09%7D%0A%09%09%09%09%09return result.toString();%0A%09%09%09%09%7D%0A
 %09%09%09%7D%0A%0A%09%09%09@Overri

Fix an NPE during ValueConversion of xtext.xtext.GrammarID