blob: a2153cd21fee1a147ef4ed7145ef4b1652d04547 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009 University of Illinois at Urbana-Champaign 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
*
* Contributors:
* UIUC - Initial API and implementation
*******************************************************************************/
package org.eclipse.rephraserengine.core.vpg;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
public class VPGLog<T, R extends TokenRef<T>>
{
public class Entry
{
private boolean isWarning;
private String message;
private R tokenRef;
public Entry(boolean isWarningOnly, String message, R tokenRef)
{
this.isWarning = isWarningOnly;
this.message = message;
this.tokenRef = tokenRef;
}
///////////////////////////////////////////////////////////////////////////
// Accessors
///////////////////////////////////////////////////////////////////////////
/** @return true iff this in a warning entry */
public boolean isWarning()
{
return isWarning;
}
/** @return true iff this is an error entry */
public boolean isError()
{
return !isWarning;
}
/** @return the message to display to the user */
public String getMessage()
{
return message;
}
/** @return the token associated with this error message, or <code>null</code> */
public R getTokenRef()
{
return tokenRef;
}
}
///////////////////////////////////////////////////////////////////////////
// VPG Access
///////////////////////////////////////////////////////////////////////////
/** DO NOT ACCESS THIS FIELD DIRECTLY; call {@link #getVPG()} instead. */
private VPG<?, T, R, ? extends VPGDB<?, T, R, ?>, ? extends VPGLog<T, R>> vpg = null;
/**
* <b>FOR INTERNAL USE ONLY. THIS IS NOT AN API METHOD.</b>
* <p>
* Sets the VPG for which we are storing information.
* <p>
* This method is called by the VPG class constructor.
*
* @param vpg the VPG for which we are storing information
*/
public void setVPG(VPG<?, T, R, ? extends VPGDB<?, T, R, ?>, ? extends VPGLog<T, R>> vpg)
{
this.vpg = vpg;
}
/**
* Returns the VPG for which we are storing information.
* <p>
* This value is set by the VPG class constructor. The user will call the
* VPGDB constructor <i>before</i> calling the VPG class constructor,
* so this field should not be accessed by a VPGDB constructor.
*
* @return the VPG for which we are storing information
*/
protected VPG<?, T, R, ? extends VPGDB<?, T, R, ?>, ? extends VPGLog<T, R>> getVPG()
{
if (vpg == null)
throw new IllegalStateException("This VPG database has not been "
+ "assigned to a VPG. Construct a VPGDB object, and then "
+ "pass it to the VPG or EclipseVPG constructor.");
else
return vpg;
}
///////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////
/** The entries in the log */
protected List<Entry> log = new LinkedList<Entry>();
/** Clears the error/warning log. */
public void clear()
{
log.clear();
notifyListeners();
}
/** Removes all entries for the given file from the error/warning log. */
public void clearEntriesFor(String filename)
{
List<Entry> newLog = new LinkedList<Entry>();
for (Entry entry : log)
{
R tokenRef = entry.getTokenRef();
if (tokenRef == null || !tokenRef.getFilename().equals(filename))
newLog.add(entry);
}
log = newLog;
notifyListeners();
}
/**
* Adds the given warning to the error/warning log.
*
* @param message the warning message to display to the user
*/
public void logWarning(String message)
{
log.add(new Entry(true, message, null));
notifyListeners();
}
/**
* Adds the given warning to the error/warning log.
*
* @param message the warning message to display to the user
* @param filename the file with which the warning is associated
*/
public void logWarning(String message, String filename)
{
log.add(new Entry(true, message, getVPG().createTokenRef(filename, 0, 0)));
notifyListeners();
}
/**
* Adds the given warning to the error/warning log.
*
* @param message the warning message to display to the user
* @param tokenRef a specific token with which the warning is associated;
* for example, if an identifier was used without being
* initialized, it could reference that identifier
*/
public void logWarning(String message, R tokenRef)
{
log.add(new Entry(true, message, tokenRef));
notifyListeners();
}
/**
* Adds the given error to the error/warning log.
*
* @param e an exception that will be displayed to the user
*/
public void logError(Throwable e)
{
StringBuilder sb = new StringBuilder();
sb.append(e.getClass().getName());
sb.append(": ");
sb.append(e.getMessage());
sb.append("\n");
ByteArrayOutputStream bs = new ByteArrayOutputStream();
e.printStackTrace(new PrintStream(bs));
sb.append(bs);
log.add(new Entry(false, sb.toString(), null));
notifyListeners();
}
/**
* Adds the given error to the error/warning log.
*
* @param message the error message to display to the user
*/
public void logError(String message)
{
log.add(new Entry(false, message, null));
notifyListeners();
}
// /**
// * Adds the given error to the error/warning log.
// *
// * @param message the error message to display to the user
// * @param filename the file with which the warning is associated
// */
// public void logError(String message, String filename)
// {
// log.add(new Entry(false, message, createTokenRef(filename, 0, 0)));
// notifyListeners();
// }
/**
* Adds the given error to the error/warning log.
*
* @param message the error message to display to the user
* @param tokenRef a specific token with which the error is associated;
* for example, if an identifier was used but not
* declared, it could reference that identifier
*/
public void logError(String message, R tokenRef)
{
log.add(new Entry(false, message, tokenRef));
notifyListeners();
}
/** @return true iff at least one error exists in the error/warning log */
public boolean hasErrorsLogged()
{
for (Entry entry : log)
if (entry.isError())
return true;
return false;
}
/** @return true iff at least one entry exists in the error/warning log */
public boolean hasErrorsOrWarningsLogged()
{
return !log.isEmpty();
}
/** @return the error/warning log */
public List<Entry> getEntries()
{
return log;
}
/** Prints the error/warning log on the given <code>PrintStream</code> */
public void printOn(PrintStream out)
{
for (Entry entry : log)
{
out.print(entry.isError() ? "ERROR: " : "Warning: ");
out.println(entry.getMessage());
R t = entry.getTokenRef();
if (t != null)
{
out.print(" (");
out.print(t.getFilename());
out.print(", offset ");
out.print(t.getOffset());
out.print(", length ");
out.print(t.getLength());
out.println(")");
}
}
}
////////////////////////////////////////////////////////////////////////////////
// Listener Support
////////////////////////////////////////////////////////////////////////////////
/**
* An object which acts as an Observer [GoF] on the VPG error/warning log.
*
* @author Jeff Overbey
*/
public static interface ILogListener
{
/** Callback method invoked when the VPG error/warning log changes. */
void onLogChange();
}
private Set<ILogListener> listeners = new HashSet<ILogListener>();
/** Adds the given object as a Observer [GoF] of the VPG error/warning log */
public void addLogListener(ILogListener listener)
{
listeners.add(listener);
listener.onLogChange();
}
/** Removes the given object as a Observer [GoF] of the VPG error/warning log */
public void removeLogListener(ILogListener listener)
{
listeners.remove(listener);
}
protected void notifyListeners()
{
for (ILogListener listener : listeners)
listener.onLogChange();
}
}