/*
 Copyright (c) 2006 Charles A. Loomis, Jr, Cedric Duprilot, and
 Centre National de la Recherche Scientifique (CNRS).

 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.

 $HeadURL: https://svn.lal.in2p3.fr/LCG/QWG/panc/trunk/src/org/quattor/pan/exceptions/ValidationException.java $
 $Id: ValidationException.java 3454 2008-07-26 18:51:06Z loomis $
 */

package org.quattor.pan.exceptions;

import java.io.File;
import java.util.LinkedList;

import org.quattor.pan.dml.data.Property;
import org.quattor.pan.type.FullType;
import org.quattor.pan.utils.MessageUtils;
import org.quattor.pan.utils.Path;
import org.quattor.pan.utils.Term;

/**
 * Exceptions of this type can be thrown during the validation phase of the
 * processing.
 * 
 * @author loomis
 * 
 */
@SuppressWarnings("serial")
public class ValidationException extends RuntimeException {

	private File objectTemplate;

	private Path path;

	private FullType boundType;

	private LinkedList<Term> terms;

	private LinkedList<String> typeStack;

	private Property value;

	private ValidationException(String message) {
		super(message);

		this.objectTemplate = null;
		path = null;
		boundType = null;

		terms = new LinkedList<Term>();
		typeStack = new LinkedList<String>();
		value = null;
	}

	public static ValidationException create(String msgkey, Object... args) {
		String msg = MessageUtils.format(msgkey, args);
		return new ValidationException(msg);
	}

	public ValidationException setObjectTemplate(File objectTemplate) {
		this.objectTemplate = objectTemplate;
		return this;
	}

	@Override
	public String getMessage() {

		// This is the path of the element that caused the validation error.
		Path rPath = null;
		if (path != null) {
			try {
				rPath = new Path(path, terms.toArray(new Term[terms.size()]));
			} catch (SyntaxException consumed) {
				// This may cause the reported path to be incorrect, but this
				// information is probably better than nothing.
				rPath = path;
			}
		}

		StringBuilder sb = new StringBuilder("validation error [");
		sb.append((objectTemplate != null) ? objectTemplate.toString()
				: "?");
		sb.append("]\n");
		sb.append(super.getMessage());
		sb.append("\n");

		if (rPath != null) {
			sb.append("element path: '");
			sb.append(rPath.toString());
			sb.append("'\n");
		}
		if (value != null) {
			sb.append("element value: ");
			sb.append(value.toString());
			sb.append("\n");
		}

		for (String s : typeStack) {
			sb.append(s);
		}

		if (path != null && boundType != null) {
			sb.append("path '");
			sb.append(path);
			sb.append("' bound to type ");
			sb.append(boundType.getTypeName());
			sb.append(" in [");
			sb.append(boundType.getSource());
			sb.append(":");
			sb.append(boundType.getSourceRange());
			sb.append("]\n");
		}

		if (getCause() != null) {
			sb.append("caused by: ");
			sb.append(getCause().getMessage());
		}

		return sb.toString();
	}

	public ValidationException setPathTypeAndObject(Path path, FullType type,
			File objectTemplate) {
		this.path = path;
		this.boundType = type;
		if (this.objectTemplate == null && objectTemplate != null) {
			this.objectTemplate = objectTemplate;
		}
		return this;
	}

	public ValidationException addTerm(Term term) {
		assert (term != null);
		terms.addFirst(term);
		return this;
	}

	public ValidationException addTypeToStack(String name, FullType type) {

		String source = "?";
		String sourceRange = "?";

		if (type != null) {
			source = type.getSource();
			sourceRange = type.getSourceRange();
		}

		StringBuilder sb = new StringBuilder();
		sb.append("type: '");
		sb.append(name);
		sb.append("' [");
		sb.append(source);
		sb.append(":");
		sb.append(sourceRange);
		sb.append("]\n");

		typeStack.add(sb.toString());

		return this;
	}

	public ValidationException setValue(Property property) {
		this.value = property;
		return this;
	}

}

@@ -1208,18 +1208,17 @@
 sing.%0A *
- 
 %0A
+
  * @auth
@@ -1229,17 +1229,16 @@
 oomis%0A *
- 
 %0A */%0A@Su
@@ -1488,24 +1488,22 @@
 private 
-Property
+Object
  value;%0A
@@ -1893,24 +1893,318 @@
 n(msg);%0A%09%7D%0A%0A
+    /* create exception with value from data */%0A%09public static ValidationException createv(Object data, String msgkey, Object... args) %7B%0A%09%09String msg = MessageUtils.format(msgkey, args);%0A%09%09ValidationException ve = new ValidationException(msg);%0A        ve.setValue(data);%0A        return ve;%0A%09%7D%0A%0A
 %09public Vali
@@ -3077,35 +3077,44 @@
 alue != null) %7B%0A
-%09%09%09
+            
 sb.append(%22eleme
@@ -3123,27 +3123,36 @@
  value: %22);%0A
-%09%09%09
+            
 sb.append(va
@@ -3160,35 +3160,44 @@
 ue.toString());%0A
-%09%09%09
+            
 sb.append(%22%5Cn%22);
@@ -4588,25 +4588,19 @@
 lue(
-Property property
+Object data
 ) %7B%0A
@@ -4618,16 +4618,12 @@
 e = 
-property
+data
 ;%0A%09%09

allow any value and add convenience function to create an exception with value set