Author: andy
Date: Mon May 19 13:30:24 2014
New Revision: 1595895
URL: http://svn.apache.org/r1595895
Log:
JENA-696 -- a basic CSV parser in support for SPARQL CSV Results.
Added:
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVParseException.java
(with props)
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVParser.java
(with props)
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVToken.java
(with props)
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVTokenIterator.java
(with props)
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVTokenType.java
(with props)
jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/csv/
jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/csv/TestCSVParser.java
(with props)
Modified:
jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingBase.java
jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/resultset/CSVInput.java
jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/TC_Atlas.java
Modified:
jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingBase.java
URL:
http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingBase.java?rev=1595895&r1=1595894&r2=1595895&view=diff
==============================================================================
---
jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingBase.java
(original)
+++
jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingBase.java
Mon May 19 13:30:24 2014
@@ -72,6 +72,7 @@ abstract public class BindingBase implem
@Override
final public Iterator<Var> vars()
{
+ // Hidesight - replace with accumulator style vars1(accumulator)
Iterator<Var> iter = vars1() ;
if ( parent != null )
iter = IteratorConcat.concat(parent.vars(), iter ) ;
Modified:
jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/resultset/CSVInput.java
URL:
http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/resultset/CSVInput.java?rev=1595895&r1=1595894&r2=1595895&view=diff
==============================================================================
---
jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/resultset/CSVInput.java
(original)
+++
jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/resultset/CSVInput.java
Mon May 19 13:30:24 2014
@@ -18,18 +18,27 @@
package com.hp.hpl.jena.sparql.resultset;
-import java.io.BufferedReader ;
-import java.io.IOException ;
import java.io.InputStream ;
import java.util.ArrayList ;
+import java.util.Iterator ;
import java.util.List ;
-import org.apache.jena.atlas.io.IO ;
+import org.apache.jena.atlas.csv.CSVParser ;
+import org.apache.jena.atlas.iterator.Iter ;
+import org.apache.jena.atlas.iterator.Transform ;
+import org.apache.jena.atlas.logging.FmtLog ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.NodeFactory ;
import com.hp.hpl.jena.query.ResultSet ;
import com.hp.hpl.jena.sparql.ARQException ;
import com.hp.hpl.jena.sparql.core.Var ;
import com.hp.hpl.jena.sparql.engine.ResultSetStream ;
+import com.hp.hpl.jena.sparql.engine.binding.Binding ;
+import com.hp.hpl.jena.sparql.engine.binding.BindingFactory ;
+import com.hp.hpl.jena.sparql.engine.binding.BindingMap ;
/** Convenient comma separated values - see also TSV (tab separated values)
* which outputs full RDF terms (in Turtle-style).
@@ -55,80 +64,78 @@ import com.hp.hpl.jena.sparql.engine.Res
public class CSVInput
{
// This code exists to support the SPARQL WG tests.
-
+ private static Logger log = LoggerFactory.getLogger(CSVInput.class) ;
public static ResultSet fromCSV(InputStream in)
{
- BufferedReader reader = IO.asBufferedUTF8(in);
- List<Var> vars = new ArrayList<Var>();
- List<String> varNames = new ArrayList<String>();
-
- String str = null;
- try
- {
- //Here we try to parse only the Header Row
- str = reader.readLine();
- if (str == null )
- throw new ARQException("CSV Results malformed, input is empty
(no header row)") ;
-
- if ( ! str.isEmpty() )
- {
- String[] tokens = str.split(",") ;
- for ( String token : tokens )
- {
- // It is perfectly valid for a variable name to be
enclosed in quotes as part of CSV encoding even
- // though legal variable names should not contain a
character which would require this
- if (token.startsWith("\"") && token.endsWith("\""))
token = token.substring(1, token.length() - 1);
-
- Var var = Var.alloc(token);
- vars.add(var);
- varNames.add(var.getName());
+ CSVParser parser = CSVParser.create(in) ;
+ final List<Var> vars = vars(parser) ;
+ List<String> varNames = Var.varNames(vars) ;
+ Transform<List<String>, Binding> transform = new
Transform<List<String>, Binding>(){
+ private int count = 1 ;
+ @Override
+ public Binding convert(List<String> row) {
+ if ( row.size() != vars.size() )
+ FmtLog.warn(log, "Row %d: Length=%d: expected=%d", count,
row.size(), vars.size()) ;
+
+ BindingMap binding = BindingFactory.create() ;
+ // Check.
+ for (int i = 0 ; i < vars.size() ; i++ ) {
+ Var v = vars.get(i) ;
+ String field = (i<row.size()) ? row.get(i) : "" ;
+ Node n = NodeFactory.createLiteral(field) ;
+ binding.add(v, n);
}
- }
- }
- catch ( IOException ex )
- {
- throw new ARQException(ex) ;
- }
-
+ count++ ;
+ return binding ;
+ }} ;
+ Iterator<Binding> bindings = Iter.map(parser, transform) ;
+
//Generate an instance of ResultSetStream using TSVInputIterator
//This will parse actual result rows as needed thus minimising memory
usage
- return new ResultSetStream(varNames, null, new
CSVInputIterator(reader, vars));
+ return new ResultSetStream(varNames, null, bindings);
+ }
+
+ private static List<Var> vars(CSVParser parser) {
+ final List<Var> vars = new ArrayList<Var>();
+ List<String> varNames = parser.parse1() ;
+ if ( varNames == null )
+ throw new ARQException("SPARQL CSV Results malformed, input is
empty");
+ for ( String vn : varNames ) {
+ vars.add(Var.alloc(vn)) ;
+ }
+ return vars ;
}
public static boolean booleanFromCSV(InputStream in)
{
- BufferedReader reader = IO.asBufferedUTF8(in);
- String str = null;
- try
- {
- //First try to parse the header
- str = reader.readLine();
- if (str == null) throw new ARQException("CSV Boolean Results
malformed, input is empty");
- str = str.trim(); //Remove extraneous white space
-
- //Expect a header row with single _askResult variable
- if (!str.equals("_askResult")) throw new ARQException("CSV
Boolean Results malformed, did not get expected ?_askResult header row");
-
- //Then try to parse the boolean result
- str = reader.readLine();
- if (str == null) throw new ARQException("CSV Boolean Results
malformed, unexpected end of input after header row");
- str = str.trim();
-
- // It is perfectly valid for a variable name to be enclosed in
quotes as part of CSV encoding even
- // though legal variable names should not contain a character
which would require this
- if (str.startsWith("\"") && str.endsWith("\"")) str =
str.substring(1, str.length() - 1);
-
- if (str.equalsIgnoreCase("true") ||
str.equalsIgnoreCase("yes")) {
- return true;
- } else if (str.equalsIgnoreCase("false") ||
str.equalsIgnoreCase("no")) {
- return false;
- } else {
- throw new ARQException("CSV Boolean Results malformed,
expected one of - true yes false no - but got " + str);
- }
- }
- catch (IOException ex)
- {
- throw new ARQException(ex);
- }
+ CSVParser parser = CSVParser.create(in) ;
+ final List<Var> vars = vars(parser) ;
+ if ( vars.size() != 1 ) {
+ throw new ARQException("CSV Boolean Results malformed: variables
line='"+vars+"'") ;
+ }
+ if ( ! vars.get(0).getName().equals("_askResult")) {
+ FmtLog.warn(log, "Boolean result variable is '%s', not
'_askResult'", vars.get(0).getName()) ;
+ }
+
+
+ List<String> line = parser.parse1() ;
+ if ( line.size() != 1 ) {
+ throw new ARQException("CSV Boolean Results malformed: data
line='"+line+"'") ;
+ }
+ String str = line.get(0) ;
+ boolean b ;
+ if ( str.equalsIgnoreCase("true") || str.equalsIgnoreCase("yes") )
+ b = true ;
+ else if (str.equalsIgnoreCase("false") || str.equalsIgnoreCase("no"))
+ b = false;
+ else {
+ throw new ARQException("CSV Boolean Results malformed, expected
one of - true yes false no - but got " + str);
+ }
+
+ List<String> line2 = parser.parse1() ;
+ if ( line2 != null ) {
+ FmtLog.warn(log, "Extra rows: first is "+line2) ;
+ }
+ return b ;
}
}
Added:
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVParseException.java
URL:
http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVParseException.java?rev=1595895&view=auto
==============================================================================
---
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVParseException.java
(added)
+++
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVParseException.java
Mon May 19 13:30:24 2014
@@ -0,0 +1,27 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache 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.apache.org/licenses/LICENSE-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 org.apache.jena.atlas.csv;
+
+class CSVParseException extends RuntimeException
+{
+ public CSVParseException(String msg, Throwable cause) { super(msg,
cause) ; }
+ public CSVParseException(String msg) { super(msg) ; }
+ public CSVParseException(Throwable cause) { super(cause) ; }
+ public CSVParseException() { super() ; }
+}
Propchange:
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVParseException.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added:
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVParser.java
URL:
http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVParser.java?rev=1595895&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVParser.java
(added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVParser.java
Mon May 19 13:30:24 2014
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache 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.apache.org/licenses/LICENSE-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 org.apache.jena.atlas.csv ;
+
+import java.io.InputStream ;
+import java.util.ArrayList ;
+import java.util.Iterator ;
+import java.util.List ;
+
+import org.apache.jena.atlas.io.IO ;
+import org.apache.jena.atlas.iterator.IteratorSlotted ;
+import org.apache.jena.atlas.iterator.PeekIterator ;
+
+/** Written specifically to handle SPARQL results CSv files.
+ * Replace with a real parser (e.g. Apache Commons CSV when released)
+ */
+public class CSVParser implements Iterable<List<String>>
+{
+ public static CSVParser create(String filename) {
+ InputStream input = IO.openFile(filename) ;
+ return create(input) ;
+ }
+
+ public static CSVParser create(InputStream input) {
+ CSVTokenIterator iter = new CSVTokenIterator(input) ;
+ CSVParser parser = new CSVParser(iter) ;
+ return parser ;
+ }
+ // ----
+
+ private final CSVTokenIterator iter ;
+ private final PeekIterator<CSVToken> pIter ;
+
+ public CSVParser(CSVTokenIterator iter) {
+ this.iter = iter ;
+ this.pIter = new PeekIterator<CSVToken>(iter) ;
+ }
+
+ @Override
+ public Iterator<List<String>> iterator() {
+ return new IteratorSlotted<List<String>>() {
+ @Override
+ protected List<String> moveToNext() {
+ return CSVParser.this.parse1() ;
+ }
+
+ @Override
+ protected boolean hasMore() {
+ return true ;
+ }};
+ }
+
+ public List<String> parse1() {
+ // Get rid of switches. break problems.
+ List<String> line = new ArrayList<String>(100) ;
+
+ loop: while (pIter.hasNext()) {
+ CSVToken t = pIter.next() ;
+ switch (t.type) {
+ case EOF :
+ return null ;
+ case NL :
+ // Blank line = one or none?
+ line.add("") ;
+ return line ;
+ case STRING :
+ case QSTRING :
+ line.add(t.image) ;
+ break ;
+ case COMMA :
+ // Immediate COMMA is an empty term.
+ line.add("") ;
+ continue loop ;
+ default :
+ exception("Syntax error: expected a string or comma.", t) ;
+ }
+ // Expect COMMA or NL
+ if ( !pIter.hasNext() ) {
+ // File ends, no NL.
+ return line ;
+ }
+ // Look at separateor or end
+ CSVToken t2 = pIter.peek() ;
+ switch (t2.type) {
+ case COMMA :
+ pIter.next() ;
+ continue loop ;
+ case NL :
+ case EOF :
+ pIter.next() ;
+ return line ;
+ default :
+ exception("Syntax error: expect comma or end of line.", t)
;
+ }
+ }
+ return null ;
+ }
+ static void exception(String msg, CSVToken t) {
+ if ( t != null && t.line >= 0 && t.col > 0 )
+ msg = String.format("[%s, %s] %s", t.line, t.col, msg) ;
+ throw new CSVParseException(msg) ;
+ }
+
+ static void exception(String msg, long line, long col) {
+ if ( line >= 0 && col > 0 )
+ msg = String.format("[%s, %s] %s", line, col, msg) ;
+ throw new CSVParseException(msg) ;
+ }
+}
Propchange:
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVParser.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVToken.java
URL:
http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVToken.java?rev=1595895&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVToken.java
(added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVToken.java
Mon May 19 13:30:24 2014
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache 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.apache.org/licenses/LICENSE-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 org.apache.jena.atlas.csv;
+
+import static org.apache.jena.atlas.csv.CSVTokenType.COMMA ;
+import static org.apache.jena.atlas.csv.CSVTokenType.EOF ;
+import static org.apache.jena.atlas.csv.CSVTokenType.NL ;
+import org.apache.jena.atlas.lib.Lib ;
+
+class CSVToken
+{
+ final CSVTokenType type ;
+ final String image ;
+ final long line ;
+ final long col ;
+
+ public boolean same(CSVToken obj) {
+ if ( this == obj )
+ return true ;
+ if ( obj == null )
+ return false ;
+ if ( type != obj.type )
+ return false ;
+ if ( type == COMMA || type == NL || type == EOF )
+ return true ;
+
+ if ( image == null && obj.image != null )
+ return false ;
+ return Lib.equal(this.image, obj.image) ;
+ }
+
+ public CSVToken(long line, long col, CSVTokenType type, String image) {
+ super() ;
+ this.type = type ;
+ this.image = image ;
+ this.line = line ;
+ this.col = col ;
+ }
+
+ @Override
+ public String toString() {
+ switch (type) {
+ case STRING :
+ case QSTRING :
+ return "Token [" + line + ", " + col + "] " + type + " |" +
image + "|" ;
+ default :
+ return "Token [" + line + ", " + col + "] " + type ;
+ }
+ }
+}
Propchange:
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVToken.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added:
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVTokenIterator.java
URL:
http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVTokenIterator.java?rev=1595895&view=auto
==============================================================================
---
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVTokenIterator.java
(added)
+++
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVTokenIterator.java
Mon May 19 13:30:24 2014
@@ -0,0 +1,114 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache 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.apache.org/licenses/LICENSE-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 org.apache.jena.atlas.csv ;
+
+import static org.apache.jena.atlas.csv.CSVTokenType.* ;
+
+import java.io.InputStream ;
+
+import org.apache.jena.atlas.io.PeekReader ;
+import org.apache.jena.atlas.iterator.IteratorSlotted ;
+
+class CSVTokenIterator extends IteratorSlotted<CSVToken>
+{
+ private PeekReader in ;
+
+ // One EOF?
+
+ CSVTokenIterator(InputStream input) {
+ this.in = PeekReader.makeUTF8(input) ;
+ }
+
+ @Override
+ protected CSVToken moveToNext() {
+ int ch = in.peekChar() ;
+ if ( ch == '\r' ) {
+ in.readChar() ;
+ ch = in.peekChar() ;
+ if ( ch != '\n' )
+ return new CSVToken(in.getLineNum(), in.getColNum(), NL, "\r")
;
+ // '\n' = drop through.
+ }
+
+ if ( ch == '\n' ) {
+ in.readChar() ;
+ return new CSVToken(in.getLineNum(), in.getColNum(), NL, "\n") ;
+ }
+
+ if ( ch == ',' ) {
+ in.readChar() ;
+ return new CSVToken(in.getLineNum(), in.getColNum(), COMMA, ",") ;
+ }
+
+ long line = in.getLineNum() ;
+ long col = in.getColNum() ;
+
+ // Not -1
+ if ( ch == '"' || ch == '\'' )
+ return new CSVToken(line, col, QSTRING, readQuotedString()) ;
+ else
+ return new CSVToken(line, col, STRING, readUnquotedString()) ;
+ }
+
+ StringBuilder builder = new StringBuilder() ;
+
+ private String readQuotedString() {
+ builder.setLength(0) ;
+ int qCh = in.readChar() ;
+ int ch = qCh ;
+ while (true) {
+ ch = in.readChar() ;
+ if ( ch == -1 )
+ CSVParser.exception("Unterminated quoted string at
end-of-file", in.getLineNum(), in.getColNum()) ;
+ // Newlines are allowed in quoted strings.
+ // if ( ch == '\r' || ch == '\n' )
+ // exception("Unterminated quoted string", in.getLineNum(),
+ // in.getColNum()) ;
+ if ( ch == qCh ) {
+ int ch2 = in.peekChar() ;
+ if ( ch2 != qCh )
+ break ;
+ // Escaped quote
+ in.readChar() ;
+ // Fall through.
+ }
+ builder.append((char)ch) ;
+ }
+ return builder.toString() ;
+ }
+
+ private String readUnquotedString() {
+ builder.setLength(0) ;
+ while (true) {
+ int ch = in.peekChar() ;
+ if ( ch == -1 || ch == '\r' || ch == '\n' )
+ break ;
+ if ( ch == ',' )
+ break ;
+ in.readChar() ;
+ builder.append((char)ch) ;
+ }
+ return builder.toString() ;
+ }
+
+ @Override
+ protected boolean hasMore() {
+ return !in.eof() && in.peekChar() != -1 ;
+ }
+}
Propchange:
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVTokenIterator.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added:
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVTokenType.java
URL:
http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVTokenType.java?rev=1595895&view=auto
==============================================================================
---
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVTokenType.java
(added)
+++
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVTokenType.java
Mon May 19 13:30:24 2014
@@ -0,0 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache 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.apache.org/licenses/LICENSE-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 org.apache.jena.atlas.csv;
+
+public enum CSVTokenType { STRING, QSTRING, COMMA, NL, EOF }
Propchange:
jena/trunk/jena-arq/src/main/java/org/apache/jena/atlas/csv/CSVTokenType.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/TC_Atlas.java
URL:
http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/TC_Atlas.java?rev=1595895&r1=1595894&r2=1595895&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/TC_Atlas.java
(original)
+++ jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/TC_Atlas.java Mon
May 19 13:30:24 2014
@@ -18,6 +18,7 @@
package org.apache.jena.atlas;
+import org.apache.jena.atlas.csv.TestCSVParser ;
import org.apache.jena.atlas.data.TS_Data ;
import org.apache.jena.atlas.event.TS_Event ;
import org.apache.jena.atlas.io.TS_IO ;
@@ -38,6 +39,7 @@ import org.junit.runners.Suite ;
, TS_JSON.class
, TS_Data.class
, TS_Web.class
+ , TestCSVParser.class
})
public class TC_Atlas
Added:
jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/csv/TestCSVParser.java
URL:
http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/csv/TestCSVParser.java?rev=1595895&view=auto
==============================================================================
---
jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/csv/TestCSVParser.java
(added)
+++
jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/csv/TestCSVParser.java
Mon May 19 13:30:24 2014
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache 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.apache.org/licenses/LICENSE-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 org.apache.jena.atlas.csv;
+
+import static org.apache.jena.atlas.csv.CSVTokenType.NL ;
+import static org.apache.jena.atlas.csv.CSVTokenType.QSTRING ;
+import static org.apache.jena.atlas.csv.CSVTokenType.STRING ;
+
+import java.io.ByteArrayInputStream ;
+import java.io.InputStream ;
+import java.io.UnsupportedEncodingException ;
+import java.util.ArrayList ;
+import java.util.List ;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+
+public class TestCSVParser extends BaseTest
+{
+ String[] row1 = {} ;
+ String[] row2 = { "" } ;
+ String[] row3 = { "a", "b" } ;
+ String[] row4 = { "123", "\"aa\"", "'bb'", "\"''\"Z", "A'\"\"'" } ;
+
+ CSVToken t1 = new CSVToken(-1, -1, CSVTokenType.COMMA, ",") ;
+
+
+ @Test public void csv_parse_term_01() { csvTerm("123", STRING, "123") ; }
+ @Test public void csv_parse_term_02() { csvTerm("aa", STRING, "aa") ; }
+ @Test public void csv_parse_term_03() { csvTerm("\" \"", QSTRING, " ") ; }
+ @Test public void csv_parse_term_04() { csvTerm("' '", QSTRING, " ") ; }
+
+ @Test public void csv_parse_term_05() { csvTerm("\"a\"\"b\"", QSTRING,
"a\"b") ; }
+ @Test public void csv_parse_term_06() { csvTerm("'a\"b'", QSTRING,
"a\"b") ; }
+
+ @Test public void csv_parse_term_07() { csvTerm("\n", NL, "\n") ; }
+ @Test public void csv_parse_term_08() { csvTerm("\r", NL, "\n") ; }
+ @Test public void csv_parse_term_09() { csvTerm("\r\n", NL, "\n") ; }
+
+ private static void csvTerm(String input, CSVTokenType type, String output)
+ {
+ try
+ {
+ CSVToken expected = new CSVToken(-1, -1, type, output) ;
+
+ InputStream in = new ByteArrayInputStream(input.getBytes("UTF-8"))
;
+ CSVTokenIterator iter = new CSVTokenIterator(in) ;
+ assertTrue(iter.hasNext()) ;
+ CSVToken t = iter.next() ;
+ assertTrue(expected.same(t)) ;
+ } catch (UnsupportedEncodingException e)
+ {
+ throw new RuntimeException(e) ;
+ }
+ }
+
+ @Test public void csv_parse_01() { csv("\n", new String[][] {{""}}) ; }
+ @Test public void csv_parse_02() { csv("a\n", new String[][] {{"a"}}) ; }
+ @Test public void csv_parse_03() { csv("a,b\n", new String[][] {{"a",
"b"}}) ; }
+ @Test public void csv_parse_04() { csv(",b\n", new String[][] {{"", "b"}})
; }
+ @Test public void csv_parse_05() { csv("a,\n", new String[][] {{"a", ""}})
; }
+ @Test public void csv_parse_06() { csv(",\n", new String[][] {{"", ""}}) ;
}
+ @Test public void csv_parse_07() { csv(",,\n", new String[][] {{"", "",
""}}) ; }
+
+ @Test public void csv_parse_10() { csv("\n\n", new String[][] { {""}, {""}
}) ; }
+ @Test public void csv_parse_11() { csv("'aa'\naa\n", new String[][] {
{"aa"}, {"aa"} }) ; }
+ @Test public void csv_parse_12() { csv("\naa", new String[][] { {""},
{"aa"} }) ; }
+ @Test public void csv_parse_13() { csv("a,b\nc,d", new String[][] { {"a",
"b"}, {"c", "d"} }) ; }
+ @Test public void csv_parse_14() { csv("a,b\rc,d", new String[][] { {"a",
"b"}, {"c", "d"} }) ; }
+
+
+ private void csv(String input, String[][] strings)
+ {
+ List<List<String>> x = new ArrayList<List<String>>() ;
+ for ( String[] a : strings )
+ {
+ List<String> y = new ArrayList<String>() ;
+ for ( String b : a )
+ y.add(b) ;
+ x.add(y) ;
+ }
+ csv(input, x) ;
+ }
+
+ private static void csv(String input, List<List<String>> answers)
+ {
+ List<List<String>> x = new ArrayList<List<String>>() ;
+ try {
+ InputStream in = new ByteArrayInputStream(input.getBytes("UTF-8"))
;
+ CSVTokenIterator iter = new CSVTokenIterator(in) ;
+ CSVParser parser = new CSVParser(iter) ;
+ List<String> row = null ;
+ while ( (row=parser.parse1())!=null) {
+ x.add(row) ;
+ }
+ assertEquals(answers, x) ;
+ } catch (UnsupportedEncodingException e)
+ {
+ throw new RuntimeException(e) ;
+ }
+
+
+ }
+}
+
Propchange:
jena/trunk/jena-arq/src/test/java/org/apache/jena/atlas/csv/TestCSVParser.java
------------------------------------------------------------------------------
svn:mime-type = text/plain