blob: a47b8c69965530be72413ec5bdac2626062fac2b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 University of Illinois 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:
* Albert L. Rossi - design and implementation
******************************************************************************/
package org.eclipse.ptp.rm.pbs.core.attributes;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.eclipse.ptp.core.attributes.BooleanAttributeDefinition;
import org.eclipse.ptp.core.attributes.DateAttributeDefinition;
import org.eclipse.ptp.core.attributes.DoubleAttributeDefinition;
import org.eclipse.ptp.core.attributes.IAttributeDefinition;
import org.eclipse.ptp.core.attributes.IllegalValueException;
import org.eclipse.ptp.core.attributes.IntegerAttributeDefinition;
import org.eclipse.ptp.core.attributes.StringAttributeDefinition;
import org.eclipse.ptp.rm.pbs.core.IPBSNonNLSConstants;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.ibm.icu.text.DateFormat;
/**
* Abstraction of Job Attribute XML. Serializes and deserializes; maintains
* mappings of definitions, string constraints, qsub flags and tooltips. <br>
*
* This implementation of IPBSJobAttributeData is currently used for both
* initial configuration and storage; eventually initialization will take place
* solely via the model definition.
*
* @author arossi
* @since 5.0
*/
public class PBSXMLJobAttributeData implements IPBSJobAttributeData, IPBSNonNLSConstants {
protected Map<String, IAttributeDefinition<?, ?, ?>> definitions;
protected Map<String, String[]> constrained;
protected Properties flags;
protected Properties tooltips;
protected Map<String, String> minSet;
public void deserialize(InputStream inputStream) throws Throwable {
clearAll();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
Document doc = factory.newDocumentBuilder().parse(inputStream);
if (doc != null)
parseDocument(doc);
}
public Map<String, IAttributeDefinition<?, ?, ?>> getAttributeDefinitionMap() throws Throwable {
return definitions;
}
public Map<String, String[]> getConstrained() throws Throwable {
return constrained;
}
public Map<String, String> getMinSet() throws Throwable {
if (minSet == null)
minSet = new HashMap<String, String>();
return minSet;
}
public Properties getPBSQsubFlags() throws Throwable {
return flags;
}
public Properties getToolTips() throws Throwable {
return tooltips;
}
public void serialize(OutputStream outputStream) throws Throwable {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
Document doc = factory.newDocumentBuilder().newDocument();
Element top = doc.createElement(ATTRIBUTES);
for (String name : definitions.keySet())
appendJobAttribute(name, doc, top);
doc.appendChild(top);
serialize(doc, outputStream);
}
private void appendAttributeDefinition(BooleanAttributeDefinition definition, Document doc, Element parent) {
Element child = doc.createElement(DEFINITION);
setCommonAttributes(definition.getId(), BOOLEAN, definition.getDisplay(), child);
appendDescription(definition, doc, child);
parent.appendChild(child);
}
private void appendAttributeDefinition(DateAttributeDefinition definition, Document doc, Element parent) {
Element child = doc.createElement(DEFINITION);
setCommonAttributes(definition.getId(), DATE, definition.getDisplay(), child);
appendDescription(definition, doc, child);
DateFormat df = definition.getDateFormat();
if (df != null) {
Element format = doc.createElement(DATE);
format.setTextContent(df.toString());
child.appendChild(format);
}
appendMinMax(definition.getMinDate(), definition.getMaxDate(), doc, child);
parent.appendChild(child);
}
private void appendAttributeDefinition(DoubleAttributeDefinition definition, Document doc, Element parent) {
Element child = doc.createElement(DEFINITION);
setCommonAttributes(definition.getId(), DOUBLE, definition.getDisplay(), child);
appendDescription(definition, doc, child);
appendMinMax(definition.getMinValue(), definition.getMaxValue(), doc, child);
parent.appendChild(child);
}
private void appendAttributeDefinition(IntegerAttributeDefinition definition, Document doc, Element parent) {
Element child = doc.createElement(DEFINITION);
setCommonAttributes(definition.getId(), INTEGER, definition.getDisplay(), child);
appendDescription(definition, doc, child);
appendMinMax(definition.getMinValue(), definition.getMaxValue(), doc, child);
parent.appendChild(child);
}
private void appendAttributeDefinition(StringAttributeDefinition definition, Document doc, Element parent) {
Element child = doc.createElement(DEFINITION);
String name = definition.getName();
String[] choices = constrained.get(name);
Element choice = null;
String type = STRING;
if (choices != null && choices.length > 0) {
type = CHOICE;
choice = doc.createElement(CHOICE);
StringBuffer sb = new StringBuffer(choices[0]);
for (int i = 1; i < choices.length; i++)
sb.append(CM).append(choices[i]);
choice.setTextContent(sb.toString());
}
setCommonAttributes(definition.getId(), type, definition.getDisplay(), child);
appendDescription(definition, doc, child);
parent.appendChild(child);
if (choice != null)
parent.appendChild(choice);
}
private void appendDescription(IAttributeDefinition<?, ?, ?> definition, Document doc, Element parent) {
String d = definition.getDescription();
if (d != null) {
Element description = doc.createElement(DESCRIPTION);
description.setTextContent(d);
parent.appendChild(description);
}
}
private void appendJobAttribute(String name, Document doc, Element parent) throws Throwable {
String tooltip = tooltips.getProperty(name);
if (TAG_INTERNAL.equals(tooltip))
return;
Element jobAttribute = doc.createElement(ATTRIBUTE);
jobAttribute.setAttribute(NAME, name);
if (minSet.containsKey(name))
jobAttribute.setAttribute(MINSET, TRUE);
IAttributeDefinition<?, ?, ?> attribute = definitions.get(name);
if (attribute instanceof BooleanAttributeDefinition)
appendAttributeDefinition((BooleanAttributeDefinition) attribute, doc, jobAttribute);
else if (attribute instanceof DateAttributeDefinition)
appendAttributeDefinition((DateAttributeDefinition) attribute, doc, jobAttribute);
else if (attribute instanceof DoubleAttributeDefinition)
appendAttributeDefinition((DoubleAttributeDefinition) attribute, doc, jobAttribute);
else if (attribute instanceof IntegerAttributeDefinition)
appendAttributeDefinition((IntegerAttributeDefinition) attribute, doc, jobAttribute);
else if (attribute instanceof StringAttributeDefinition)
appendAttributeDefinition((StringAttributeDefinition) attribute, doc, jobAttribute);
appendQsubFlag(name, doc, jobAttribute);
appendTooltip(tooltip, doc, jobAttribute);
parent.appendChild(jobAttribute);
}
private void appendMinMax(Object min, Object max, Document doc, Element child) {
if (min != null) {
Element e = doc.createElement(MIN);
e.setTextContent(min.toString());
child.appendChild(e);
}
if (max != null) {
Element e = doc.createElement(MAX);
e.setTextContent(max.toString());
child.appendChild(e);
}
}
private void appendQsubFlag(String name, Document doc, Element parent) {
String flag = flags.getProperty(name);
Element e = doc.createElement(FLAG);
e.setTextContent(flag);
parent.appendChild(e);
}
private void appendTooltip(String tooltip, Document doc, Element parent) throws IllegalValueException {
Element e = doc.createElement(TOOLTIP);
e.setTextContent(tooltip);
parent.appendChild(e);
}
private void clearAll() {
if (definitions == null)
definitions = new TreeMap<String, IAttributeDefinition<?, ?, ?>>();
else
definitions.clear();
if (flags == null)
flags = new Properties();
else
flags.clear();
if (tooltips == null)
tooltips = new Properties();
else
tooltips.clear();
if (constrained == null)
constrained = new HashMap<String, String[]>();
else
constrained.clear();
if (minSet == null)
minSet = new HashMap<String, String>();
else
minSet.clear();
}
private Element getSingletonElement(Element element, String name) {
NodeList nodelist = element.getElementsByTagName(name);
if (nodelist != null) {
Node node = nodelist.item(0);
if (node != null)
if (node.getNodeType() == Node.ELEMENT_NODE)
return (Element) node;
}
return null;
}
private void handleAttributeDefinition(String name, Element child) throws ParseException, IllegalValueException {
String description = null;
Element e = getSingletonElement(child, DESCRIPTION);
if (e != null)
description = e.getTextContent().trim();
String id = child.getAttribute(ID);
String type = child.getAttribute(TYPE);
String displayStr = child.getAttribute(DISPLAY);
boolean display = displayStr == null ? false : Boolean.valueOf(displayStr).booleanValue();
String defaultValue = null;
e = getSingletonElement(child, DEFAULT);
if (e != null)
defaultValue = e.getTextContent();
if (BOOLEAN.equals(type))
handleBooleanAttribute(id, name, display, description, defaultValue);
else if (STRING.equals(type))
handleStringAttribute(id, name, display, description, defaultValue);
else if (CHOICE.equals(type)) {
e = getSingletonElement((Element) child.getParentNode(), CHOICE);
if (e != null)
constrained.put(name, e.getTextContent().split(CM));
handleStringAttribute(id, name, display, description, defaultValue);
} else {
String min = null;
String max = null;
e = getSingletonElement(child, MIN);
if (e != null)
min = e.getTextContent().trim();
e = getSingletonElement(child, MAX);
if (e != null)
max = e.getTextContent().trim();
if (DATE.equals(type)) {
String format = null;
e = getSingletonElement(child, FORMAT);
if (e != null)
format = e.getTextContent().trim();
handleDateAttribute(id, name, display, description, defaultValue, format, min, max);
} else if (DOUBLE.equals(type))
handleDoubleAttribute(id, name, display, description, defaultValue, min, max);
else if (INTEGER.equals(type))
handleIntegerAttribute(id, name, display, description, defaultValue, min, max);
}
}
private void handleBooleanAttribute(String id2, String name2, boolean display, String description2, String defaultValue) {
boolean dval = defaultValue == null ? false : Boolean.valueOf(defaultValue).booleanValue();
definitions.put(name2, new BooleanAttributeDefinition(id2, name2, description2, display, dval));
}
private void handleDateAttribute(String id2, String name2, boolean display, String description2, String defaultValue,
String format2, String min2, String max2) throws ParseException, IllegalValueException {
DateFormat df = DateFormat.getPatternInstance(format2);
Date dval = defaultValue == null ? null : df.parse(defaultValue);
Date min = min2 == null ? null : df.parse(min2);
Date max = max2 == null ? null : df.parse(max2);
if (min != null && max != null) {
if (dval == null)
dval = min;
definitions.put(name2, new DateAttributeDefinition(id2, name2, description2, display, dval, df, min, max));
} else
definitions.put(name2, new DateAttributeDefinition(id2, name2, description2, display, dval, df));
}
private void handleDoubleAttribute(String id2, String name2, boolean display, String description2, String defaultValue,
String min2, String max2) throws IllegalValueException {
Double dval = defaultValue == null ? null : new Double(defaultValue);
Double min = min2 == null ? null : new Double(min2);
Double max = max2 == null ? null : new Double(max2);
if (min != null) {
if (max == null)
max = Double.MAX_VALUE;
} else if (max != null)
if (min == null)
max = Double.MIN_VALUE;
if (min != null && max != null) {
if (dval == null)
dval = min;
definitions.put(name2, new DoubleAttributeDefinition(id2, name2, description2, display, dval, min, max));
} else
definitions.put(name2, new DoubleAttributeDefinition(id2, name2, description2, display, dval));
}
private void handleIntegerAttribute(String id2, String name2, boolean display, String description2, String defaultValue,
String min2, String max2) throws IllegalValueException {
Integer dval = defaultValue == null ? null : new Integer(defaultValue);
Integer min = min2 == null ? null : new Integer(min2);
Integer max = max2 == null ? null : new Integer(max2);
if (min != null) {
if (max == null)
max = Integer.MAX_VALUE;
} else if (max != null)
if (min == null)
max = Integer.MIN_VALUE;
if (min != null && max != null) {
if (dval == null)
dval = min;
definitions.put(name2, new IntegerAttributeDefinition(id2, name2, description2, display, dval, min, max));
} else
definitions.put(name2, new IntegerAttributeDefinition(id2, name2, description2, display, dval));
}
private void handleJobAttributeDefinitionElement(Element element) throws ParseException, IllegalValueException {
String name = element.getAttribute(NAME);
String isMinSet = element.getAttribute(MINSET);
if (TRUE.equals(isMinSet))
minSet.put(name, null);
Element child = getSingletonElement(element, TOOLTIP);
if (child != null)
try {
handleTooltip(name, child);
} catch (IllegalValueException ive) {
return;
}
child = getSingletonElement(element, DEFINITION);
if (child != null)
handleAttributeDefinition(name, child);
child = getSingletonElement(element, FLAG);
if (child != null)
handleQsubFlag(name, child);
}
private void handleQsubFlag(String name, Element child) {
flags.put(name, child.getTextContent());
}
private void handleStringAttribute(String id2, String name2, boolean display, String description2, String defaultValue) {
definitions.put(name2, new StringAttributeDefinition(id2, name2, description2, display, defaultValue));
}
private void handleTooltip(String name, Element child) throws IllegalValueException {
if (TAG_INTERNAL.equals(child.getTextContent()))
throw new IllegalValueException(TAG_INTERNAL);
tooltips.put(name, child.getTextContent());
}
private void parseDocument(Document doc) throws ParseException, IllegalValueException {
NodeList attributeDefinitions = doc.getElementsByTagName(ATTRIBUTE);
for (int i = 0; i < attributeDefinitions.getLength(); i++) {
Node node = attributeDefinitions.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element e = (Element) node;
handleJobAttributeDefinitionElement(e);
}
}
}
private void serialize(Document doc, OutputStream out) throws Exception {
TransformerFactory tfactory = TransformerFactory.newInstance();
Transformer serializer;
try {
serializer = tfactory.newTransformer();
// Setup indenting to "pretty print"
serializer.setOutputProperty(OutputKeys.INDENT, YES);
serializer.setOutputProperty(INDENTATION, INDENT_SPACES);
serializer.transform(new DOMSource(doc), new StreamResult(out));
} catch (TransformerException e) {
// this is fatal, just dump the stack and throw a runtime exception
e.printStackTrace();
throw new RuntimeException(e);
}
}
private void setCommonAttributes(String id, String type, boolean display, Element child) {
child.setAttribute(ID, id);
child.setAttribute(TYPE, type);
child.setAttribute(DISPLAY, ZEROSTR + display);
}
}