/*
* Copyright 2003-2010 Tufts University Licensed under the
* Educational Community 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.osedu.org/licenses/ECL-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.
*/
package tufts.vue.ds;
import tufts.vue.*;
import tufts.vue.ds.XMLIngest.XmlSchema;
import java.util.*;
import java.io.*;
import java.util.List;
import java.awt.*;
import java.nio.charset.Charset;
import javax.swing.*;
import edu.tufts.vue.ui.ConfigurationUI;
import au.com.bytecode.opencsv.CSVReader;
/**
* @version $Revision: 1.27 $ / $Date: 2010-02-03 19:13:16 $ / $Author: mike $
* @author Scott Fraize
*/
public class XmlDataSource extends BrowseDataSource
{
private static final org.apache.log4j.Logger Log = org.apache.log4j.Logger.getLogger(XmlDataSource.class);
private final List<Resource> mItems = new ArrayList<Resource>();
private static final String ITEM_PATH_KEY = "item_path";
private static final String KEY_FIELD_KEY = "key_field";
private static final String IMAGE_FIELD_KEY = "image_field";
private static final String ENCODING_FIELD_KEY = "encoding_field";
private static final String MATRIX_FIELD_KEY = "matrix";
private static final String MATRIX_ROW_KEY ="matrixRow";
private static final String MATRIX_COL_KEY ="matrixCol";
private static final String MATRIX_RELATION_KEY="matrixRelation";
private static final String MATRIX_FORMAT_KEY ="matrixFormat";
private static final String MATRIX_PIVOT_KEY ="matrixPivot";
private static final String MATRIX_STARTROW_KEY ="matrixStartRow";
private static final String MATRIX_MATRIXSIZE_KEY ="matrixSize";
private static final String MATRIX_IGNORE_KEY ="matrixIgnore";
private static final String MATRIX_RELPROCESS_KEY ="matrixRelProcess";
private static final String NONE_SELECTED = "(none selected)";
private static final String AUTO_SELECTED = "(auto detect)";
private static final String WIDE = "wide";
private static final String TALL = "tall";
public static final String TYPE_NAME = "XML Feed";
private String itemKey;
private String keyField;
private String imageField = NONE_SELECTED;
private String encodingField = AUTO_SELECTED;
private String matrixField = "false";
private String matrixRowField = NONE_SELECTED;
private String matrixColField = NONE_SELECTED;
private String matrixRelField = NONE_SELECTED;
private String matrixFormatField = NONE_SELECTED;
private String matrixPivotField = NONE_SELECTED;
private String matrixStartRowField = "";
private String matrixSizeField = "";
private String matrixIgnoreField = "";
private String matrixRelProcessField = "";
private boolean isCSV; // hack while XmlDataSource supports both XML and flat-files
public XmlDataSource() {}
public XmlDataSource(String displayName, String address) throws DataSourceException {
this.setDisplayName(displayName);
this.setAddress(address);
}
@Override
public String getTypeName() {
return TYPE_NAME;
}
@Override
public int getCount() {
return mItems == null ? -1 : mItems.size();
}
@Override public void setConfiguration(java.util.Properties p) {
if (DEBUG.DR) Log.debug(this + " setConfiguration " + p);
super.setConfiguration(p);
String val = null;
try {
if ((val = p.getProperty(ITEM_PATH_KEY)) != null)
setItemKey(val);
} catch (Throwable t) {
Log.error("val=" + val, t);
}
try {
if ((val = p.getProperty(KEY_FIELD_KEY)) != null)
setKeyField(val);
} catch (Throwable t) {
Log.error("val=" + val, t);
}
try {
if ((val = p.getProperty(ENCODING_FIELD_KEY)) != null)
setEncodingField(val);
} catch (Throwable t) {
Log.error("val=" + val, t);
}
try {
if ((val = p.getProperty(MATRIX_FIELD_KEY)) != null)
setMatrixField(val);
} catch (Throwable t) {
Log.error("val=" + val, t);
}
try {
if ((val = p.getProperty(IMAGE_FIELD_KEY)) != null)
setImageField(val);
} catch (Throwable t) {
Log.error("val=" + val, t);
}
try {
if ((val = p.getProperty(MATRIX_ROW_KEY)) != null)
setMatrixRowField(val);
} catch (Throwable t) {
Log.error("val=" + val, t);
}
try {
if ((val = p.getProperty(MATRIX_COL_KEY)) != null)
setMatrixColField(val);
} catch (Throwable t) {
Log.error("val=" + val, t);
}
try {
if ((val = p.getProperty(MATRIX_FORMAT_KEY)) != null)
setMatrixColField(val);
} catch (Throwable t) {
Log.error("val=" + val, t);
}
try {
if ((val = p.getProperty(MATRIX_PIVOT_KEY)) != null)
setMatrixPivotField(val);
} catch (Throwable t) {
Log.error("val=" + val, t);
}
try {
if ((val = p.getProperty(MATRIX_STARTROW_KEY)) != null)
setMatrixStartRowField(val);
} catch (Throwable t) {
Log.error("val=" + val, t);
}
try {
if ((val = p.getProperty(MATRIX_RELATION_KEY)) != null)
setMatrixRelField(val);
} catch (Throwable t) {
Log.error("val=" + val, t);
}
try {
if ((val = p.getProperty(MATRIX_MATRIXSIZE_KEY)) != null)
setMatrixSizeField(val);
} catch (Throwable t) {
Log.error("val=" + val, t);
}
try {
if ((val = p.getProperty(MATRIX_IGNORE_KEY)) != null)
setMatrixIgnoreField(val);
} catch (Throwable t) {
Log.error("val=" + val, t);
}
try {
if ((val = p.getProperty(MATRIX_RELPROCESS_KEY)) != null)
setMatrixRelProcessField(val);
} catch (Throwable t) {
Log.error("val=" + val, t);
}
}
@Override
protected JComponent buildResourceViewer() {
return loadViewer();
}
public String getItemKey() {
return itemKey == null ? "rss.channel.item" : itemKey;
}
public void setItemKey(String k) {
itemKey = k;
unloadViewer();
}
public String getImageField() {
return imageField == NONE_SELECTED ? null : imageField;
}
public void setImageField(String name) {
if (NONE_SELECTED.equals(name))
imageField = NONE_SELECTED;
else
imageField = name;
unloadViewer();
}
public String getKeyField() {
return keyField;
}
public String getMatrixField() {
return matrixField;
}
public String getMatrixRowField() {
return matrixRowField;
}
public String getMatrixColField() {
return matrixColField;
}
public String getMatrixRelField() {
return matrixRelField;
}
public String getMatrixFormatField() {
return matrixFormatField;
}
public String getMatrixPivotField() {
return matrixPivotField;
}
public String getMatrixIgnoreField() {
return matrixIgnoreField;
}
public String getMatrixSizeField() {
return matrixSizeField;
}
public String getMatrixStartRowField() {
return matrixStartRowField;
}
public String getMatrixRelProcessField() {
return matrixRelProcessField;
}
public String getEncodingField() {
if (encodingField.equals("(auto detect)"))
return "windows-1252";
else
return encodingField;
}
public void setKeyField(String k) {
if (DEBUG.DR) Log.debug("setKeyField[" + k + "]");
if (k != null) {
k = k.trim();
if (k.length() < 1)
keyField = null;
else
keyField = k;
} else {
keyField = null;
}
unloadViewer();
}
public void setEncodingField(String k) {
if (DEBUG.DR) Log.debug("setEncodingField[" + k + "]");
if (k != null) {
k = k.trim();
if (k.length() < 1)
encodingField = null;
else
encodingField = k;
} else {
encodingField = null;
}
unloadViewer();
}
public void setMatrixField(String k) {
if (DEBUG.DR) Log.debug("setMatrixField[" + k + "]");
if (k != null) {
k = k.trim();
if (k.length() < 1)
matrixField = null;
else
matrixField = k;
} else {
matrixField = null;
}
unloadViewer();
}
public void setMatrixColField(String k) {
if (DEBUG.DR) Log.debug("setMatrixColField[" + k + "]");
if (k != null) {
k = k.trim();
if (k.length() < 1)
matrixColField = null;
else
matrixColField = k;
} else {
matrixColField = null;
}
// unloadViewer();
}
public void setMatrixRelProcessField(String k) {
if (DEBUG.DR) Log.debug("setMatrixRelProcessField[" + k + "]");
if (k != null) {
k = k.trim();
if (k.length() < 1)
matrixRelProcessField = null;
else
matrixRelProcessField = k;
} else {
matrixRelProcessField = null;
}
// unloadViewer();
}
public void setMatrixFormatField(String k) {
if (DEBUG.DR) Log.debug("setMatrixFormatField[" + k + "]");
if (k != null) {
k = k.trim();
if (k.length() < 1)
matrixFormatField = null;
else
matrixFormatField = k;
} else {
matrixFormatField = null;
}
// unloadViewer();
}
public void setMatrixIgnoreField(String k) {
if (DEBUG.DR) Log.debug("setMatrixIgnoreField[" + k + "]");
if (k != null) {
k = k.trim();
if (k.length() < 1)
matrixIgnoreField = null;
else
matrixIgnoreField = k;
} else {
matrixIgnoreField = null;
}
// unloadViewer();
}
public void setMatrixPivotField(String k) {
if (DEBUG.DR) Log.debug("setMatrixFormatField[" + k + "]");
if (k != null) {
k = k.trim();
if (k.length() < 1)
matrixPivotField = null;
else
matrixPivotField = k;
} else {
matrixPivotField = null;
}
// unloadViewer();
}
public void setMatrixSizeField(String k) {
if (DEBUG.DR) Log.debug("setMatrixSizeField[" + k + "]");
if (k != null) {
k = k.trim();
if (k.length() < 1)
matrixSizeField = null;
else
matrixSizeField = k;
} else {
matrixSizeField = null;
}
// unloadViewer();
}
public void setMatrixStartRowField(String k) {
if (DEBUG.DR) Log.debug("setMatrixStartRowField[" + k + "]");
if (k != null) {
k = k.trim();
if (k.length() < 1)
matrixStartRowField = null;
else
matrixStartRowField = k;
} else {
matrixStartRowField = null;
}
// unloadViewer();
}
public void setMatrixRelField(String k) {
if (DEBUG.DR) Log.debug("setMatrixRelField[" + k + "]");
if (k != null) {
k = k.trim();
if (k.length() < 1)
matrixRelField = null;
else
matrixRelField = k;
} else {
matrixRelField = null;
}
// unloadViewer();
}
public void setMatrixRowField(String k) {
if (DEBUG.DR) Log.debug("setMatrixRowField[" + k + "]");
if (k != null) {
k = k.trim();
if (k.length() < 1)
matrixRowField = null;
else
matrixRowField = k;
} else {
matrixRowField = null;
}
// unloadViewer();
}
@Override public java.util.List<ConfigField> getConfigurationUIFields() {
ConfigField path
= new ConfigField(ITEM_PATH_KEY,
"Item Path",
"XML node path of interest",
getItemKey()); // current value is inserted here
String keyFieldName = getKeyField();
Vector possibleKeyFieldValues = null;
if (mSchema != null) {
if (keyFieldName == null)
keyFieldName = mSchema.getKeyField().getName();
possibleKeyFieldValues = mSchema.getPossibleKeyFieldNames();
}
ConfigField keyField
= new ConfigField(KEY_FIELD_KEY
,"Key Field"
,"Field with a unique value for each item"
,keyFieldName // current value
,edu.tufts.vue.ui.ConfigurationUI.COMBO_BOX_CONTROL);
keyField.values = possibleKeyFieldValues;
ConfigField imageField
= new ConfigField(IMAGE_FIELD_KEY
,"Image/Content Field"
,"Field with a path to an image or resource for displaying in nodes"
,this.imageField // current value
,edu.tufts.vue.ui.ConfigurationUI.COMBO_BOX_CONTROL);
if (mSchema != null) {
imageField.values = new Vector();
imageField.values.add(NONE_SELECTED);
final Vector fieldNames = mSchema.getFieldNames();
Collections.sort(fieldNames);
imageField.values.addAll(fieldNames);
}
ConfigField encodingField
= new ConfigField(ENCODING_FIELD_KEY
,"Read as"
,"Encoding to read data file as."
,this.encodingField // current value
,edu.tufts.vue.ui.ConfigurationUI.COMBO_BOX_CONTROL);
// encodingField.value = new Vector();
SortedMap<String,Charset> sets = java.nio.charset.Charset.availableCharsets();
encodingField.values = new Vector();
encodingField.values.add(AUTO_SELECTED);
encodingField.values.addAll(sets.keySet());
List<ConfigField> fields = super.getConfigurationUIFields();
if (!isCSV)
fields.add(path);
fields.add(keyField);
fields.add(imageField);
if (isCSV)
fields.add(encodingField);
List<ConfigField> mFields = null;
if (this.getMatrixField().equals("true"))
{
if (this.getMatrixFormatField().equals(TALL))
mFields = this.getMatrixConfigurationUIFields(headerValues);
else
mFields = this.getWideMatrixConfigurationUIFields(headerValues);
fields.addAll(mFields);
}
return fields;
}
private JComponent loadViewer() {
Log.debug("loadContentAndBuildViewer...");
tufts.vue.VUE.diagPush("XmlLoad");
JComponent viewer = null;
RuntimeException exception = null;
try {
viewer = loadContentAndBuildViewer();
} catch (RuntimeException re) {
//Log.error("loadViewer", re);
exception = re;
} catch (Throwable t) {
Log.error("loadViewer", t);
} finally {
tufts.vue.VUE.diagPop();
}
if (exception != null)
throw exception;
return viewer;
}
private String[] readLine(BufferedReader r) throws java.io.IOException {
return r.readLine().split(","); // test impl
}
private String[] readLine(CSVReader r) throws java.io.IOException {
return trim(r.readNext());
}
private static String[] trim(String[] values) {
if (values == null)
return null;
for (int i = 0; i < values.length; i++) {
// fixup for au.com.bytecode.opencsv.CSVReader, which leaves whitespace & quotes in the values!
String v = values[i].trim();
if (v.length() > 0 && v.charAt(0) == '"')
v = v.substring(1);
values[i] = v;
}
return values;
}
public Schema ingestCSV(Schema schema, String file, boolean hasColumnTitles) throws java.io.IOException
{
//final Schema schema = new Schema(file);
//final CSVReader reader = new CSVReader(new FileReader(file));
// TODO: need an encoding Win/Mac encoding toggle
// TODO: need handle this in BrowseDataSource openReader (encoding provided by user in data-source config)
// TODO: the Open CSV CSVReader impl is horrible - doesn't handle quoted values properly!
final CSVReader dataStream = new CSVReader(new InputStreamReader(new FileInputStream(file),this.getEncodingField()));
//final BufferedReader dataStream = new BufferedReader(new InputStreamReader(new FileInputStream(file), "windows-1252"));
String[] values = readLine(dataStream);
if (schema == null) {
//if (DEBUG.SCHEMA) Log.debug("no current schema, instancing new");
schema = Schema.getNewAuthorityInstance(Resource.instance(file), getGUID(), getDisplayName());
} else {
if (DEBUG.SCHEMA) Log.debug("reloading schema " + schema);
schema.setResource(Resource.instance(file));
}
schema.flushData();
if (values == null)
throw new IOException(file + ": empty file?");
if (hasColumnTitles) {
schema.ensureFields(values);
values = readLine(dataStream);
} else {
schema.ensureFields(values.length);
}
if (values == null)
throw new IOException(file + ": has column names, but no data");
do {
schema.addRow(values);
} while ((values = readLine(dataStream)) != null);
dataStream.close();
schema.notifyAllRowsAdded();
return schema;
}
protected String[] headerValues = null;
private static String readFileAsString(String filePath)
throws java.io.IOException{
StringBuffer fileData = new StringBuffer(1000);
BufferedReader reader = new BufferedReader(
new FileReader(filePath));
char[] buf = new char[1024];
int numRead=0;
while((numRead=reader.read(buf)) != -1){
String readData = String.valueOf(buf, 0, numRead);
fileData.append(readData);
buf = new char[1024];
}
reader.close();
return fileData.toString();
}
public Schema ingestMatrixCSV(Schema schema, String file, boolean hasColumnTitles) throws java.io.IOException
{
final boolean isMatrixDataset = true;
int matrixSize = 0;
//final Schema schema = new Schema(file);
//final CSVReader reader = new CSVReader(new FileReader(file));
// TODO: need an encoding Win/Mac encoding toggle
// TODO: need handle this in BrowseDataSource openReader (encoding provided by user in data-source config)
// TODO: the Open CSV CSVReader impl is horrible - doesn't handle quoted values properly!
final CSVReader dataStream = new CSVReader(new InputStreamReader(new FileInputStream(file),this.getEncodingField()));
//final BufferedReader dataStream = new BufferedReader(new InputStreamReader(new FileInputStream(file), "windows-1252"));
String[] values = readLine(dataStream);
headerValues = new String[values.length];
headerValues = values.clone();
if (schema == null) {
//if (DEBUG.SCHEMA) Log.debug("no current schema, instancing new");
schema = Schema.getNewAuthorityInstance(Resource.instance(file), getGUID(), getDisplayName());
} else {
if (DEBUG.SCHEMA) Log.debug("reloading schema " + schema);
schema.setResource(Resource.instance(file));
}
schema.flushData();
if (values == null)
throw new IOException(file + ": empty file?");
if (hasColumnTitles)
{
if (isMatrixDataset)
{
int n=0;
if (this.matrixFormatField.equals(NONE_SELECTED))
{
JPanel p = new JPanel();
p.setLayout(new BorderLayout());
JLabel label = new JLabel();
label.setIcon(VueResources.getImageIcon("widetall"));
JLabel label2 = new JLabel("Is the matrix format wide or tall?");
p.add(label,BorderLayout.CENTER);
p.add(label2,BorderLayout.SOUTH);
//Custom button text
Object[] options = {"Wide",
"Tall"};
n = JOptionPane.showOptionDialog(VUE.getApplicationFrame(),
p,
"Define Matrix Format",
JOptionPane.YES_NO_OPTION,
JOptionPane.PLAIN_MESSAGE,
null,
options,
options[1]);
if (n==0)
this.setMatrixFormatField(WIDE);
else
this.setMatrixFormatField(TALL);
} //matrix format
if (this.matrixFormatField.equals(TALL) &&
(this.matrixColField.equals(NONE_SELECTED) ||
this.matrixRowField.equals(NONE_SELECTED) ||
this.matrixRelField.equals(NONE_SELECTED)))
{
UIParams params = this.getXMLforMatrix(values);
boolean proceed = false;
ConfigurationUI cui = new edu.tufts.vue.ui.ConfigurationUI(new java.io.ByteArrayInputStream(params.xml.getBytes()),params.extraValuesByKey);
cui.setPreferredSize(new Dimension(350, (int)cui.getPreferredSize().getHeight()));
if (VueUtil.option(VUE.getDialogParent(),
cui,
VueResources.getString("optiondialog.configuration.message"),
javax.swing.JOptionPane.DEFAULT_OPTION,
javax.swing.JOptionPane.PLAIN_MESSAGE,
new Object[] {
VueResources.getString("optiondialog.configuration.continue"), VueResources.getString("optiondialog.configuration.cancel")
},
VueResources.getString("optiondialog.configuration.continue")) == 1) {
proceed = false;
} else {
setConfiguration(cui.getProperties());
DataSourceViewer.saveDataSourceViewer();
}
}
else if (this.matrixFormatField.equals(WIDE) && (this.matrixPivotField.equals(NONE_SELECTED)))
{
UIParams params = this.getXMLforWideMatrix(values);
boolean proceed = false;
ConfigurationUI cui = new edu.tufts.vue.ui.ConfigurationUI(new java.io.ByteArrayInputStream(params.xml.getBytes()),params.extraValuesByKey);
cui.setPreferredSize(new Dimension(450, (int)cui.getPreferredSize().getHeight()));
if (VueUtil.option(VUE.getDialogParent(),
cui,
VueResources.getString("optiondialog.configuration.message"),
javax.swing.JOptionPane.DEFAULT_OPTION,
javax.swing.JOptionPane.PLAIN_MESSAGE,
new Object[] {
VueResources.getString("optiondialog.configuration.continue"), VueResources.getString("optiondialog.configuration.cancel")
},
VueResources.getString("optiondialog.configuration.continue")) == 1) {
proceed = false;
} else {
setConfiguration(cui.getProperties());
DataSourceViewer.saveDataSourceViewer();
}
}
}
schema.ensureFields(this,values,isMatrixDataset);
values = readLine(dataStream);
} else {
schema.ensureFields(values.length);
}
if (values == null)
throw new IOException(file + ": has column names, but no data");
String scriptFile = this.getMatrixRelProcessField();
if (scriptFile !=null && scriptFile.length() > 1)
{
//System.out.println(scriptFile);
schema.scriptTemplate = XmlDataSource.readFileAsString(scriptFile);
}
//Clear this out so we can properly cleanly dataset.
schema.existingRows = new HashMap<String,Integer>();
schema.tempTable = new TreeMap<String,DataRow>();
do {
if (this.matrixFormatField.equals(TALL))
schema.addMatrixRow(this,values);
else
schema.addWideMatrixRow(this,values);
} while ((values = readLine(dataStream)) != null);
if (this.matrixFormatField.equals(WIDE))
schema.convertToRows();
dataStream.close();
schema.notifyAllRowsAdded();
return schema;
}
private UIParams getXMLforWideMatrix(String[] values)
{
final UIParams params = new UIParams();
final StringBuilder b = new StringBuilder();
//final String address = dataSource.getAddress();
b.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
b.append("<configuration>\n");
final java.util.Map<String,Vector> extraValuesMap = new java.util.HashMap();
for (ConfigField f : getWideMatrixConfigurationUIFields(values)) {
EditLibraryPanel.addField(b, f.key, f.title, f.description, f.value, f.uiControl, f.maxLen);
if (f.values != null)
extraValuesMap.put(f.key, f.values);
}
params.extraValuesByKey = extraValuesMap;
b.append("</configuration>");
params.xml=b.toString();
return params;
}
private UIParams getXMLforMatrix(String[] values)
{
final UIParams params = new UIParams();
final StringBuilder b = new StringBuilder();
//final String address = dataSource.getAddress();
b.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
b.append("<configuration>\n");
final java.util.Map<String,Vector> extraValuesMap = new java.util.HashMap();
for (ConfigField f : getMatrixConfigurationUIFields(values)) {
EditLibraryPanel.addField(b, f.key, f.title, f.description, f.value, f.uiControl, f.maxLen);
if (f.values != null)
extraValuesMap.put(f.key, f.values);
}
params.extraValuesByKey = extraValuesMap;
b.append("</configuration>");
params.xml=b.toString();
return params;
}
private static class UIParams {
String xml;
// possible enumerated types, indexed by key field
Map<String,Vector> extraValuesByKey = Collections.EMPTY_MAP;
}
private java.util.List<ConfigField> getWideMatrixConfigurationUIFields(String[] values) {
java.util.List<ConfigField> fields = new ArrayList<ConfigField>();
ConfigField field1
= new ConfigField(MATRIX_PIVOT_KEY
,"What is the pivot attribute?"
,"Read CSV as relational matrix"
,this.matrixPivotField // current value
,edu.tufts.vue.ui.ConfigurationUI.COMBO_BOX_CONTROL);
List l = Arrays.asList(values);
//l.add(0, NONE_SELECTED);
field1.values = new Vector(l);
fields.add(field1);
/* ConfigField field2
= new ConfigField(MATRIX_STARTROW_KEY
,"What row # contains the header?"
,"Read CSV as relational matrix"
,this.matrixStartRowField // current value
,edu.tufts.vue.ui.ConfigurationUI.SINGLE_LINE_CLEAR_TEXT_CONTROL);
// field2.values = new Vector(l);
fields.add(field2);
*/
ConfigField field3
= new ConfigField(MATRIX_MATRIXSIZE_KEY
,"# of rows/cols in matrix?"
,"Read CSV as relational matrix"
,this.matrixSizeField // current value
,edu.tufts.vue.ui.ConfigurationUI.SINGLE_LINE_CLEAR_TEXT_CONTROL);
fields.add(field3);
ConfigField field4
= new ConfigField(MATRIX_IGNORE_KEY
,"Ignore matching relations (opt.)"
,"Read CSV as relational matrix"
,this.matrixIgnoreField // current value
,edu.tufts.vue.ui.ConfigurationUI.SINGLE_LINE_CLEAR_TEXT_CONTROL);
fields.add(field4);
ConfigField field5
= new ConfigField(MATRIX_RELPROCESS_KEY
,"Script to process relation (opt.)"
,"Read CSV as relational matrix"
,this.matrixRelProcessField// current value
,edu.tufts.vue.ui.ConfigurationUI.FILECHOOSER_CONTROL);
fields.add(field5);
return fields;
}
private java.util.List<ConfigField> getMatrixConfigurationUIFields(String[] values) {
java.util.List<ConfigField> fields = new ArrayList<ConfigField>();
ConfigField field1
= new ConfigField(MATRIX_ROW_KEY
,"Select row from data"
,"Read CSV as relational matrix"
,this.matrixRowField // current value
,edu.tufts.vue.ui.ConfigurationUI.COMBO_BOX_CONTROL);
List l = Arrays.asList(values);
//l.add(0, NONE_SELECTED);
field1.values = new Vector(l);
fields.add(field1);
ConfigField field2
= new ConfigField(MATRIX_COL_KEY
,"Select column from data"
,"Read CSV as relational matrix"
,this.matrixColField // current value
,edu.tufts.vue.ui.ConfigurationUI.COMBO_BOX_CONTROL);
field2.values = new Vector(l);
fields.add(field2);
ConfigField field3
= new ConfigField(MATRIX_RELATION_KEY
,"Select relationship from data"
,"Read CSV as relational matrix"
,this.matrixRelField // current value
,edu.tufts.vue.ui.ConfigurationUI.COMBO_BOX_CONTROL);
field3.values = new Vector(l);
fields.add(field3);
return fields;
}
private Schema mSchema;
public Schema getSchema()
{
return mSchema;
}
private JComponent loadContentAndBuildViewer() throws java.io.IOException
{
Log.debug("loadContentAndBuildViewer");
final Schema schema;
//boolean isCSV = false;
Log.info("INGESTING " + getAddress() + "...");
boolean newIngest = false;
if (getAddress().toLowerCase().endsWith(".csv")) {
// Note: for CSV data, we pass in the existing schema, permitting it
// to be re-loaded, and preserving existing runtime Schema references.
if (getMatrixField().equals("true"))
schema = ingestMatrixCSV(mSchema, getAddress(), true);
else
schema = ingestCSV(mSchema, getAddress(), true);
mSchema = schema;
isCSV = true;
} else {
// TODO: would be better to pass the existing schema instance into ingestXML
// (as we doo with ingestCSV), and have it be flushed and reloaded with new
// data so we wouldn't have to re-update all runtime LWComponent MetaMap
// Schema references, tho that appears to be be successfully working. But
// besides being cleaner and faster, if we did that, we could keep any
// existing field style information alive that had been stored in the
// schema.
// TODO: What's different about XML schema loading that's not loading
// the user styles?
schema = XMLIngest.ingestXML((XmlSchema) mSchema,openInput(), getItemKey());
newIngest = true;
schema.setDSGUID(getGUID());
mSchema = schema;
//schema = XMLIngest.ingestXML(openAddress(), getItemKey());
}
Log.info("ingested " + getAddress());
if (getKeyField() != null)
mSchema.setKeyField(getKeyField());
if (getEncodingField() != null)
mSchema.setEncodingField(getEncodingField());
schema.setImageField(getImageField());
schema.setName(getDisplayName());
if (newIngest)
schema.notifyAllRowsAdded();
updateAllRuntimeSchemaReferences(schema);
return DataTree.create(schema);
// return buildOldStyleTree(schema);
}
/** find all schema handles in all nodes that match the new schema
* and replace them with pointers to the live data schema */
// todo: handle deleted nodes in undo queue, tho LWComponent setParent should be handling that
private static void updateAllRuntimeSchemaReferences(final Schema newlyLoadedSchema)
{
Schema.reportNewAuthoritativeSchema(newlyLoadedSchema, VUE.getAllMaps());
}
private JComponent buildOldStyleTree(Schema schema)
{
mItems.clear();
final Resource top = Resource.instance(getAddress());
top.reset();
//top.setClientType(Resource.DIRECTORY); // todo: fix later -- Resource.java can't be checked in at the moment
top.setClientType(3);
top.setTitle("XML Data Feed: " + getDisplayName() + " " + new Date());
top.setProperty("URL", getAddress());
//fr.setDataType("xml");
mItems.add(top);
for (DataRow row : schema.getRows()) {
//Resource r = Resource.instance(row.getValue("rss.channel.item.link"));
String link = row.getValue("link");
final Resource r;
if (link != null) {
r = Resource.instance(link);
final String title = row.getValue("title");
r.setProperty("Title", title);
r.setTitle(title);
} else {
String value = row.getValue(getItemKey());
if (value != null && value.startsWith("http:")) {
r = Resource.instance(value);
} else {
r = Resource.instance("#" + getItemKey() + ": " + value);
r.setDataType("xml");
}
r.setTitle(value);
}
//Resource r = Resource.instance(row.getValue("link"));
//r.setTitle(row.getValue("rss.channel.item.title"));
String thumb = row.getValue("media:group.media:content.media:url");
if (thumb != null)
((URLResource)r).setURL_Thumb(thumb);
//r.getProperties().putAll(row.asMap());
// for (Map.Entry<String,String> e : row.asMap().entrySet())
// r.addProperty(e.getKey(), e.getValue());
//for (Map.Entry<String,?> e : tufts.vue.MetaMap.entries(row.asMap()))
for (Map.Entry e : row.dataEntries())
r.addProperty(e.getKey().toString(), e.getValue().toString());
mItems.add(r);
}
//schema.dumpSchema(new PrintWriter(debug));
//top.setProperty("Description", "<pre>" + debug.toString());
if (mItems.size() == 0)
throw new DataSourceException("[Empty XML feed]");
// if (DEBUG.Enabled) {
// for (Map.Entry<String,List<String>> e : headers.entrySet()) {
// Object value = e.getValue();
// if (value instanceof Collection && ((Collection)value).size() == 1)
// value = ((Collection)value).toArray()[0];
// if (e.getKey() == null)
// r.setProperty("HTTP-response", value);
// else
// r.setProperty("HTTP:" + e.getKey(), value);
// }
// }
VueDragTree tree = new VueDragTree(mItems, this.getDisplayName());
tree.setRootVisible(true);
tree.setShowsRootHandles(true);
tree.expandRow(0);
tree.setRootVisible(false);
tree.setName(getClass().getSimpleName() + ": " + getAddress());
return tree;
}
private static boolean TEST_DEBUG = false;
public static void main(String[] args) throws Exception
{
TEST_DEBUG = true;
DEBUG.Enabled = true;
DEBUG.DR = true;
DEBUG.RESOURCE = true;
DEBUG.DATA = true;
tufts.vue.VUE.init(args);
XmlDataSource ds = new XmlDataSource("test", args[0]);
ds.loadContentAndBuildViewer();
}
}