use of net.sourceforge.processdash.data.MalformedData in project processdash by dtuma.
the class DataMessageHandler method maybeSaveValue.
private void maybeSaveValue(MessageEvent message, String dataName, SimpleData value, Date editTimestamp) {
// discard malformed data values
if (value instanceof MalformedData) {
logger.warning("When handling message with ID '" + message.getMessageId() + //
"', found malformed definition for '" + dataName + "'. Discarding value.");
return;
}
// check to see if this data element has been edited locally *after*
// the time in the message. If so, prefer the local edit and discard
// this data change.
DataRepository data = ctx.getData();
String localTimestampName = dataName + "/Edit_Timestamp";
if (editTimestamp != null) {
SimpleData localTimestamp = data.getSimpleValue(localTimestampName);
if (localTimestamp instanceof DateData) {
if (((DateData) localTimestamp).getValue().after(editTimestamp))
return;
}
}
// store the value in the data repository
data.userPutValue(dataName, value);
if (editTimestamp != null)
data.putValue(localTimestampName, new DateData(editTimestamp, true));
}
use of net.sourceforge.processdash.data.MalformedData in project processdash by dtuma.
the class DataRepository method instantiateValue.
private SaveableData instantiateValue(String name, String dataPrefix, Object valueObj, boolean readOnly) {
SaveableData o = null;
if (valueObj instanceof SimpleData) {
o = (SimpleData) valueObj;
if (readOnly)
o = o.getEditable(false);
} else if (valueObj instanceof CompiledScript) {
o = new CompiledFunction(name, (CompiledScript) valueObj, this, dataPrefix);
} else if (valueObj instanceof SearchFactory) {
o = ((SearchFactory) valueObj).buildFor(name, this, dataPrefix);
} else if (valueObj instanceof String) {
String value = (String) valueObj;
if (value.startsWith("=")) {
readOnly = true;
value = value.substring(1);
}
try {
o = ValueFactory.createQuickly(name, value, this, dataPrefix);
} catch (MalformedValueException mfe) {
// temporary fix to allow old PSP for Engineers add-on to work in 1.7
if ("![(&&\tCompleted)]".equals(value)) {
valueObj = Compiler.compile("[Completed]");
o = new CompiledFunction(name, (CompiledScript) valueObj, this, dataPrefix);
} else {
o = new MalformedData(value);
}
}
if (readOnly && o != null)
o.setEditable(false);
}
return o;
}
use of net.sourceforge.processdash.data.MalformedData in project processdash by dtuma.
the class DataRepository method mountData.
void mountData(DataFile dataFile, String dataPrefix, Map values) throws InvalidDatafileFormat {
try {
startInconsistency();
boolean registerDataNames = false;
String datafilePath = "internal data";
boolean fileEditable = true;
// if this is a regular file,
if (dataFile != null && dataFile.file != null) {
datafilePath = dataFile.file.getPath();
fileEditable = dataFile.canWrite && Settings.isReadWrite();
// register the names of data elements in this file IF it is
// not global data.
registerDataNames = dataPrefix.length() > 0;
}
Map defaultData = dataFile.inheritedDefinitions;
if (defaultData == null)
defaultData = Collections.EMPTY_MAP;
boolean successful = false;
boolean datafileModified = false;
int retryCount = 10;
while (!successful && retryCount-- > 0) try {
// values map.
for (Iterator i = values.entrySet().iterator(); i.hasNext(); ) {
Map.Entry defn = (Map.Entry) i.next();
String localName = (String) defn.getKey();
Object valueObj = defn.getValue();
String dataName = createDataName(dataPrefix, localName);
SaveableData o = instantiateValue(dataName, dataPrefix, valueObj, !fileEditable);
if (o instanceof MalformedData)
logger.warning("Data value for '" + dataName + "' in file '" + datafilePath + "' is malformed.");
DataElement d = (DataElement) data.get(dataName);
if (d == null) {
boolean isDefaultName = defaultData.containsKey(localName);
if (o != null || isDefaultName) {
try {
add(dataName, isDefaultName, o, IS_NOT_DEFAULT_VAL, dataFile, DO_NOTIFY);
} catch (DataElementAlreadyExistsException e) {
d = e.elem;
}
}
}
if (d != null) {
putValue(dataName, o, IS_NOT_DEFAULT_VAL, NOT_MODIFYING_DATAFILE);
d = (DataElement) data.get(dataName);
if (d != null) {
d.datafile = dataFile;
d.isDefaultName = defaultData.containsKey(localName);
}
}
if (registerDataNames && (o instanceof DoubleData || o instanceof CompiledFunction))
dataElementNameSet.add(localName);
}
// Next, handle the default values that this datafile inherits.
String dataPrefixSlash = dataPrefix + "/";
for (Iterator i = defaultData.entrySet().iterator(); i.hasNext(); ) {
Map.Entry defn = (Map.Entry) i.next();
String localName = (String) defn.getKey();
Object valueObj = defn.getValue();
// name, do nothing.
if (values.containsKey(localName))
continue;
// Ignore renaming operations; they are not relevant.
if (valueObj instanceof DataRenamingOperation)
continue;
boolean shouldCreateEagerly = shouldCreateEagerly(valueObj);
if ("@now".equals(valueObj))
shouldCreateEagerly = datafileModified = true;
String dataName = dataPrefixSlash + localName;
DataElement d = (DataElement) data.get(dataName);
if (d == null) {
if (shouldCreateEagerly) {
// the item doesn't exist, but we should create it anyway.
SaveableData o = instantiateValue(dataName, dataPrefix, valueObj, !fileEditable);
if (o != null) {
try {
add(dataName, IS_DEFAULT_NAME, o, IS_DEFAULT_VAL, dataFile, DO_NOT_NOTIFY);
} catch (DataElementAlreadyExistsException e) {
d = e.elem;
}
}
}
}
if (d != null) {
// a matching data element exists.
d.datafile = dataFile;
d.isDefaultName = true;
dataName = d.name;
if (instantiatedDataMatches(valueObj, d.getValue())) {
// the data element already has the proper value. (This
// will be common, as clients registering data listeners
// will cause lazy data to spring to life even as this
// for loop is executing.) Nothing needs to be done.
} else if (!d.hasListeners()) {
// This element has the wrong value, but no one is
// listening to it. Revert the element to a lazy
// default value.
janitor.cleanup(d);
} else {
// This element has the wrong value, and clients are
// listening to it. Create and save the correct value.
SaveableData o = instantiateValue(dataName, dataPrefix, valueObj, !fileEditable);
putValue(dataName, o, IS_DEFAULT_VAL, NOT_MODIFYING_DATAFILE);
}
}
// send an event stating that the element is added. (Elsewhere in
// DataRepository, added events are never sent for data elements
// with default names (because it cannot tell whether the item is
// springing forth for the first time, or a subsequent time).
repositoryListenerList.dispatchAdded(dataName);
if (registerDataNames && (valueObj instanceof DoubleData || valueObj instanceof CompiledScript))
dataElementNameSet.add(localName);
}
// make a call to getID. We don't need the resulting value, but
// having made the call will cause an ID to be mapped for this
// prefix. This is necessary to allow users to bring up HTML pages
// from their browser's history or bookmark list.
getID(dataPrefix);
if (defaultData == globalDataDefinitions)
globalDataIsMounted = true;
if (datafileModified)
datafileModified(dataFile);
successful = true;
} catch (Throwable e) {
if (retryCount > 0) {
// Try again to open this datafile. Most errors are transient,
// caused by incredibly infrequent thread-related problems.
logger.log(Level.WARNING, "when opening " + datafilePath + " caught error; retrying.", e);
} else {
// We've done our best, but after 10 tries, we still can't open
// this datafile. Give up and throw an exception.
dataFile.invalidate();
closeDatafile(dataPrefix);
throw new InvalidDatafileFormat("Caught unexpected exception " + e);
}
}
} finally {
finishInconsistency();
}
}
Aggregations