]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/tabular/JcrTabularRowIterator.java
Improve CMS UI utilities.
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / tabular / JcrTabularRowIterator.java
1 package org.argeo.cms.tabular;
2
3 import java.io.InputStream;
4 import java.util.ArrayList;
5 import java.util.List;
6 import java.util.concurrent.ArrayBlockingQueue;
7
8 import javax.jcr.Binary;
9 import javax.jcr.Node;
10 import javax.jcr.NodeIterator;
11 import javax.jcr.Property;
12 import javax.jcr.PropertyType;
13 import javax.jcr.RepositoryException;
14
15 import org.apache.commons.io.IOUtils;
16 import org.argeo.api.tabular.ArrayTabularRow;
17 import org.argeo.api.tabular.TabularColumn;
18 import org.argeo.api.tabular.TabularRow;
19 import org.argeo.api.tabular.TabularRowIterator;
20 import org.argeo.cms.ArgeoTypes;
21 import org.argeo.jcr.JcrException;
22 import org.argeo.util.CsvParser;
23
24 /** Iterates over the rows of a {@link ArgeoTypes#ARGEO_TABLE} node. */
25 public class JcrTabularRowIterator implements TabularRowIterator {
26 private Boolean hasNext = null;
27 private Boolean parsingCompleted = false;
28
29 private Long currentRowNumber = 0l;
30
31 private List<TabularColumn> header = new ArrayList<TabularColumn>();
32
33 /** referenced so that we can close it */
34 private Binary binary;
35 private InputStream in;
36
37 private CsvParser csvParser;
38 private ArrayBlockingQueue<List<String>> textLines;
39
40 public JcrTabularRowIterator(Node tableNode) {
41 try {
42 for (NodeIterator it = tableNode.getNodes(); it.hasNext();) {
43 Node node = it.nextNode();
44 if (node.isNodeType(ArgeoTypes.ARGEO_COLUMN)) {
45 Integer type = PropertyType.valueFromName(node.getProperty(
46 Property.JCR_REQUIRED_TYPE).getString());
47 TabularColumn tc = new TabularColumn(node.getProperty(
48 Property.JCR_TITLE).getString(), type);
49 header.add(tc);
50 }
51 }
52 Node contentNode = tableNode.getNode(Property.JCR_CONTENT);
53 if (contentNode.isNodeType(ArgeoTypes.ARGEO_CSV)) {
54 textLines = new ArrayBlockingQueue<List<String>>(1000);
55 csvParser = new CsvParser() {
56 protected void processLine(Integer lineNumber,
57 List<String> header, List<String> tokens) {
58 try {
59 textLines.put(tokens);
60 } catch (InterruptedException e) {
61 // TODO Auto-generated catch block
62 e.printStackTrace();
63 }
64 // textLines.add(tokens);
65 if (hasNext == null) {
66 hasNext = true;
67 synchronized (JcrTabularRowIterator.this) {
68 JcrTabularRowIterator.this.notifyAll();
69 }
70 }
71 }
72 };
73 csvParser.setNoHeader(true);
74 binary = contentNode.getProperty(Property.JCR_DATA).getBinary();
75 in = binary.getStream();
76 Thread thread = new Thread(contentNode.getPath() + " reader") {
77 public void run() {
78 try {
79 csvParser.parse(in);
80 } finally {
81 parsingCompleted = true;
82 IOUtils.closeQuietly(in);
83 }
84 }
85 };
86 thread.start();
87 }
88 } catch (RepositoryException e) {
89 throw new JcrException("Cannot read table " + tableNode, e);
90 }
91 }
92
93 public synchronized boolean hasNext() {
94 // we don't know if there is anything available
95 // while (hasNext == null)
96 // try {
97 // wait();
98 // } catch (InterruptedException e) {
99 // // silent
100 // // FIXME better deal with interruption
101 // Thread.currentThread().interrupt();
102 // break;
103 // }
104
105 // buffer not empty
106 if (!textLines.isEmpty())
107 return true;
108
109 // maybe the parsing is finished but the flag has not been set
110 while (!parsingCompleted && textLines.isEmpty())
111 try {
112 wait(100);
113 } catch (InterruptedException e) {
114 // silent
115 // FIXME better deal with interruption
116 Thread.currentThread().interrupt();
117 break;
118 }
119
120 // buffer not empty
121 if (!textLines.isEmpty())
122 return true;
123
124 // (parsingCompleted && textLines.isEmpty())
125 return false;
126
127 // if (!hasNext && textLines.isEmpty()) {
128 // if (in != null) {
129 // IOUtils.closeQuietly(in);
130 // in = null;
131 // }
132 // if (binary != null) {
133 // JcrUtils.closeQuietly(binary);
134 // binary = null;
135 // }
136 // return false;
137 // } else
138 // return true;
139 }
140
141 public synchronized TabularRow next() {
142 try {
143 List<String> tokens = textLines.take();
144 List<Object> objs = new ArrayList<Object>(tokens.size());
145 for (String token : tokens) {
146 // TODO convert to other formats using header
147 objs.add(token);
148 }
149 currentRowNumber++;
150 return new ArrayTabularRow(objs);
151 } catch (InterruptedException e) {
152 // silent
153 // FIXME better deal with interruption
154 }
155 return null;
156 }
157
158 public void remove() {
159 throw new UnsupportedOperationException();
160 }
161
162 public Long getCurrentRowNumber() {
163 return currentRowNumber;
164 }
165
166 public List<TabularColumn> getHeader() {
167 return header;
168 }
169
170 }