/**
* Copyright (C) 2010 STMicroelectronics
*
* This file is part of "Mind Compiler" 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 <http://www.gnu.org/licenses/>.
*
* Contact: mind@ow2.org
*
* Authors: Matthieu Leclercq
* Contributors:
*/
package org.ow2.mind.error;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.objectweb.fractal.adl.Node;
import org.objectweb.fractal.adl.error.ChainedErrorLocator;
import org.objectweb.fractal.adl.error.Error;
import org.objectweb.fractal.adl.error.ErrorLocator;
public final class ErrorHelper {
private ErrorHelper() {
}
public static String formatError(final Error error) {
ErrorLocator locator = error.getLocator();
if (locator instanceof ChainedErrorLocator) {
locator = ((ChainedErrorLocator) locator).getRootLocator();
if (locator == null) {
final Iterator<ErrorLocator> iter = ((ChainedErrorLocator) error
.getLocator()).getChainedLocations().iterator();
while (iter.hasNext() && locator == null) {
locator = iter.next();
}
}
}
final String cwd = System.getProperty("user.dir") + File.separator;
final File cwdFile = new File(cwd);
String fileLocation = null;
File inputFile = null;
if (locator != null && locator.getInputFilePath() != null) {
// Convert paths to handle different operating systems, conventions, and
// special characters (such as space ' ', plus '+', etc)
try {
fileLocation = URLDecoder.decode(locator.getInputFilePath(), "UTF-8");
} catch (final UnsupportedEncodingException e) {
fileLocation = locator.getInputFilePath();
}
inputFile = new File(fileLocation);
if (inputFile.getPath().startsWith(cwdFile.getPath())) {
fileLocation = inputFile.getPath().substring(
cwdFile.getPath().length() + 1);
}
}
final StringBuilder sb = new StringBuilder();
if (locator != null && fileLocation != null && inputFile != null) {
sb.append("At ").append(fileLocation);
if (locator.getBeginLine() >= 0) {
sb.append(":").append(locator.getBeginLine());
if (locator.getBeginColumn() >= 0) {
sb.append(",").append(locator.getBeginColumn());
}
}
sb.append(":\n |--> ");
if (locator.getBeginLine() >= 0) {
if (inputFile.exists()) {
try {
final FileReader fileReader = new FileReader(inputFile);
final LineNumberReader lineNumberReader = new LineNumberReader(
fileReader);
for (int i = 0; i < locator.getBeginLine() - 1; i++) {
lineNumberReader.readLine();
}
final String line = lineNumberReader.readLine().replace("\t",
" ");
sb.append(" ").append(line).append("\n |--> ");
if (locator.getBeginColumn() >= 0) {
for (int i = 0; i < locator.getBeginColumn() - 1; i++) {
sb.append(" ");
}
int end = line.length();
if (locator.getEndColumn() >= 0
&& locator.getBeginLine() == locator.getEndLine()) {
end = locator.getEndColumn();
}
for (int i = locator.getBeginColumn(); i < end + 1; i++) {
sb.append("-");
}
sb.append("\n |--> ");
}
lineNumberReader.close();
} catch (final IOException e1) {
// ignore
}
}
}
}
sb.append(error.getMessage()).append("\n");
Throwable cause = error.getCause();
while (cause != null) {
sb.append("caused by : ");
sb.append(cause.getMessage()).append('\n');
cause = cause.getCause();
}
return sb.toString();
}
public static final String ERROR_DECORATION_NAME = "error-list";
public static final String WARNING_DECORATION_NAME = "warning-list";
// This class is use to avoid serialization of Error/Warning list (see
// MIND-119)
private static final class NonSerializableErrorList {
final List<Error> list = new ArrayList<Error>();
}
public static void addError(final Node node, final Error error) {
getErrorListDecoration(node).add(error);
}
public static List<Error> getErrors(final Node node) {
if (node.astGetDecoration(ERROR_DECORATION_NAME) == null) {
return Collections.emptyList();
}
return new ArrayList<Error>(getErrorListDecoration(node));
}
private static List<Error> getErrorListDecoration(final Node node) {
NonSerializableErrorList errors = (NonSerializableErrorList) node
.astGetDecoration(ERROR_DECORATION_NAME);
if (errors == null) {
errors = new NonSerializableErrorList();
node.astSetDecoration(ERROR_DECORATION_NAME, errors);
}
return errors.list;
}
public static void addWarning(final Node node, final Error warning) {
getWarningListDecoration(node).add(warning);
}
public static List<Error> getWarnings(final Node node) {
if (node.astGetDecoration(WARNING_DECORATION_NAME) == null) {
return Collections.emptyList();
}
return new ArrayList<Error>(getWarningListDecoration(node));
}
private static List<Error> getWarningListDecoration(final Node node) {
NonSerializableErrorList warnings = (NonSerializableErrorList) node
.astGetDecoration(WARNING_DECORATION_NAME);
if (warnings == null) {
warnings = new NonSerializableErrorList();
node.astSetDecoration(WARNING_DECORATION_NAME, warnings);
}
return warnings.list;
}
}