KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jdesktop > dataset > DataSet


1 /*
2  * $Id: DataSet.java,v 1.3 2005/02/25 19:46:13 rbair Exp $
3  *
4  * Copyright 2005 Sun Microsystems, Inc., 4150 Network Circle,
5  * Santa Clara, California 95054, U.S.A. All rights reserved.
6  */

7
8 package org.jdesktop.dataset;
9 import java.beans.PropertyChangeEvent JavaDoc;
10 import java.beans.PropertyChangeListener JavaDoc;
11 import java.io.ByteArrayInputStream JavaDoc;
12 import java.io.File JavaDoc;
13 import java.io.FileInputStream JavaDoc;
14 import java.io.InputStream JavaDoc;
15 import java.math.BigDecimal JavaDoc;
16 import java.util.ArrayList JavaDoc;
17 import java.util.Collections JavaDoc;
18 import java.util.Date JavaDoc;
19 import java.util.HashMap JavaDoc;
20 import java.util.List JavaDoc;
21 import java.util.Map JavaDoc;
22 import javax.xml.parsers.DocumentBuilder JavaDoc;
23 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
24 import javax.xml.xpath.XPath JavaDoc;
25 import javax.xml.xpath.XPathConstants JavaDoc;
26 import javax.xml.xpath.XPathFactory JavaDoc;
27 import org.jdesktop.dataset.event.TableChangeEvent;
28 import org.w3c.dom.Document JavaDoc;
29 import org.w3c.dom.Node JavaDoc;
30 import org.w3c.dom.NodeList JavaDoc;
31
32 /**
33  *
34  * @author rbair
35  */

36 public class DataSet {
37     private String JavaDoc name;
38     private Map JavaDoc<String JavaDoc,DataTable> tables = new HashMap JavaDoc<String JavaDoc,DataTable>();
39     private Map JavaDoc<String JavaDoc,DataRelation> relations = new HashMap JavaDoc<String JavaDoc,DataRelation>();
40     private Map JavaDoc<String JavaDoc,DataValue> values = new HashMap JavaDoc<String JavaDoc,DataValue>();
41
42     private final class NameChangeListener implements PropertyChangeListener JavaDoc {
43         public void propertyChange(PropertyChangeEvent JavaDoc evt) {
44             Object JavaDoc source = evt.getSource();
45             if (source instanceof DataTable) {
46                 DataTable table = (DataTable)source;
47                 tables.remove(evt.getOldValue());
48                 tables.put((String JavaDoc)evt.getNewValue(), table);
49             } else if (source instanceof DataRelation) {
50                 DataRelation relation = (DataRelation)source;
51                 relations.remove(evt.getOldValue());
52                 relations.put((String JavaDoc)evt.getNewValue(), relation);
53             } else if (source instanceof DataValue) {
54                 DataValue value = (DataValue)source;
55                 values.remove(evt.getOldValue());
56                 values.put((String JavaDoc)evt.getNewValue(), value);
57             }
58         }
59     }
60     
61     private NameChangeListener nameChangeListener = new NameChangeListener();
62     
63     public DataSet() {
64     }
65
66     public DataTable createTable() {
67         DataTable table = new DataTable(this);
68         table.addPropertyChangeListener("name", nameChangeListener);
69         tables.put(table.getName(), table);
70         return table;
71     }
72     
73     public DataRelationTable createRelationTable() {
74         DataRelationTable table = new DataRelationTable(this);
75         table.addPropertyChangeListener("name", nameChangeListener);
76         tables.put(table.getName(), table);
77         return table;
78     }
79     
80     public DataRelation createRelation() {
81         DataRelation relation = new DataRelation(this);
82         relation.addPropertyChangeListener("name", nameChangeListener);
83         relations.put(relation.getName(), relation);
84         return relation;
85     }
86     
87     public DataValue createValue() {
88         DataValue value = new DataValue(this);
89         value.addPropertyChangeListener("name", nameChangeListener);
90         values.put(value.getName(), value);
91         return value;
92     }
93         
94     public void dropTable(DataTable table) {
95         dropTable(table.getName());
96     }
97     
98     public void dropTable(String JavaDoc tableName) {
99         tables.remove(tableName).removePropertyChangeListener("name", nameChangeListener);
100     }
101     
102     public void dropRelationTable(DataRelationTable table) {
103         dropTable(table.getName());
104     }
105     
106     public void dropRelationTable(String JavaDoc tableName) {
107         dropTable(tableName);
108     }
109     
110     public void dropRelation(DataRelation relation) {
111         dropRelation(relation.getName());
112     }
113     
114     public void dropRelation(String JavaDoc relationName) {
115         relations.remove(relationName).removePropertyChangeListener("name", nameChangeListener);
116     }
117     
118     public void dropValue(DataValue value) {
119         dropValue(value.getName());
120     }
121     
122     public void dropValue(String JavaDoc valueName) {
123         values.remove(valueName).removePropertyChangeListener("name", nameChangeListener);
124     }
125     
126     protected boolean hasElement(String JavaDoc name) {
127         boolean b = relations.containsKey(name);
128         if (!b) {
129             b = tables.containsKey(name);
130         }
131         if (!b) {
132             b = values.containsKey(name);
133         }
134         return b;
135     }
136     
137     public List JavaDoc<DataRow> getRows(String JavaDoc path) {
138         if (path == null || path.trim().equals("")) {
139             return Collections.EMPTY_LIST;
140         }
141         
142         path = path.trim();
143         
144         //first, split on "."
145
String JavaDoc[] steps = path.split("\\.");
146         
147         //each step is either a specific name ("myTable"), or is a composite
148
//of a name and an index ("myTable[mySelector]")
149

150         //maintain a collection of results
151
List JavaDoc<DataRow> workingSet = null;
152         
153         for (String JavaDoc step : steps) {
154             String JavaDoc name = null;
155             String JavaDoc selectorName = null;
156             if (step.contains("[")) {
157                 name = step.substring(0, step.indexOf('['));
158                 selectorName = step.substring(step.indexOf('[')+1, step.indexOf(']'));
159             }
160             
161             if (workingSet == null) {
162                 //get all of the results from the named object (better be a
163
//table, not a relation!)
164
DataTable table = tables.get(name);
165                 if (table == null) {
166                     assert false;
167                 }
168                 workingSet = table.getRows();
169                 if (selectorName != null) {
170 // workingSet = filterRows(workingSet, selectors.get(selectorName));
171
}
172             } else {
173                 //better be a relation...
174
DataRelation relation = relations.get(name);
175                 if (relation == null) {
176                     assert false;
177                 }
178                 workingSet = relation.getRows((DataRow[])workingSet.toArray(new DataRow[workingSet.size()]));
179                 if (selectorName != null) {
180 // workingSet = filterRows(workingSet, selectors.get(selectorName));
181
}
182             }
183         }
184         return Collections.unmodifiableList(workingSet);
185     }
186     
187     public List JavaDoc<DataRow> filterRows(List JavaDoc<DataRow> rows, DataSelector ds) {
188         List JavaDoc<Integer JavaDoc> indices = ds.getRowIndices();
189         List JavaDoc<DataRow> results = new ArrayList JavaDoc<DataRow>(indices.size());
190         for (int index : indices) {
191             results.add(rows.get(index));
192         }
193         return results;
194     }
195     
196     public List JavaDoc<DataColumn> getColumns(String JavaDoc path) {
197         //path will either include a single table name, or a single
198
//relation name, followed by a single column name
199
String JavaDoc[] parts = path.split("\\.");
200         assert parts.length == 1 || parts.length == 2;
201         
202         DataTable table = tables.get(parts[0]);
203         if (table == null) {
204             DataRelation relation = relations.get(parts[0]);
205             if (relation == null) {
206                 return new ArrayList JavaDoc<DataColumn>();
207             } else {
208                 table = relation.getChildColumn().getTable();
209             }
210         }
211         
212         if (parts.length == 1) {
213             return table.getColumns();
214         } else {
215             List JavaDoc<DataColumn> results = new ArrayList JavaDoc<DataColumn>();
216             results.add(table.getColumn(parts[1]));
217             return Collections.unmodifiableList(results);
218         }
219     }
220     
221     public DataTable getTable(String JavaDoc tableName) {
222         return tables.get(tableName);
223     }
224     
225     public DataRelationTable getRelationTable(String JavaDoc name) {
226         return (DataRelationTable)tables.get(name);
227     }
228     
229     public void load() {
230         for (DataTable table : tables.values()) {
231             if (!(table instanceof DataRelationTable)) {
232                 table.load();
233             }
234         }
235     }
236
237     /**
238      * Constructs a DataSet based on the given XML schema.
239      */

240     public static DataSet createFromSchema(String JavaDoc schema) {
241         DataSet ds = new DataSet();
242         //set up an XML parser to parse the schema
243
try {
244             DocumentBuilder JavaDoc db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
245             Document JavaDoc dom = db.parse(new ByteArrayInputStream JavaDoc(schema.getBytes()));
246             
247             //extract the dataset name
248
XPath JavaDoc xpath = XPathFactory.newInstance().newXPath();
249             ds.name = xpath.evaluate("/schema/@id", dom);
250             
251             //begin extracting the dataset. First, locate the element related
252
//to this dataset (where the name attribute equals the id
253
String JavaDoc expression = "/schema/element[@name='" + ds.name + "']";
254             NodeList JavaDoc nodes = (NodeList JavaDoc)xpath.evaluate(expression, dom, XPathConstants.NODESET);
255             if (nodes != null && nodes.getLength() > 0) {
256                 Node JavaDoc dataSetNode = nodes.item(0);
257                 //now that I have the node, extract the DataTables
258
NodeList JavaDoc tableNodes = (NodeList JavaDoc)xpath.evaluate("complexType/choice/element", dataSetNode, XPathConstants.NODESET);
259                 for (int i=0; i<tableNodes.getLength(); i++) {
260                     Node JavaDoc tableNode = tableNodes.item(i);
261                     DataTable table = ds.createTable();
262                     table.setName(xpath.evaluate("@name", tableNode));
263                     //construct the table's data columns
264
NodeList JavaDoc columnNodes = (NodeList JavaDoc)xpath.evaluate("complexType/sequence/element", tableNode, XPathConstants.NODESET);
265                     for (int j=0; j<columnNodes.getLength(); j++) {
266                         Node JavaDoc colNode = columnNodes.item(j);
267                         DataColumn col = table.createColumn(xpath.evaluate("@name", colNode));
268                         //set the required flag
269
String JavaDoc minOccurs = xpath.evaluate("@minOccurs", colNode);
270                         if (minOccurs.equals("")) {
271                             col.setRequired(true);
272                         }
273                         
274                         String JavaDoc defaultValue = xpath.evaluate("@default", colNode);
275                         String JavaDoc classType = xpath.evaluate("@type", colNode);
276                         if (classType.equals("xs:string")) {
277                             col.setType(String JavaDoc.class);
278                             if (!defaultValue.equals("")) {
279                                 col.setDefaultValue(defaultValue);
280                             }
281                         } else if (classType.equals("xs:decimal")) {
282                             col.setType(BigDecimal JavaDoc.class);
283                             if (!defaultValue.equals("")) {
284                                 col.setDefaultValue(new BigDecimal JavaDoc(defaultValue));
285                             }
286                         } else if (classType.equals("xs:integer") || classType.equals("xs:int")) {
287                             col.setType(Integer JavaDoc.class);
288                             if (!defaultValue.equals("")) {
289                                 col.setDefaultValue(new Integer JavaDoc(defaultValue));
290                             }
291                         } else if (classType.equals("xs:boolean")) {
292                             col.setType(Boolean JavaDoc.class);
293                             if (!defaultValue.equals("")) {
294                                 col.setDefaultValue(Boolean.parseBoolean(defaultValue));
295                             }
296                         } else if (classType.equals("xs:date") || classType.equals("xs:time") || classType.equals("xs.dateTime")) {
297                             col.setType(Date JavaDoc.class);
298                             if (!defaultValue.equals("")) {
299                                 col.setDefaultValue(new Date JavaDoc(Date.parse(defaultValue)));
300                             }
301                         } else if (classType.equals("xs:unsignedByte")) {
302                             col.setType(Byte JavaDoc.class);
303                             if (!defaultValue.equals("")) {
304                                 col.setDefaultValue(new Byte JavaDoc(defaultValue));
305                             }
306                         } else {
307                             System.err.println("unexpected classType: '" + classType + "'");
308                         }
309                     }
310                 }
311             }
312         } catch (Exception JavaDoc e) {
313             e.printStackTrace();
314         }
315         return ds;
316     }
317     
318     /**
319      * Construct and return a proper schema file describing the DataSet
320      */

321     public String JavaDoc getSchema() {
322         StringBuilder JavaDoc buffer = new StringBuilder JavaDoc();
323         buffer.append("<?xml version=\"1.0\" standalone=\"yes\" ?>\n");
324         buffer.append("<xs:schema id=\"DataSet2\" targetNamespace=\"http://www.tempuri.org/DataSet2.xsd\" xmlns:mstns=\"http://www.tempuri.org/DataSet2.xsd\" " +
325                 "xmlns=\"http://www.tempuri.org/DataSet2.xsd\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" " +
326                 "xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\" attributeFormDefault=\"qualified\" elementFormDefault=\"qualified\">\n");
327         buffer.append("\t<xs:element name=\"");
328         buffer.append(name);
329         buffer.append(" msdata:IsDataSet=\"true\">\n");
330         buffer.append("\t\t<xs:complexType>\n");
331         buffer.append("\t\t\t<xs:choice maxOccurs=\"unbounded\">\n");
332         for (DataTable table : tables.values()) {
333             buffer.append("\t\t\t\t<xs:element name=\"");
334             buffer.append(table.getName());
335             buffer.append("\">\n");
336             buffer.append("\t\t\t\t\t<xs:complexType>\n");
337             buffer.append("\t\t\t\t\t\t<xs:sequence>\n");
338             for (DataColumn col : table.getColumns()) {
339                 buffer.append("\t\t\t\t\t\t\t<xs:element name=\"");
340                 buffer.append(col.getName());
341                 buffer.append("\" type=\"");
342                 if (col.getType() == String JavaDoc.class) {
343                     buffer.append("xs:string");
344                 } else if (col.getType() == BigDecimal JavaDoc.class) {
345                     buffer.append("xs:decimal");
346                 } else if (col.getType() == Integer JavaDoc.class) {
347                     buffer.append("xs:integer");
348                 } else if (col.getType() == Boolean JavaDoc.class) {
349                     buffer.append("xs:boolean");
350                 } else if (col.getType() == Date JavaDoc.class) {
351                     buffer.append("xs:dateTime");
352                 } else if (col.getType() == Byte JavaDoc.class) {
353                     buffer.append("xs:unsignedByte");
354                 }
355                 if (col.getDefaultValue() != null) {
356                     buffer.append("\" default=\"");
357                     buffer.append(col.getDefaultValue());
358                 }
359                 if (!col.isRequired()) {
360                     buffer.append("\" minOccurs=\"0");
361                 }
362                 buffer.append("\" />\n");
363             }
364             buffer.append("\t\t\t\t\t\t</xs:sequence>\n");
365             buffer.append("\t\t\t\t\t</xs:complexType>\n");
366             buffer.append("\t\t\t\t</xs:element>\n");
367         }
368         buffer.append("\t\t\t</xs:choice>\n");
369         buffer.append("\t\t</xs:complexType>\n");
370         
371         //TODO write the relations etc out
372

373         //close the document down
374
buffer.append("\t</xs:element>\n");
375         buffer.append("</xs:schema>\n");
376     
377         return buffer.toString();
378     }
379     
380     public static DataSet createFromSchema(File JavaDoc f) {
381         String JavaDoc schema = "";
382         try {
383             FileInputStream JavaDoc fis = new FileInputStream JavaDoc(f);
384             DataSet ds = createFromSchema(fis);
385             fis.close();
386             return ds;
387         } catch (Exception JavaDoc e) {
388             e.printStackTrace();
389             return null;
390         }
391     }
392     
393     public static DataSet createFromSchema(InputStream JavaDoc is) {
394         String JavaDoc schema = "";
395         try {
396             StringBuilder JavaDoc builder = new StringBuilder JavaDoc();
397             byte[] bytes = new byte[4096];
398             int length = -1;
399             while ((length = is.read(bytes)) != -1) {
400                 builder.append(new String JavaDoc(bytes, 0, length));
401             }
402             schema = builder.toString();
403             return createFromSchema(schema);
404         } catch (Exception JavaDoc e) {
405             e.printStackTrace();
406             return null;
407         }
408     }
409     
410     public void readXml(File JavaDoc f) {
411         String JavaDoc xml = "";
412         try {
413             FileInputStream JavaDoc fis = new FileInputStream JavaDoc(f);
414             readXml(fis);
415             fis.close();
416         } catch (Exception JavaDoc e) {
417             e.printStackTrace();
418         }
419     }
420     
421     public void readXml(InputStream JavaDoc is) {
422         String JavaDoc xml = "";
423         try {
424             StringBuilder JavaDoc builder = new StringBuilder JavaDoc();
425             byte[] bytes = new byte[4096];
426             int length = -1;
427             while ((length = is.read(bytes)) != -1) {
428                 builder.append(new String JavaDoc(bytes, 0, length));
429             }
430             xml = builder.toString();
431             readXml(xml);
432         } catch (Exception JavaDoc e) {
433             e.printStackTrace();
434         }
435     }
436     
437     public void readXml(String JavaDoc xml) {
438         //TODO when parsing the xml, validate it against the xml schema
439

440         try {
441             DocumentBuilder JavaDoc db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
442             Document JavaDoc dom = db.parse(new ByteArrayInputStream JavaDoc(xml.getBytes()));
443
444             //create the xpath
445
XPath JavaDoc xpath = XPathFactory.newInstance().newXPath();
446             
447             //for each table, find all of its items
448
for (DataTable table : tables.values()) {
449                 if (!(table instanceof DataRelationTable)) {
450                     //clear out the table
451
table.clear();
452                     //get the nodes
453
NodeList JavaDoc nodes = (NodeList JavaDoc)xpath.evaluate("/" + name + "/" + table.getName(), dom, XPathConstants.NODESET);
454                     //for each node, iterate through the columns, loading their values
455
for (int i=0; i<nodes.getLength(); i++) {
456                         //each rowNode node represents a row
457
Node JavaDoc rowNode = nodes.item(i);
458                         DataRow row = table.appendRowNoEvent();
459                         NodeList JavaDoc cols = rowNode.getChildNodes();
460                         for (int j=0; j<cols.getLength(); j++) {
461                             Node JavaDoc colNode = cols.item(j);
462                             if (colNode.getNodeType() == Node.ELEMENT_NODE) {
463                                 //TODO this doesn't take into account type conversion...
464
//could use a default converter...
465
System.out.println(colNode.getNodeName() + "=" + colNode.getTextContent());
466                                 row.setValue(colNode.getNodeName(), colNode.getTextContent());
467                             }
468                         }
469                         row.setStatus(DataRow.DataRowStatus.UNCHANGED);
470                     }
471                     table.fireDataTableChanged(new TableChangeEvent(table));
472                 }
473             }
474         } catch (Exception JavaDoc e) {
475             e.printStackTrace();
476         }
477     }
478     
479     public String JavaDoc writeXml() {
480         StringBuilder JavaDoc builder = new StringBuilder JavaDoc();
481         builder.append("<?xml version=\"1.0\" ?>\n");
482         builder.append("<");
483         builder.append(name);
484         builder.append(">\n");
485         for (DataTable table : tables.values()) {
486             if (!(table instanceof DataRelationTable)) {
487                 for (DataRow row : table.rows) {
488                     builder.append("\t<");
489                     builder.append(table.getName());
490                     builder.append(">\n");
491
492                     for (DataColumn col : table.columns.values()) {
493                         builder.append("\t\t<");
494                         builder.append(col.getName());
495                         builder.append(">");
496                         builder.append(row.getValue(col));
497                         builder.append("</");
498                         builder.append(col.getName());
499                         builder.append(">\n");
500                     }
501
502                     builder.append("\t</");
503                     builder.append(table.getName());
504                     builder.append(">\n");
505                 }
506             }
507         }
508         builder.append("</");
509         builder.append(name);
510         builder.append(">");
511         
512         return builder.toString();
513     }
514     
515     public static void main(String JavaDoc[] args) {
516         DataSet ds = createFromSchema(new File JavaDoc("/home/rb156199/dataset.xsd"));
517         System.out.println("DataSet: " + ds.name);
518         for (DataTable table : ds.tables.values()) {
519             System.out.println("\tDataTable: " + table.getName());
520             for (DataColumn col : table.getColumns()) {
521                 System.out.println("\t\tDataColumn: " + col.getName());
522             }
523         }
524         
525         System.out.println(ds.getSchema());
526     }
527 }
Popular Tags