jena-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From a...@apache.org
Subject [39/50] [abbrv] Move jena-csv code to intended location
Date Wed, 08 Oct 2014 20:11:48 GMT
http://git-wip-us.apache.org/repos/asf/jena/blob/e7ac8b4d/jena-csv/src/main/java/org/apache/jena/propertytable/impl/PropertyTableBuilder.java
----------------------------------------------------------------------
diff --git a/jena-csv/src/main/java/org/apache/jena/propertytable/impl/PropertyTableBuilder.java b/jena-csv/src/main/java/org/apache/jena/propertytable/impl/PropertyTableBuilder.java
new file mode 100644
index 0000000..665c282
--- /dev/null
+++ b/jena-csv/src/main/java/org/apache/jena/propertytable/impl/PropertyTableBuilder.java
@@ -0,0 +1,134 @@
+/*
+ * 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.propertytable.impl;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.jena.atlas.csv.CSVParser;
+import org.apache.jena.atlas.csv.CSVTokenIterator;
+import org.apache.jena.atlas.io.IO;
+import org.apache.jena.propertytable.PropertyTable;
+import org.apache.jena.propertytable.Row;
+import org.apache.jena.propertytable.lang.LangCSV;
+import org.apache.jena.riot.system.IRIResolver;
+
+import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.graph.NodeFactory;
+
+
+/**
+ * A tool for constructing PropertyTable from a file (e.g., a CSV file).
+ * 
+ *
+ */
+public class PropertyTableBuilder {
+	
+	public static Node CSV_ROW_NODE = NodeFactory.createURI(LangCSV.CSV_ROW);
+	
+	public static PropertyTable buildPropetyTableHashMapImplFromCsv(String csvFilePath) {		
+		PropertyTable table = new PropertyTableHashMapImpl();
+		return fillPropertyTable(table, csvFilePath);
+	}
+	
+	public static PropertyTable buildPropetyTableArrayImplFromCsv(String csvFilePath) {
+		PropertyTable table = createEmptyPropertyTableArrayImpl(csvFilePath);
+		return fillPropertyTable(table, csvFilePath);
+	}
+	
+	private static PropertyTable createEmptyPropertyTableArrayImpl (String csvFilePath) {
+		CSVParser parser = CSVParser.create(csvFilePath);
+		List<String> rowLine = null;
+		int rowNum = 0;
+		int columnNum = 0;
+		
+		while ((rowLine = parser.parse1()) != null) {
+			if (rowNum == 0) {
+				columnNum = rowLine.size();
+			}
+			rowNum++;
+		}
+		if (rowNum!=0 && columnNum!=0){
+			return new PropertyTableArrayImpl(rowNum, columnNum+1);
+		} else {
+			return null;
+		}
+	}
+
+	protected static PropertyTable fillPropertyTable(PropertyTable table, String csvFilePath ){
+		InputStream input = IO.openFile(csvFilePath) ;
+		CSVTokenIterator iterator = new CSVTokenIterator(input) ;
+		return fillPropertyTable(table, iterator, csvFilePath);
+	}
+	
+	protected static PropertyTable fillPropertyTable(PropertyTable table, CSVTokenIterator iterator, String csvFilePath){
+		if (table == null){
+			return null;
+		}
+		CSVParser parser = new CSVParser (iterator);
+		List<String> rowLine = null;
+		ArrayList<Node> predicates = new ArrayList<Node>();
+		int rowNum = 0;
+
+		while ((rowLine = parser.parse1()) != null) {
+			if (rowNum == 0) {
+				table.createColumn(CSV_ROW_NODE);
+				for (String column : rowLine) {
+					String uri = createColumnKeyURI(csvFilePath, column);
+					Node p = NodeFactory.createURI(uri);
+					predicates.add(p);
+					table.createColumn(p);
+				}
+			} else {
+				Node subject = LangCSV.caculateSubject(rowNum, csvFilePath);
+				Row row = table.createRow(subject);
+				
+				row.setValue(table.getColumn(CSV_ROW_NODE), NodeFactory.createLiteral(
+						(rowNum + ""), XSDDatatype.XSDinteger));
+
+				for (int col = 0; col < rowLine.size() && col<predicates.size(); col++) {
+
+					String columnValue = rowLine.get(col).trim();
+					if("".equals(columnValue)){
+						continue;
+					}
+					Node o;
+					try {
+						// Try for a double.
+						double d = Double.parseDouble(columnValue);
+						o = NodeFactory.createLiteral(columnValue,
+								XSDDatatype.XSDdouble);
+					} catch (Exception e) {
+						o = NodeFactory.createLiteral(columnValue);
+					}
+					row.setValue(table.getColumn(predicates.get(col)), o);
+				}
+			}
+			rowNum++;
+		}
+		return table;
+	}
+	
+	protected static String createColumnKeyURI(String csvFilePath, String column){
+		String uri = IRIResolver.resolveString(csvFilePath) + "#" + LangCSV.toSafeLocalname(column);
+		return uri;
+	}
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/e7ac8b4d/jena-csv/src/main/java/org/apache/jena/propertytable/impl/PropertyTableHashMapImpl.java
----------------------------------------------------------------------
diff --git a/jena-csv/src/main/java/org/apache/jena/propertytable/impl/PropertyTableHashMapImpl.java b/jena-csv/src/main/java/org/apache/jena/propertytable/impl/PropertyTableHashMapImpl.java
new file mode 100644
index 0000000..b74925b
--- /dev/null
+++ b/jena-csv/src/main/java/org/apache/jena/propertytable/impl/PropertyTableHashMapImpl.java
@@ -0,0 +1,357 @@
+/*
+ * 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.propertytable.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.jena.atlas.iterator.Iter;
+import org.apache.jena.atlas.iterator.IteratorConcat;
+import org.apache.jena.propertytable.Column;
+import org.apache.jena.propertytable.PropertyTable;
+import org.apache.jena.propertytable.Row;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.SetMultimap;
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.graph.Triple;
+import com.hp.hpl.jena.util.iterator.ExtendedIterator;
+import com.hp.hpl.jena.util.iterator.WrappedIterator;
+
+/**
+ * A PropertyTable Implementation using HashMap.
+ * It contains PSO and POS indexes.
+ * 
+ */
+public class PropertyTableHashMapImpl implements PropertyTable {
+
+	private Map<Node, Column> columnIndex; // Maps property Node key to Column
+	private List<Column> columnList; // Stores the list of columns in the table
+	private Map<Node, Row> rowIndex; // Maps the subject Node key to Row.
+	private List<Row> rowList; // Stores the list of rows in the table
+
+	// PSO index
+	private Map<Node, Map<Node, Node>> valueIndex; // Maps column Node to
+													// (subject Node, value)
+													// pairs
+	// POS index
+	private Map<Node, SetMultimap<Node, Node>> valueReverseIndex; // Maps column
+																	// Node to
+																	// (value,
+																	// subject
+																	// Node)
+																	// pairs
+
+	PropertyTableHashMapImpl() {
+		columnIndex = new HashMap<Node, Column>();
+		columnList = new ArrayList<Column>();
+		rowIndex = new HashMap<Node, Row>();
+		rowList = new ArrayList<Row>();
+		valueIndex = new HashMap<Node, Map<Node, Node>>();
+		valueReverseIndex = new HashMap<Node, SetMultimap<Node, Node>>();
+	}
+
+	@Override
+	public ExtendedIterator<Triple> getTripleIterator() {
+		
+		// use PSO index to scan all the table (slow)
+		IteratorConcat<Triple> iter = new IteratorConcat<Triple>();
+		for (Column column : getColumns()) {
+			iter.add(getTripleIterator(column));
+		}
+		return WrappedIterator.create(Iter.distinct(iter));
+	}
+
+	@Override
+	public ExtendedIterator<Triple> getTripleIterator(Column column) {
+		
+		// use PSO index directly (fast)
+		
+		if (column == null || column.getColumnKey() == null)
+			throw new NullPointerException("column is null");
+		
+		ArrayList<Triple> triples = new ArrayList<Triple>();
+		Map<Node, Node> values = valueIndex.get(column.getColumnKey());
+
+		for (Entry<Node, Node> entry : values.entrySet()) {
+			Node subject = entry.getKey();
+			Node value = entry.getValue();
+			triples.add(Triple.create(subject, column.getColumnKey(), value));
+		}
+		return WrappedIterator.create(triples.iterator());
+	}
+
+	@Override
+	public ExtendedIterator<Triple> getTripleIterator(Node value) {
+		
+		// use POS index ( O(n), n= column count )
+		
+		if (value == null)
+			throw new NullPointerException("value is null");
+		
+		IteratorConcat<Triple> iter = new IteratorConcat<Triple>();
+		for (Column column : this.getColumns()) {
+			ExtendedIterator<Triple> eIter = getTripleIterator(column,value);
+			iter.add(eIter);
+		}
+		return WrappedIterator.create(Iter.distinct(iter));
+	}
+
+	@Override
+	public ExtendedIterator<Triple> getTripleIterator(Column column, Node value) {
+		
+		// use POS index directly (fast)
+		
+		if (column == null || column.getColumnKey() == null)
+			throw new NullPointerException("column is null");
+		
+		if (value == null)
+			throw new NullPointerException("value is null");
+		
+		
+		Node p = column.getColumnKey();
+		final SetMultimap<Node, Node> valueToSubjectMap = valueReverseIndex
+				.get(p);
+		final Set<Node> subjects = valueToSubjectMap.get(value);
+		ArrayList<Triple> triples = new ArrayList<Triple>();
+		for (Node subject : subjects) {
+			triples.add(Triple.create(subject, p, value));
+		}
+		return WrappedIterator.create(triples.iterator());
+	}
+
+
+	@Override
+	public ExtendedIterator<Triple> getTripleIterator(Row row) {
+		// use PSO index ( O(n), n= column count )
+		
+		if (row == null || row.getRowKey() == null)
+			throw new NullPointerException("row is null");
+		
+		ArrayList<Triple> triples = new ArrayList<Triple>();
+		for (Column column : getColumns()) {
+			Node value = row.getValue(column);
+			triples.add(Triple.create(row.getRowKey(), column.getColumnKey(), value));
+		}
+		return WrappedIterator.create(triples.iterator());
+	}
+
+	@Override
+	public Collection<Column> getColumns() {
+		return columnList;
+	}
+
+	@Override
+	public Column getColumn(Node p) {
+		if (p == null)
+			throw new NullPointerException("column node is null");
+		return columnIndex.get(p);
+	}
+
+	@Override
+	public Column createColumn(Node p) {
+		if (p == null)
+			throw new NullPointerException("column node is null");
+
+		if (columnIndex.containsKey(p))
+			throw new IllegalArgumentException("column already exists: '"
+					+ p.toString());
+
+		columnIndex.put(p, new ColumnImpl(this, p));
+		columnList.add(columnIndex.get(p));
+		valueIndex.put(p, new HashMap<Node, Node>());
+		valueReverseIndex.put(p, HashMultimap.<Node, Node> create());
+		return getColumn(p);
+	}
+
+	@Override
+	public Row getRow(final Node s) {
+		if (s == null)
+			throw new NullPointerException("subject node is null");
+		Row row = rowIndex.get(s);
+		return row;
+
+	}
+	
+	@Override
+	public Row createRow(final Node s){
+		Row row = this.getRow(s);
+		if (row != null)
+			return row;
+
+		row = new InternalRow(s);
+		rowIndex.put(s, row);
+		rowList.add(row);
+
+		return row;
+	}
+	
+	@Override
+	public List<Row> getAllRows() {
+		return rowList;
+	}
+
+	
+	
+	@Override
+	public List<Node> getColumnValues(Column column) {
+		if (column == null || column.getColumnKey() == null)
+			throw new NullPointerException("column is null");
+		
+		Map<Node, Node> values = valueIndex.get(column.getColumnKey());
+
+		List<Node> list = new ArrayList<Node>(values.size());
+		list.addAll(values.values());
+		return list;
+	}
+	
+	@Override
+	public Collection<Row> getMatchingRows(Column column, Node value) {
+		if (column == null || column.getColumnKey() == null)
+			throw new NullPointerException("column is null");
+		
+		if (value == null)
+			throw new NullPointerException("value is null");
+		
+		
+		Node p = column.getColumnKey();
+		final SetMultimap<Node, Node> valueToSubjectMap = valueReverseIndex
+				.get(p);
+		final Set<Node> subjects = valueToSubjectMap.get(value);
+		
+		final ArrayList<Row> matchingRows = new ArrayList<Row>();
+		for (Node subject : subjects) {
+			matchingRows.add(this.getRow(subject));
+		}
+		return matchingRows;
+	}
+
+	private final void setX(final Node s, final Node p, final Node value) {
+		if (p == null)
+			throw new NullPointerException("column Node must not be null.");
+		if (value == null)
+			throw new NullPointerException("value must not be null.");
+
+		Map<Node, Node> subjectToValueMap = valueIndex.get(p);
+		if (!columnIndex.containsKey(p) || subjectToValueMap == null)
+			throw new IllegalArgumentException("column: '" + p
+					+ "' does not yet exist.");
+
+		Node oldValue = subjectToValueMap.get(s);
+		subjectToValueMap.put(s, value);
+		addToReverseMap(p, s, oldValue, value);
+	}
+
+	private void addToReverseMap(final Node p, final Node s,
+			final Node oldValue, final Node value) {
+
+		final SetMultimap<Node, Node> valueToSubjectMap = valueReverseIndex
+				.get(p);
+		valueToSubjectMap.remove(oldValue, s);
+		valueToSubjectMap.put(value, s);
+	}
+
+	private void unSetX(final Node s, final Node p) {
+
+		final Map<Node, Node> subjectToValueMap = valueIndex.get(p);
+		if (!columnIndex.containsKey(p) || subjectToValueMap == null)
+			throw new IllegalArgumentException("column: '" + p
+					+ "' does not yet exist.");
+
+		final Node value = subjectToValueMap.get(s);
+		if (value == null)
+			return;
+
+		subjectToValueMap.remove(s);
+		removeFromReverseMap(p, s, value);
+	}
+
+	private void removeFromReverseMap(final Node p, final Node s,
+			final Node value) {
+		final SetMultimap<Node, Node> valueTokeysMap = valueReverseIndex.get(p);
+		valueTokeysMap.remove(s, value);
+	}
+
+	private Node getX(final Node s, final Node p) {
+		final Map<Node, Node> subjectToValueMap = valueIndex.get(p);
+		if (!columnIndex.containsKey(p) || subjectToValueMap == null)
+			throw new IllegalArgumentException("column: '" + p
+					+ "' does not yet exist.");
+		return subjectToValueMap.get(s);
+	}
+
+	private final class InternalRow implements Row {
+		private final Node key;
+
+		InternalRow(final Node key) {
+			this.key = key;
+		}
+
+		@Override
+		public void setValue(Column column, Node value) {
+			if (value == null)
+				unSetX(key, column.getColumnKey());
+			else
+				setX(key, column.getColumnKey(), value);
+		}
+
+		@Override
+		public Node getValue(Column column) {
+			return getX(key, column.getColumnKey());
+		}
+		
+		@Override
+		public Node getValue(Node columnKey) {
+			return getX(key, columnKey);
+		}
+
+		@Override
+		public PropertyTable getTable() {
+			return PropertyTableHashMapImpl.this;
+		}
+
+		@Override
+		public Node getRowKey() {
+			return key;
+		}
+
+		@Override
+		public Collection<Column> getColumns() {
+			// TODO Auto-generated method stub
+			return PropertyTableHashMapImpl.this.getColumns();
+		}
+
+		@Override
+		public ExtendedIterator<Triple> getTripleIterator() {
+			ArrayList<Triple> triples = new ArrayList<Triple>();
+			for (Column column : getColumns()) {
+				Node value = this.getValue(column);
+				triples.add(Triple.create(key, column.getColumnKey(), value));
+			}
+			return WrappedIterator.create(triples.iterator());
+		}
+
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/e7ac8b4d/jena-csv/src/main/java/org/apache/jena/propertytable/lang/LangCSV.java
----------------------------------------------------------------------
diff --git a/jena-csv/src/main/java/org/apache/jena/propertytable/lang/LangCSV.java b/jena-csv/src/main/java/org/apache/jena/propertytable/lang/LangCSV.java
new file mode 100644
index 0000000..ccda47e
--- /dev/null
+++ b/jena-csv/src/main/java/org/apache/jena/propertytable/lang/LangCSV.java
@@ -0,0 +1,229 @@
+/**
+ * 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.propertytable.lang;
+
+import static org.apache.jena.riot.RDFLanguages.CSV;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.jena.atlas.csv.CSVParser;
+import org.apache.jena.atlas.web.ContentType;
+import org.apache.jena.propertytable.util.IRILib;
+import org.apache.jena.riot.Lang;
+import org.apache.jena.riot.RDFLanguages;
+import org.apache.jena.riot.RDFParserRegistry;
+import org.apache.jena.riot.ReaderRIOT;
+import org.apache.jena.riot.ReaderRIOTFactory;
+import org.apache.jena.riot.lang.LangRIOT;
+import org.apache.jena.riot.system.ErrorHandler;
+import org.apache.jena.riot.system.ErrorHandlerFactory;
+import org.apache.jena.riot.system.IRIResolver;
+import org.apache.jena.riot.system.ParserProfile;
+import org.apache.jena.riot.system.RiotLib;
+import org.apache.jena.riot.system.StreamRDF;
+
+import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.graph.NodeFactory;
+import com.hp.hpl.jena.sparql.util.Context;
+
+/**
+ * The LangRIOT implementation for CSV
+ *
+ */
+public class LangCSV implements LangRIOT {
+
+	public static final String CSV_PREFIX = "http://w3c/future-csv-vocab/";
+	public static final String CSV_ROW = CSV_PREFIX + "row";
+
+	private InputStream input = null;
+	private Reader reader = null;
+	private String base;
+	private String filename;
+	private StreamRDF sink;
+	private ParserProfile profile; // Warning - we don't use all of this.
+	
+	public static void register(){
+		RDFParserRegistry.removeRegistration(Lang.CSV);
+		RDFParserRegistry.registerLangTriples(Lang.CSV, new ReaderRIOTFactoryCSV());
+	}
+
+	@Override
+	public Lang getLang() {
+		return RDFLanguages.CSV;
+	}
+
+	@Override
+	public ParserProfile getProfile() {
+		return profile;
+	}
+
+	@Override
+	public void setProfile(ParserProfile profile) {
+		this.profile = profile;
+	}
+
+	public LangCSV(Reader reader, String base, String filename,
+			ErrorHandler errorHandler, StreamRDF sink) {
+		this.reader = reader;
+		this.base = base;
+		this.filename = filename;
+		this.sink = sink;
+		this.profile = RiotLib.profile(getLang(), base, errorHandler);
+	}
+
+	public LangCSV(InputStream in, String base, String filename,
+			ErrorHandler errorHandler, StreamRDF sink) {
+		this.input = in;
+		this.base = base;
+		this.filename = filename;
+		this.sink = sink;
+		this.profile = RiotLib.profile(getLang(), base, errorHandler);
+	}
+
+	@Override
+	public void parse() {
+		sink.start();
+		CSVParser parser = (input != null) ? CSVParser.create(input)
+				: CSVParser.create(reader);
+		List<String> row = null;
+		ArrayList<Node> predicates = new ArrayList<Node>();
+		int rowNum = 0;
+		while ((row = parser.parse1()) != null) {
+			
+			if (rowNum == 0) {
+				for (String column : row) {
+					String uri = IRIResolver.resolveString(filename) + "#"
+							+ toSafeLocalname(column);
+					Node predicate = this.profile.createURI(uri, rowNum, 0);
+					predicates.add(predicate);
+				}
+			} else {
+				//Node subject = this.profile.createBlankNode(null, -1, -1);
+				Node subject = caculateSubject(rowNum, filename);
+				Node predicateRow = this.profile.createURI(CSV_ROW, -1, -1);
+				Node objectRow = this.profile
+						.createTypedLiteral((rowNum + ""),
+								XSDDatatype.XSDinteger, rowNum, 0);
+				sink.triple(this.profile.createTriple(subject, predicateRow,
+						objectRow, rowNum, 0));
+				for (int col = 0; col < row.size() && col<predicates.size(); col++) {
+					Node predicate = predicates.get(col);
+					String columnValue = row.get(col).trim();
+					if("".equals(columnValue)){
+						continue;
+					}					
+					Node o;
+					try {
+						// Try for a double.
+						double d = Double.parseDouble(columnValue);
+						o = NodeFactory.createLiteral(columnValue,
+								XSDDatatype.XSDdouble);
+					} catch (Exception e) {
+						o = NodeFactory.createLiteral(columnValue);
+					}
+					sink.triple(this.profile.createTriple(subject, predicate,
+							o, rowNum, col));
+				}
+
+			}
+			rowNum++;
+		}
+		sink.finish();
+
+	}
+
+	public static String toSafeLocalname(String raw) {
+		String ret = raw.trim();
+		return encodeURIComponent(ret);
+		
+	}
+	
+	public static String encodeURIComponent(String s) {
+	    return IRILib.encodeUriComponent(s);
+	}
+	
+	public static Node caculateSubject(int rowNum, String filename){
+		Node subject = NodeFactory.createAnon();
+//		String uri = IRIResolver.resolveString(filename) + "#Row_" + rowNum; 
+//		Node subject =  NodeFactory.createURI(uri);
+		return subject;
+	}
+	
+	
+	
+	
+    private static class ReaderRIOTFactoryCSV implements ReaderRIOTFactory
+    {
+        @Override
+        public ReaderRIOT create(Lang lang) {
+            return new ReaderRIOTLangCSV(lang) ;
+        }
+    }
+
+    private static class ReaderRIOTLangCSV implements ReaderRIOT
+    {
+        private final Lang lang ;
+        private ErrorHandler errorHandler ; 
+        private ParserProfile parserProfile = null ;
+
+        ReaderRIOTLangCSV(Lang lang) {
+            this.lang = lang ;
+            errorHandler = ErrorHandlerFactory.getDefaultErrorHandler() ;
+        }
+
+        @Override
+        public void read(InputStream in, String baseURI, ContentType ct, StreamRDF output, Context context) {
+            if ( lang == CSV){
+            	LangRIOT parser = new LangCSV (in, baseURI, baseURI, ErrorHandlerFactory.getDefaultErrorHandler(),  output);
+                if ( parserProfile != null )
+                    parser.setProfile(parserProfile);
+                if ( errorHandler != null )
+                    parser.getProfile().setHandler(errorHandler) ;
+                parser.parse() ;
+            } else {
+            	throw new IllegalArgumentException("The Lang must be 'CSV'!");
+            }
+
+        }
+
+        @Override
+        public void read(Reader in, String baseURI, ContentType ct, StreamRDF output, Context context) {
+        	if ( lang == CSV){
+        		LangRIOT parser = new LangCSV (in, baseURI, baseURI, ErrorHandlerFactory.getDefaultErrorHandler(),  output);
+                if ( parserProfile != null )
+                    parser.setProfile(parserProfile);
+                if ( errorHandler != null )
+                    parser.getProfile().setHandler(errorHandler) ;
+        		parser.parse() ;
+        	} else {
+            	throw new IllegalArgumentException("The Lang must be 'CSV'!");
+            }
+        }
+
+        @Override public ErrorHandler getErrorHandler()                     { return errorHandler ; }
+        @Override public void setErrorHandler(ErrorHandler errorHandler)    { this.errorHandler = errorHandler ; }
+
+        @Override public ParserProfile getParserProfile()                   { return parserProfile ; } 
+        @Override public void setParserProfile(ParserProfile parserProfile) { this.parserProfile = parserProfile ; }
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/e7ac8b4d/jena-csv/src/main/java/org/apache/jena/propertytable/util/IRILib.java
----------------------------------------------------------------------
diff --git a/jena-csv/src/main/java/org/apache/jena/propertytable/util/IRILib.java b/jena-csv/src/main/java/org/apache/jena/propertytable/util/IRILib.java
new file mode 100644
index 0000000..b535c88
--- /dev/null
+++ b/jena-csv/src/main/java/org/apache/jena/propertytable/util/IRILib.java
@@ -0,0 +1,264 @@
+/*
+ * 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.propertytable.util;
+
+import java.io.File ;
+import java.io.IOException ;
+
+import org.apache.jena.atlas.AtlasException ;
+import org.apache.jena.atlas.lib.Chars ;
+import org.apache.jena.atlas.lib.StrUtils ;
+import org.apache.jena.riot.SysRIOT ;
+
+/** 
+ * Operations related to IRIs.
+ * Add support for '£', based on {@link org.apache.jena.riot.system.IRILib}
+ * 
+ * This class should be merged into riot IRILib in future.
+ */
+public class IRILib
+{
+    // http://www.w3.org/TR/xpath-functions/#func-encode-for-uri
+    // Encodes delimiters.
+    
+    /* RFC 3986
+     * 
+     * unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
+     * gen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+     * sub-delims  = "!" / "$" / "&" / "'" / "(" / ")"
+                    / "*" / "+" / "," / ";" / "="
+     */
+    
+    private static char uri_reserved[] = 
+    { 
+      '!', '*', '"', '\'', '(', ')', ';', ':', '@', '&', 
+      '=', '+', '$', ',', '/', '?', '%', '#', '[', ']'} ;
+
+    // No allowed in URIs
+    private static char uri_non_chars[] = { '<', '>', '{', '}', '|', '\\', '`', '^', ' ',  '\n', '\r', '\t', '£' } ;
+    
+    // RFC 2396
+    //private static char uri_unwise[]    = { '{' , '}', '|', '\\', '^', '[', ']', '`' } ;
+
+
+    private static char[] charsComponent =
+    // reserved, + non-chars + nasties.
+    { '!', '*', '"', '\'', '(', ')', ';', ':', '@', '&', 
+      '=', '+', '$', ',', '/', '?', '%', '#', '[', ']',
+      '{', '}', '|', '\\', '`', '^',
+      ' ', '<', '>', '\n', '\r', '\t', '£' } ;
+    
+    private static char[] charsFilename =
+        // reserved, + non-chars + nasties.
+        // Leave : (Windows drive charcater) and / (separator) alone
+        // include SPC and ~
+        { '!', '*', '"', '\'', '(', ')', ';', /*':',*/ '@', '&', 
+          '=', '+', '$', ',', /*'/',*/ '?', '%', '#', '[', ']',
+          '{', '}', '|', '\\', '`', '^',
+          ' ', '<', '>', '\n', '\r', '\t',
+          '~'} ;
+
+    private static char[] charsPath =  
+    {
+        // Reserved except leave the separators alone. 
+        // Leave the path separator alone.
+        // Leave the drive separator alone.
+        '!', '*', '"', '\'', '(', ')', ';', /*':',*/ '@', '&',
+        '=', '+', '$', ',', /*'/',*/ '?', '%', '#', '[', ']',
+        '{', '}', '|', '\\', '`', '^',
+        // Other junk 
+        ' ', '<', '>', '\n', '\r', '\t' } ;
+
+    // The initializers must have run.
+    static final String cwd ; 
+    static final String cwdURL ;
+    
+    // Current directory, with trailing "/"
+    // This matters for resolution.
+    static { 
+        String x = new File(".").getAbsolutePath() ;
+        x = x.substring(0, x.length()-1) ;
+        cwd = x ;
+        cwdURL = plainFilenameToURL(cwd) ;
+    }
+    
+    // See also IRIResolver
+    /** Return a string that is an IRI for the filename.*/
+    public static String fileToIRI(File f)
+    {
+        return filenameToIRI(f.getAbsolutePath()) ;
+    }
+    
+    /** Create a string that is a IRI for the filename.
+     *  The file name may already have file:.
+     *  The file name may be relative. 
+     *  Encode using the rules for a path (e.g. ':' and'/' do not get encoded)
+     */
+    public static String filenameToIRI(String fn)
+    {
+        if ( fn == null ) return cwdURL ;
+        
+        if ( fn.length() == 0 ) return cwdURL ;
+        
+        if ( fn.startsWith("file:") )
+            return normalizeFilenameURI(fn) ;
+        return plainFilenameToURL(fn) ;
+    }
+    
+    /** Convert an IRI to a filename */
+    public static String IRIToFilename(String iri)
+    {
+        if ( ! iri.startsWith("file:") )
+            throw new AtlasException("Not a file: URI: "+iri) ; 
+        
+        String fn ;
+        if ( iri.startsWith("file:///") )
+            fn = iri.substring("file://".length()) ;
+        else
+            fn = iri.substring("file:".length()) ;
+        return decode(fn) ;
+    }
+    
+    /** Convert a plain file name (no file:) to a file: URL */
+    private static String plainFilenameToURL(String fn)
+    {
+        // No "file:"
+        // Make Absolute filename.
+        boolean trailingSlash = fn.endsWith("/") ;
+        File file = new File(fn) ;
+        
+        try { fn = file.getCanonicalPath() ; }
+        catch (IOException e) { fn = file.getAbsolutePath() ; }
+        
+        if ( trailingSlash && ! fn.endsWith("/") )
+            fn = fn + "/" ;
+        
+        if ( SysRIOT.isWindows )
+        {
+            // C:\ => file:///C:/... 
+            if ( fn.length() >= 2 && fn.charAt(1) == ':' )
+                // Windows drive letter - already absolute path.
+                // Make "URI" absolute path
+                fn = "/"+fn ;
+            // Convert \ to /
+            // Maybe should do this on all platforms? i.e consistency.
+            fn = fn.replace('\\', '/' ) ;
+        }
+        
+        fn = encodeFileURL(fn) ;
+        return "file://"+fn ;
+    }
+    
+    
+    /** Sanitize a "file:" URL. Must start "file:" */
+    private static String normalizeFilenameURI(String fn)
+    {
+        if ( ! fn.startsWith("file:/") )
+        {
+            // Relative path.
+            String fn2 = fn.substring("file:".length()) ;
+            return plainFilenameToURL(fn2) ;
+        }
+        
+        // Starts file:///
+        if ( fn.startsWith("file:///") )
+            // Assume it's good as return as-is.
+            return fn ;
+
+        if ( fn.startsWith("file://") )
+        {
+            String fn2 = fn.substring("file:/".length()) ;  // Leave one "/"
+            return plainFilenameToURL(fn2) ;
+        }
+
+        // Must be file:/
+        String fn2 = fn.substring("file:".length()) ;
+        return plainFilenameToURL(fn2) ;
+    }
+
+    /** Encode using the rules for a component (e.g. ':' and '/' get encoded) 
+     * Does not encode non-ASCII characters 
+     */
+    public static String encodeUriComponent(String string)
+    {
+        String encStr = StrUtils.encodeHex(string,'%', charsComponent) ;
+        return encStr ;
+    }
+
+    /** Encode using the rules for a file: URL.  
+     *  Does not encode non-ASCII characters
+     */
+    public static String encodeFileURL(String string)
+    {
+        String encStr = StrUtils.encodeHex(string,'%', charsFilename) ;
+        return encStr ;
+    }
+
+    /** Encode using the rules for a path (e.g. ':' and '/' do not get encoded) */
+    public static String encodeUriPath(String uri)
+    {
+        // Not perfect.
+        // Encode path.
+        // %-encode chars.
+        uri = StrUtils.encodeHex(uri, '%', charsPath) ;
+        return uri ;
+    }
+
+    public static String decode(String string)
+    {
+        return StrUtils.decodeHex(string, '%') ;
+    }
+
+    public static String encodeNonASCII(String string)
+    {
+        if ( ! containsNonASCII(string) )
+            return string ;
+        
+        byte[] bytes = StrUtils.asUTF8bytes(string) ;
+        StringBuilder sw = new StringBuilder() ;
+        for ( byte b : bytes )
+        {
+            // Signed bytes ...
+            if ( b > 0 )
+            {
+                sw.append( (char) b );
+                continue;
+            }
+
+            int hi = ( b & 0xF0 ) >> 4;
+            int lo = b & 0xF;
+            sw.append( '%' );
+            sw.append( Chars.hexDigitsUC[hi] );
+            sw.append( Chars.hexDigitsUC[lo] );
+        }
+        return sw.toString() ;
+    }
+
+    public static boolean containsNonASCII(String string)
+    {
+        boolean clean = true ;
+        for ( int i = 0 ; i < string.length() ; i++ )
+        {
+            char ch = string.charAt(i) ;
+            if ( ch >= 127 )
+                return true;
+        }
+        return false ;
+    } 
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/e7ac8b4d/jena-csv/src/main/java/riotcmd/LocatorOupputFile.java
----------------------------------------------------------------------
diff --git a/jena-csv/src/main/java/riotcmd/LocatorOupputFile.java b/jena-csv/src/main/java/riotcmd/LocatorOupputFile.java
new file mode 100644
index 0000000..14caeeb
--- /dev/null
+++ b/jena-csv/src/main/java/riotcmd/LocatorOupputFile.java
@@ -0,0 +1,148 @@
+/*
+ * 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 riotcmd;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.AccessControlException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.hp.hpl.jena.util.FileManager;
+import com.hp.hpl.jena.util.FileUtils;
+import com.hp.hpl.jena.util.LocatorFile;
+
+class LocatorOupputFile {
+    static Logger log = LoggerFactory.getLogger(LocatorOupputFile.class) ;
+    private String thisDir = null ;
+    private String thisDirLogStr = "" ;
+    
+    public LocatorOupputFile(String dir)
+    {
+        if ( dir != null )
+        {
+            if ( dir.endsWith("/") || dir.endsWith(java.io.File.separator) )
+                dir = dir.substring(0,dir.length()-1) ;
+            thisDirLogStr = " ["+dir+"]" ;
+        }
+        thisDir = dir ;
+    }
+
+    LocatorOupputFile()
+    {
+        this(null) ;
+    }
+    
+    @Override
+    public boolean equals( Object other )
+    {
+        return
+            other instanceof LocatorFile
+            && equals( thisDir, ((LocatorOupputFile) other).thisDir );
+    }
+    
+    private boolean equals( String a, String b )
+    {
+        return a == null ? b == null : a.equals(  b  );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        if ( thisDir == null )
+            return 157 ;
+        return thisDir.hashCode();
+    }
+    
+    private File toFile(String filenameOrURI)
+    {
+        String fn = FileUtils.toFilename(filenameOrURI) ;
+        if ( fn == null )
+            return null ;
+        
+        if ( thisDir != null && ! fn.startsWith("/") && ! fn.startsWith(FileManager.filePathSeparator) )
+            fn = thisDir+java.io.File.separator+fn ;
+                     
+        return new File(fn) ;
+    }
+    
+    
+    public boolean exists(String filenameOrURI)
+    {
+        File f = toFile(filenameOrURI) ;
+        
+        if ( f == null )
+            return false ;
+        
+        return f.exists() ;
+    }
+    
+
+    public OutputStream open(String filenameOrURI)
+    {
+        // Worry about %20.
+        // toFile calls FileUtils.toFilename(filenameOrURI) ;
+        File f = toFile(filenameOrURI) ;
+
+        try {
+            if ( f == null )
+            {
+                if ( log.isTraceEnabled())
+                    log.trace("Not found: "+filenameOrURI+thisDirLogStr) ;
+                return null ;
+            }
+        } catch (AccessControlException e) {
+            log.warn("Security problem testing for file", e);
+            return null;
+        }
+        
+        try {
+            OutputStream out = new FileOutputStream(f) ;
+
+            if ( log.isTraceEnabled() )
+                log.trace("Found: "+filenameOrURI+thisDirLogStr) ;
+                
+            
+            // Create base -- Java 1.4-isms
+            //base = f.toURI().toURL().toExternalForm() ;
+            //base = base.replaceFirst("^file:/([^/])", "file:///$1") ;
+            return out ;
+        } catch (IOException ioEx)
+        {
+            // Includes FileNotFoundException
+            // We already tested whether the file exists or not.
+            // log.warn("File unreadable (but exists): "+f.getPath()+" Exception: "+ioEx.getMessage()) ;
+            return null ;
+        }
+    }
+    
+    public String getDir()  { return thisDir ; }
+    
+
+    public String getName()
+    {
+        String tmp = "LocatorFile" ;
+        if ( thisDir != null )
+            tmp = tmp+"("+thisDir+")" ;
+        return tmp ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/e7ac8b4d/jena-csv/src/main/java/riotcmd/ModDest.java
----------------------------------------------------------------------
diff --git a/jena-csv/src/main/java/riotcmd/ModDest.java b/jena-csv/src/main/java/riotcmd/ModDest.java
new file mode 100644
index 0000000..e5560f0
--- /dev/null
+++ b/jena-csv/src/main/java/riotcmd/ModDest.java
@@ -0,0 +1,51 @@
+/*
+ * 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 riotcmd;
+
+import arq.cmd.CmdException;
+import arq.cmdline.ArgDecl;
+import arq.cmdline.ArgModuleGeneral;
+import arq.cmdline.CmdArgModule;
+import arq.cmdline.CmdGeneral;
+
+class ModDest implements ArgModuleGeneral{
+	
+	private ArgDecl argDest     = new ArgDecl(ArgDecl.HasValue, "dest") ;
+	private String dest         = null ;
+
+	@Override
+	public void processArgs(CmdArgModule cmdLine) {
+		if ( cmdLine.contains(argDest) ) {
+			dest = cmdLine.getValue(argDest) ;
+        } else {
+        	throw new CmdException("No destination output file! Please add '--dest=file' in the program arguements") ;
+        }
+	}
+
+	@Override
+	public void registerWith(CmdGeneral cmdLine) {
+		cmdLine.getUsage().startCategory("Destination Output") ;
+		cmdLine.add(argDest,    "--dest=file",      "The destination output file") ;	
+	}
+	
+    public String getDest() {
+        return dest ;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/e7ac8b4d/jena-csv/src/main/java/riotcmd/csv2rdf.java
----------------------------------------------------------------------
diff --git a/jena-csv/src/main/java/riotcmd/csv2rdf.java b/jena-csv/src/main/java/riotcmd/csv2rdf.java
new file mode 100644
index 0000000..882a29a
--- /dev/null
+++ b/jena-csv/src/main/java/riotcmd/csv2rdf.java
@@ -0,0 +1,205 @@
+/*
+ * 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 riotcmd;
+
+import java.io.OutputStream;
+
+import org.apache.jena.atlas.io.IO;
+import org.apache.jena.atlas.web.ContentType;
+import org.apache.jena.atlas.web.TypedInputStream;
+import org.apache.jena.riot.Lang;
+import org.apache.jena.riot.RDFDataMgr;
+import org.apache.jena.riot.RDFLanguages;
+import org.apache.jena.riot.ReaderRIOT;
+import org.apache.jena.riot.RiotException;
+import org.apache.jena.riot.SysRIOT;
+import org.apache.jena.riot.lang.LabelToNode;
+import org.apache.jena.riot.lang.StreamRDFCounting;
+import org.apache.jena.riot.out.NodeToLabel;
+import org.apache.jena.riot.process.inf.InfFactory;
+import org.apache.jena.riot.system.ErrorHandler;
+import org.apache.jena.riot.system.ErrorHandlerFactory;
+import org.apache.jena.riot.system.RiotLib;
+import org.apache.jena.riot.system.StreamRDF;
+import org.apache.jena.riot.system.StreamRDF2;
+import org.apache.jena.riot.system.StreamRDFLib;
+import org.apache.jena.riot.system.SyntaxLabels;
+
+import arq.cmd.CmdException;
+
+import com.hp.hpl.jena.sparql.util.Utils;
+
+/**
+ * It's a command line tool for direct and scalable transforming from CSV to the formatted RDF syntax (i.e. N-Triples), 
+ * with no intermediary Graph or PropertyTable.
+ * 
+ * It reuses the parsing functions from CmdLangParse and sinks the triples into the destination output file.
+ *
+ */
+public class csv2rdf extends CmdLangParse{
+	
+	protected ModDest modDest = new ModDest() ;
+	protected OutputStream destOut;
+
+    public static void main(String... argv)
+    {
+        new csv2rdf(argv).mainRun() ;
+    }    
+    
+    protected csv2rdf(String[] argv)
+    {
+        super(argv) ;
+        super.addModule(modDest) ;
+        
+    }
+	
+	@Override
+	protected Lang selectLang(String filename, ContentType contentType,
+			Lang dftLang) {
+		return RDFLanguages.CSV; 
+	}
+
+	@Override
+	protected String getCommandName() {
+		return Utils.classShortName(csv2rdf.class) ;
+	}
+	
+    @Override
+    protected String getSummary()
+    {
+        return getCommandName()+" --dest=outputFile inputFile ..." ;
+    }
+
+	// override the original CmdLangParse.parseRIOT()
+    protected void parseRIOT(String baseURI, String filename, TypedInputStream in)
+    {
+    	
+    	String dest = modDest.getDest();
+    	LocatorOupputFile l = new LocatorOupputFile();
+    	destOut = l.open(dest);
+    	
+    	if (destOut == null){
+            System.err.println("Can't write to destination output file: '"+dest+"' ") ;
+            return ;
+    	}
+    	
+        // I ti s shame we effectively duplicate deciding thelnaguage but we want to control the
+        // pasrer at a deep level (in validation, we want line numbers get into error message)
+        // This code predates RDFDataMgr.
+        
+        ContentType ct = in.getMediaType() ;
+        
+        baseURI = SysRIOT.chooseBaseIRI(baseURI, filename) ;
+        
+        boolean checking = true ;
+        if ( modLangParse.explicitChecking() )  checking = true ;
+        if ( modLangParse.explicitNoChecking() ) checking = false ;
+        
+        ErrorHandler errHandler = null ;
+        if ( checking )
+        {
+            if ( modLangParse.stopOnBadTerm() )
+                errHandler = ErrorHandlerFactory.errorHandlerStd  ;
+            else
+                // Try to go on if possible.  This is the default behaviour.
+                errHandler = ErrorHandlerFactory.errorHandlerWarn ;
+        }
+        
+        if ( modLangParse.skipOnBadTerm() )
+        {
+            // TODO skipOnBadterm
+        }
+        
+        Lang lang = selectLang(filename, ct, RDFLanguages.NQUADS) ;  
+        LangHandler handler = dispatch.get(lang) ;
+        if ( handler == null )
+            throw new CmdException("Undefined language: "+lang) ; 
+        
+        // If multiple files, choose the overall labels. 
+        if ( langHandlerOverall == null )
+            langHandlerOverall = handler ;
+        else
+        {
+            if ( langHandlerOverall != langHandlerAny )
+            {
+                if ( langHandlerOverall != handler )
+                    langHandlerOverall = langHandlerAny ;
+            }
+        }
+        
+        // Make a flag.
+        // Input and output subflags.
+        // If input is "label, then output using NodeToLabel.createBNodeByLabelRaw() ;
+        // else use NodeToLabel.createBNodeByLabel() ;
+        // Also, as URI.
+        final boolean labelsAsGiven = false ;
+        
+        NodeToLabel labels = SyntaxLabels.createNodeToLabel() ;
+        if ( labelsAsGiven )
+            labels = NodeToLabel.createBNodeByLabelEncoded() ;
+        
+        StreamRDF s = StreamRDFLib.sinkNull() ;
+        if ( ! modLangParse.toBitBucket() )
+            s = StreamRDFLib.writer(output) ;
+        
+        // add dest output
+        if ( destOut != null)
+        	s = new StreamRDF2(s,  StreamRDFLib.writer(destOut));
+        
+        if ( setup != null )
+            s = InfFactory.inf(s, setup) ;
+        
+        StreamRDFCounting sink = StreamRDFLib.count(s) ;
+        s = null ;
+        
+        ReaderRIOT reader = RDFDataMgr.createReader(lang) ;
+        try {
+            if ( checking ) {
+                if ( lang == RDFLanguages.NTRIPLES || lang == RDFLanguages.NQUADS )
+                    reader.setParserProfile(RiotLib.profile(baseURI, false, true, errHandler)) ;
+                else
+                    reader.setParserProfile(RiotLib.profile(baseURI, true, true, errHandler)) ;
+            } else
+                reader.setParserProfile(RiotLib.profile(baseURI, false, false, errHandler)) ;
+
+            if ( labelsAsGiven )
+                reader.getParserProfile().setLabelToNode(LabelToNode.createUseLabelAsGiven()) ;
+            modTime.startTimer() ;
+            reader.read(in, baseURI, ct, sink, null) ;
+        } catch (RiotException ex) {
+            // Should have handled the exception and logged a message by now.
+            // System.err.println("++++"+ex.getMessage());
+
+            if ( modLangParse.stopOnBadTerm() )
+                return ;
+        } finally {
+            // Not close - we may write again to the underlying output stream in another call to parse a file.  
+            sink.finish() ;
+            IO.close(in) ;
+        }
+        long x = modTime.endTimer() ;
+        long n = sink.countTriples()+sink.countQuads() ;
+
+        if ( modTime.timingEnabled() )
+            output(filename, n, x, handler) ;
+        
+        totalMillis += x ;
+        totalTuples += n ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/e7ac8b4d/jena-csv/src/test/java/org/apache/jena/propertytable/AbstractColumnTest.java
----------------------------------------------------------------------
diff --git a/jena-csv/src/test/java/org/apache/jena/propertytable/AbstractColumnTest.java b/jena-csv/src/test/java/org/apache/jena/propertytable/AbstractColumnTest.java
new file mode 100644
index 0000000..90ff0af
--- /dev/null
+++ b/jena-csv/src/test/java/org/apache/jena/propertytable/AbstractColumnTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.propertytable;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.graph.NodeFactory;
+
+/**
+ * Tests related to Column.
+ *
+ */
+public abstract class AbstractColumnTest extends BaseTest{
+
+
+	@Test(expected = NullPointerException.class)
+	public void testCreateColumnWithArgNull() {
+		table.createColumn(null);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testCreateListColumnWithAlreadyExistingCoulmnName() {
+		table.createColumn(URI("something"));
+		table.createColumn(URI("something"));
+	}
+	
+	@Test
+	public void testColumnCreate() {
+		table.createColumn(URI("something"));
+		Assert.assertEquals(1, table.getColumns().size());
+		Assert.assertTrue(collectionContains(table.getColumns(), URI("something")));
+	}
+	
+	@Test
+	public void testGetColumnValues() {
+		Column something = table.createColumn(URI("something"));
+		final Row row1 = table.createRow(NodeFactory.createAnon());
+		row1.setValue(something, URI("apple"));
+		final Row row2 = table.createRow(NodeFactory.createAnon());
+		row2.setValue(something, URI("orange"));
+		final List<Node> values = something.getValues();
+		Assert.assertTrue(values.size() == 2);
+		Assert.assertTrue(values.contains( URI("apple")));
+		Assert.assertTrue(values.contains(  URI("orange")));
+	}
+	
+	@Test
+	public void testGetColumn() {
+		table.createColumn(URI("something"));
+		Assert.assertNotNull(table.getColumn(URI("something")));
+		Assert.assertNull(table.getColumn( URI("nonExistentColumnName")));
+	}
+
+	@Test
+	public void testGetTable() {
+		Column something = table.createColumn(URI("something"));
+		Assert.assertEquals(table, something.getTable());
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/e7ac8b4d/jena-csv/src/test/java/org/apache/jena/propertytable/AbstractPropertyTableTest.java
----------------------------------------------------------------------
diff --git a/jena-csv/src/test/java/org/apache/jena/propertytable/AbstractPropertyTableTest.java b/jena-csv/src/test/java/org/apache/jena/propertytable/AbstractPropertyTableTest.java
new file mode 100644
index 0000000..3738d4e
--- /dev/null
+++ b/jena-csv/src/test/java/org/apache/jena/propertytable/AbstractPropertyTableTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.propertytable;
+
+import java.util.Collection;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.hp.hpl.jena.graph.NodeFactory;
+
+/**
+ * Tests related to PropertyTable.
+ *
+ */
+public abstract class AbstractPropertyTableTest extends AbstractRowTest{
+
+	@Test
+	public void testGetMatchingColumns() {
+		Column something = table.createColumn(URI("something") );
+		final Row row1 = table.createRow(NodeFactory.createAnon());
+		row1.setValue(something, URI("apple"));
+		final Row row2 = table.createRow(NodeFactory.createAnon());
+		row2.setValue(something, URI("orange"));
+		Collection<Row> matchingRows = table.getMatchingRows(something, URI("apple"));
+		Assert.assertTrue(matchingRows.size() == 1);
+		matchingRows = table.getMatchingRows(something, URI("banana"));
+		Assert.assertTrue(matchingRows.isEmpty());
+	}
+	
+	@Test
+	public void testGetAllRows() {
+		Assert.assertTrue(table.getAllRows().size() == 1);
+		table.createRow(NodeFactory.createAnon());
+		Assert.assertTrue(table.getAllRows().size() == 2);
+		table.createRow(NodeFactory.createAnon());
+		Assert.assertTrue(table.getAllRows().size() == 3);
+	}
+
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/e7ac8b4d/jena-csv/src/test/java/org/apache/jena/propertytable/AbstractRowTest.java
----------------------------------------------------------------------
diff --git a/jena-csv/src/test/java/org/apache/jena/propertytable/AbstractRowTest.java b/jena-csv/src/test/java/org/apache/jena/propertytable/AbstractRowTest.java
new file mode 100644
index 0000000..9457375
--- /dev/null
+++ b/jena-csv/src/test/java/org/apache/jena/propertytable/AbstractRowTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.propertytable;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.graph.NodeFactory;
+
+/**
+ * Tests related to Row.
+ *
+ */
+public abstract class AbstractRowTest extends AbstractColumnTest{
+
+	@Test
+	public void testAddRowValue() {
+
+		Column something = table.createColumn(URI("something"));
+		Column somethingElse = table.createColumn(URI("somethingElse"));
+
+		row.setValue(something, URI("apple"));
+		row.setValue(somethingElse, URI("orange"));
+
+		Assert.assertEquals(URI("apple"), row.getValue(something));
+		Assert.assertEquals(URI("orange"), row.getValue(somethingElse));
+	}
+	
+	@Test
+	public void testUnsetRowValue() {
+		Column something = table.createColumn(URI("something"));
+		row.setValue( something , URI("apple"));
+		Assert.assertEquals(URI("apple"), row.getValue(something));
+		row.setValue( something , null);
+		Assert.assertEquals(null, row.getValue(something));
+	}
+	
+	@Test(expected=NullPointerException.class)
+	public void testGetRowWithNullKey() {
+		table.getRow(null);
+	}
+	
+	@Test(expected = NullPointerException.class)
+	public void testAddValueToNotExistingColumn() {
+		row.setValue(table.getColumn(URI("something")), URI("apple"));
+	}
+	
+
+	
+	@Test(expected=IllegalArgumentException.class)
+	public void testGetListWithANonExistantColumn() {
+		Assert.assertNull(row.getValue( NodeFactory.createAnon() ));
+	}
+	
+	@Test
+	public void testGetListWithAnMissingRowValue() {
+		Column something = table.createColumn(URI("something"));
+		Assert.assertNull(row.getValue(something));
+	}
+
+    @Test
+    public void testGetValue() {
+    	Column something = table.createColumn(URI("something"));
+        row.setValue(something, URI("apple"));
+        Node value = row.getValue(something);
+        Assert.assertEquals(URI("apple"), value);
+    }
+    
+    @Test
+    public void testRowExistsFalse(){
+    	Assert.assertNull(table.getRow(NodeFactory.createAnon()));
+    }
+    
+    @Test
+    public void testRowExistsTrue() {
+		Assert.assertNotNull(table.getRow(rowSubject));
+    }
+
+    @Test
+    public void testGetRowFalseAndDoesntCreateRow() {
+    	Assert.assertNull(table.getRow(NodeFactory.createAnon()));
+    	Assert.assertNull(table.getRow(NodeFactory.createAnon()));
+    }
+    
+    @Test(expected=IllegalArgumentException.class)
+	public void testGetValueBeforeColumnExists() {
+		row.getValue(URI("nonexistentColumnX"));
+	}
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/e7ac8b4d/jena-csv/src/test/java/org/apache/jena/propertytable/BaseTest.java
----------------------------------------------------------------------
diff --git a/jena-csv/src/test/java/org/apache/jena/propertytable/BaseTest.java b/jena-csv/src/test/java/org/apache/jena/propertytable/BaseTest.java
new file mode 100644
index 0000000..282f649
--- /dev/null
+++ b/jena-csv/src/test/java/org/apache/jena/propertytable/BaseTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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.propertytable;
+
+import java.util.Collection;
+
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.graph.NodeFactory;
+
+public abstract class BaseTest {
+	protected PropertyTable table;
+	protected PropertyTable table2;
+	protected Row row;
+	private static final String ns = "eh:foo/bar#";
+	protected static final Node rowSubject = URI("rowSubject");
+	protected static final String csvFilePath = "src/test/resources/test.csv";
+	
+	
+	protected static Node URI(String localName) {
+		return NodeFactory.createURI(ns + localName);
+	}
+	
+	protected static boolean collectionContains(
+			final Collection<Column> columns, final Node columnkey) {
+		for (final Column column : columns) {
+			if (column.getColumnKey().equals(columnkey))
+				return true;
+		}
+		return false;
+	}
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/e7ac8b4d/jena-csv/src/test/java/org/apache/jena/propertytable/TS_PropertyTable.java
----------------------------------------------------------------------
diff --git a/jena-csv/src/test/java/org/apache/jena/propertytable/TS_PropertyTable.java b/jena-csv/src/test/java/org/apache/jena/propertytable/TS_PropertyTable.java
new file mode 100644
index 0000000..084365d
--- /dev/null
+++ b/jena-csv/src/test/java/org/apache/jena/propertytable/TS_PropertyTable.java
@@ -0,0 +1,42 @@
+/*
+ * 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.propertytable;
+
+import org.apache.jena.propertytable.graph.GraphCSVTest;
+import org.apache.jena.propertytable.impl.PropertyTableArrayImplTest;
+import org.apache.jena.propertytable.impl.PropertyTableBuilderForArrayImplTest;
+import org.apache.jena.propertytable.impl.PropertyTableBuilderForHashMapImplTest;
+import org.apache.jena.propertytable.impl.PropertyTableHashMapImplTest;
+import org.apache.jena.propertytable.lang.TestLangCSV;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses( {
+	PropertyTableArrayImplTest.class,
+	PropertyTableHashMapImplTest.class,
+	GraphCSVTest.class,
+	PropertyTableBuilderForArrayImplTest.class,
+	PropertyTableBuilderForHashMapImplTest.class,
+	TestLangCSV.class
+})
+public class TS_PropertyTable {
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/e7ac8b4d/jena-csv/src/test/java/org/apache/jena/propertytable/graph/GraphCSVTest.java
----------------------------------------------------------------------
diff --git a/jena-csv/src/test/java/org/apache/jena/propertytable/graph/GraphCSVTest.java b/jena-csv/src/test/java/org/apache/jena/propertytable/graph/GraphCSVTest.java
new file mode 100644
index 0000000..3d23f86
--- /dev/null
+++ b/jena-csv/src/test/java/org/apache/jena/propertytable/graph/GraphCSVTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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.propertytable.graph;
+
+import org.apache.jena.propertytable.graph.GraphCSV;
+import org.apache.jena.propertytable.lang.LangCSV;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.hp.hpl.jena.query.ARQ;
+import com.hp.hpl.jena.query.Query;
+import com.hp.hpl.jena.query.QueryExecution;
+import com.hp.hpl.jena.query.QueryExecutionFactory;
+import com.hp.hpl.jena.query.QueryFactory;
+import com.hp.hpl.jena.query.QuerySolution;
+import com.hp.hpl.jena.query.ResultSet;
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.ModelFactory;
+import com.hp.hpl.jena.sparql.engine.main.StageBuilder;
+import com.hp.hpl.jena.sparql.engine.main.StageGenerator;
+
+/**
+ * Tests related to GraphCSV with some real world data.
+ *
+ */
+public class GraphCSVTest extends Assert {
+	
+	@BeforeClass
+	public static void init(){
+		LangCSV.register();
+	}
+	
+	@Test
+	public void testGraphCSV() throws Exception {
+		//String file = "src/test/resources/HEFCE_organogram_senior_data_31032011.csv";test.csv
+		String file = "src/test/resources/test.csv";
+		
+		Model csv = ModelFactory.createModelForGraph(new GraphCSV(file));
+		assertEquals(12, csv.size());
+
+		Query query = QueryFactory
+				.create("PREFIX : <src/test/resources/test.csv#> SELECT ?townName ?pop {?x :Town ?townName ; :Population ?pop ; :Predicate%20With%20Space 'PredicateWithSpace2' . FILTER(?pop > 500000)}");
+		
+		QueryExecution qexec = QueryExecutionFactory.create(query, csv);
+		ResultSet results = qexec.execSelect();
+		
+		assertTrue(results.hasNext());
+		QuerySolution soln = results.nextSolution();
+		assertEquals( "Northville", soln.getLiteral("townName").getString());
+		assertTrue( 654000 == soln.getLiteral("pop").getInt());
+		
+		assertFalse(results.hasNext());
+	}
+	
+	@Test 
+	public void stageGeneratorTest() throws Exception{
+		wireIntoExecution();
+		testGraphCSV();
+	}
+	
+    private static void wireIntoExecution() {
+        StageGenerator orig = (StageGenerator)ARQ.getContext().get(ARQ.stageGenerator) ;
+        StageGenerator stageGenerator = new StageGeneratorPropertyTable(orig) ;
+        StageBuilder.setGenerator(ARQ.getContext(), stageGenerator) ;
+    }
+	
+	//http://www.w3.org/TR/csvw-ucr/#UC-OrganogramData
+	//2.4 Use Case #4 - Publication of public sector roles and salaries
+	@Test
+	public void testUseCase4(){
+		String file = "src/test/resources/HEFCE_organogram_senior_data_31032011.csv";
+		
+		Model csv = ModelFactory.createModelForGraph(new GraphCSV(file));
+		assertEquals(72, csv.size());
+
+		Query query = QueryFactory
+				.create("PREFIX : <src/test/resources/HEFCE_organogram_senior_data_31032011.csv#> SELECT ?name ?unit {?x :Name ?name ; :Unit ?unit ; :Actual%20Pay%20Floor%20%28%A3%29 ?floor ; :Actual%20Pay%20Ceiling%20%28%A3%29 ?ceiling . FILTER(?floor > 100000 && ?ceiling <120000 )}");
+		
+		QueryExecution qexec = QueryExecutionFactory.create(query, csv);
+		ResultSet results = qexec.execSelect();
+		
+		assertTrue(results.hasNext());
+		QuerySolution soln = results.nextSolution();
+		assertEquals( "David Sweeney", soln.getLiteral("name").getString());
+		assertEquals( "Research, Innovation and Skills", soln.getLiteral("unit").getString());
+		
+		assertFalse(results.hasNext());
+	}
+	
+	
+	//http://www.w3.org/TR/csvw-ucr/#UC-JournalArticleSearch
+	//2.6 Use Case #6 - Journal Article Solr Search Results
+	@Test
+	public void testUseCase6(){
+		String file = "src/test/resources/PLOSone-search-results.csv";
+		
+		Model csv = ModelFactory.createModelForGraph(new GraphCSV(file));
+		assertEquals(30, csv.size());
+
+		Query query = QueryFactory
+				.create("PREFIX : <src/test/resources/PLOSone-search-results.csv#> SELECT ?author {?x :author ?author ; :doi '10.1371/journal.pone.0095156' }");
+		
+		QueryExecution qexec = QueryExecutionFactory.create(query, csv);
+		ResultSet results = qexec.execSelect();
+		
+		assertTrue(results.hasNext());
+		QuerySolution soln = results.nextSolution();
+		assertEquals( "Oshrat Raz,Dorit L Lev,Alexander Battler,Eli I Lev", soln.getLiteral("author").getString());
+		
+		assertFalse(results.hasNext());
+	}
+	
+	//http://www.w3.org/TR/csvw-ucr/#UC-PaloAltoTreeData
+	//2.11 Use Case #11 - City of Palo Alto Tree Data
+	@Test
+	public void testUseCase11(){
+		String file = "src/test/resources/Palo_Alto_Trees.csv";
+		
+		Model csv = ModelFactory.createModelForGraph(new GraphCSV(file));
+		assertEquals(199, csv.size());
+
+		Query query = QueryFactory
+				.create("PREFIX : <src/test/resources/Palo_Alto_Trees.csv#> SELECT ?longitude ?latitude {?x :Longitude ?longitude ; :Latitude ?latitude ; :Distance%20from%20Property ?distance . FILTER(?distance > 50 )}");
+		
+		QueryExecution qexec = QueryExecutionFactory.create(query, csv);
+		ResultSet results = qexec.execSelect();
+		
+		assertTrue(results.hasNext());
+		QuerySolution soln = results.nextSolution();
+		assertEquals( -122.1566921, soln.getLiteral("longitude").getDouble(), 0);
+		assertEquals( 37.4408948, soln.getLiteral("latitude").getDouble(), 0);
+		
+		assertFalse(results.hasNext());
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/e7ac8b4d/jena-csv/src/test/java/org/apache/jena/propertytable/impl/AbstractPropertyTableBuilderTest.java
----------------------------------------------------------------------
diff --git a/jena-csv/src/test/java/org/apache/jena/propertytable/impl/AbstractPropertyTableBuilderTest.java b/jena-csv/src/test/java/org/apache/jena/propertytable/impl/AbstractPropertyTableBuilderTest.java
new file mode 100644
index 0000000..f7a1e02
--- /dev/null
+++ b/jena-csv/src/test/java/org/apache/jena/propertytable/impl/AbstractPropertyTableBuilderTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.propertytable.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+
+import org.apache.jena.atlas.csv.CSVTokenIterator;
+import org.apache.jena.propertytable.BaseTest;
+import org.apache.jena.propertytable.Row;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.graph.NodeFactory;
+
+
+/**
+ * Tests related to PropertyTableBuilder, or more explicitly for the CSV parser in the current release.
+ *
+ */
+public abstract class AbstractPropertyTableBuilderTest extends BaseTest {
+
+	@Test
+	public void testFillPropertyTable() {
+		CSVTokenIterator iterator = csv("a,b\nc,d\ne,f");
+		PropertyTableBuilder.fillPropertyTable(table, iterator, csvFilePath);
+
+		Assert.assertEquals(3, table.getColumns().size());
+		containsColumn(PropertyTableBuilder.CSV_ROW_NODE);
+		containsColumn("a");
+		containsColumn("b");
+
+		Assert.assertEquals(2, table.getAllRows().size());
+		containsValue(0, "a", "c");
+		containsValue(0, "b", "d");
+
+		containsValue(1, "a", "e");
+		containsValue(1, "b", "f");
+
+	}
+
+	@Test
+	public void testIrregularTable1() {
+		CSVTokenIterator iterator = csv("a,b\nc\ne,f");
+		PropertyTableBuilder.fillPropertyTable(table, iterator, csvFilePath);
+
+		Assert.assertEquals(3, table.getColumns().size());
+		containsColumn(PropertyTableBuilder.CSV_ROW_NODE);
+		containsColumn("a");
+		containsColumn("b");
+
+		Assert.assertEquals(2, table.getAllRows().size());
+		containsValue(0, "a", "c");
+		nullValue(0, "b");
+
+		containsValue(1, "a", "e");
+		containsValue(1, "b", "f");
+	}
+
+	@Test
+	public void testIrregularTable2() {
+		CSVTokenIterator iterator = csv("a,b\nc,d1,d2\ne,f");
+		PropertyTableBuilder.fillPropertyTable(table, iterator, csvFilePath);
+
+		Assert.assertEquals(3, table.getColumns().size());
+		containsColumn(PropertyTableBuilder.CSV_ROW_NODE);
+		containsColumn("a");
+		containsColumn("b");
+
+		Assert.assertEquals(2, table.getAllRows().size());
+		containsValue(0, "a", "c");
+		containsValue(0, "b", "d1");
+
+		containsValue(1, "a", "e");
+		containsValue(1, "b", "f");
+	}
+
+	@Test
+	public void testIrregularTable3() {
+		CSVTokenIterator iterator = csv("a,b\n,d\ne,f");
+		PropertyTableBuilder.fillPropertyTable(table, iterator, csvFilePath);
+
+		Assert.assertEquals(3, table.getColumns().size());
+		containsColumn(PropertyTableBuilder.CSV_ROW_NODE);
+		containsColumn("a");
+		containsColumn("b");
+
+		Assert.assertEquals(2, table.getAllRows().size());
+		nullValue(0, "a");
+		containsValue(0, "b", "d");
+
+		containsValue(1, "a", "e");
+		containsValue(1, "b", "f");
+	}
+
+	private void nullValue(int rowIndex, String column) {
+		Row row = table.getAllRows().get(rowIndex);
+		Node v = row.getValue(NodeFactory.createURI(getColumnKey(column)));
+		Assert.assertEquals(null, v);
+	}
+
+	private void containsValue(int rowIndex, String column, String value) {
+		Row row = table.getAllRows().get(rowIndex);
+		Node v = row.getValue(NodeFactory.createURI(getColumnKey(column)));
+		Assert.assertEquals(value, v.getLiteralValue());
+	}
+
+	private String getColumnKey(String column) {
+		return PropertyTableBuilder.createColumnKeyURI(csvFilePath, column);
+	}
+
+	private void containsColumn(String column) {
+		containsColumn(NodeFactory.createURI(getColumnKey(column)));
+	}
+
+	private void containsColumn(Node columnKey) {
+		Assert.assertTrue(collectionContains(table.getColumns(), columnKey));
+	}
+
+	private CSVTokenIterator csv(String input) {
+		try {
+			InputStream in = new ByteArrayInputStream(input.getBytes("UTF-8"));
+			CSVTokenIterator iterator = new CSVTokenIterator(in);
+			return iterator;
+		} catch (UnsupportedEncodingException e) {
+			throw new RuntimeException(e);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/e7ac8b4d/jena-csv/src/test/java/org/apache/jena/propertytable/impl/PropertyTableArrayImplTest.java
----------------------------------------------------------------------
diff --git a/jena-csv/src/test/java/org/apache/jena/propertytable/impl/PropertyTableArrayImplTest.java b/jena-csv/src/test/java/org/apache/jena/propertytable/impl/PropertyTableArrayImplTest.java
new file mode 100644
index 0000000..ba1ca2d
--- /dev/null
+++ b/jena-csv/src/test/java/org/apache/jena/propertytable/impl/PropertyTableArrayImplTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.propertytable.impl;
+
+import org.apache.jena.propertytable.AbstractPropertyTableTest;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for PropertyTableArrayImpl
+ *
+ */
+public class PropertyTableArrayImplTest extends AbstractPropertyTableTest{
+	
+	private static int rowNum = 10;
+	private static int columnNum = 10 ;
+	
+	@Before
+	public void setUp() {
+		table = new PropertyTableArrayImpl(rowNum, columnNum);
+		table2 = new PropertyTableArrayImpl(rowNum, columnNum);
+		row = table.createRow(rowSubject);
+
+	}
+
+	@After
+	public void tearDown() {
+		table = null;
+		table2 = null;
+		row = null;
+	}
+	
+	@Test
+	public void testColumnOutofBounds1() {
+		for (int i=0;i<columnNum;i++){
+			table.createColumn(URI("something_"+i));
+		}
+		Assert.assertEquals(columnNum, table.getColumns().size());
+	}
+	
+	@Test(expected = IllegalArgumentException.class)
+	public void testColumnOutofBounds2() {
+		for (int i=0;i<columnNum+1;i++){
+			table.createColumn(URI("something_"+i));
+		}
+	}
+	
+	@Test
+	public void testRowOutofBounds1() {
+		
+		// we've already created a new Row in @Before
+		for (int i=0;i<rowNum-1;i++){
+			table.createRow(URI("something_"+i));
+		}
+		Assert.assertEquals(rowNum, table.getAllRows().size());
+	}
+	
+	@Test(expected = IllegalArgumentException.class)
+	public void testRowOutofBounds2() {
+		
+		// we've already created a new Row in @Before
+		for (int i=0;i<rowNum;i++){
+			table.createRow(URI("something_"+i));
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/e7ac8b4d/jena-csv/src/test/java/org/apache/jena/propertytable/impl/PropertyTableBuilderForArrayImplTest.java
----------------------------------------------------------------------
diff --git a/jena-csv/src/test/java/org/apache/jena/propertytable/impl/PropertyTableBuilderForArrayImplTest.java b/jena-csv/src/test/java/org/apache/jena/propertytable/impl/PropertyTableBuilderForArrayImplTest.java
new file mode 100644
index 0000000..7b7e0c8
--- /dev/null
+++ b/jena-csv/src/test/java/org/apache/jena/propertytable/impl/PropertyTableBuilderForArrayImplTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.propertytable.impl;
+
+import org.junit.After;
+import org.junit.Before;
+
+public class PropertyTableBuilderForArrayImplTest extends AbstractPropertyTableBuilderTest{
+	
+	private static int rowNum = 10;
+	private static int columnNum = 10 ;
+	
+	@Before
+	public void setUp() {
+		table = new PropertyTableArrayImpl(rowNum, columnNum);
+	}
+
+	@After
+	public void tearDown() {
+		table = null;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/e7ac8b4d/jena-csv/src/test/java/org/apache/jena/propertytable/impl/PropertyTableBuilderForHashMapImplTest.java
----------------------------------------------------------------------
diff --git a/jena-csv/src/test/java/org/apache/jena/propertytable/impl/PropertyTableBuilderForHashMapImplTest.java b/jena-csv/src/test/java/org/apache/jena/propertytable/impl/PropertyTableBuilderForHashMapImplTest.java
new file mode 100644
index 0000000..f2768f5
--- /dev/null
+++ b/jena-csv/src/test/java/org/apache/jena/propertytable/impl/PropertyTableBuilderForHashMapImplTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.propertytable.impl;
+
+import org.junit.After;
+import org.junit.Before;
+
+public class PropertyTableBuilderForHashMapImplTest extends AbstractPropertyTableBuilderTest{
+	@Before
+	public void setUp() {
+		table = new PropertyTableHashMapImpl();
+	}
+
+	@After
+	public void tearDown() {
+		table = null;
+	}
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/e7ac8b4d/jena-csv/src/test/java/org/apache/jena/propertytable/impl/PropertyTableHashMapImplTest.java
----------------------------------------------------------------------
diff --git a/jena-csv/src/test/java/org/apache/jena/propertytable/impl/PropertyTableHashMapImplTest.java b/jena-csv/src/test/java/org/apache/jena/propertytable/impl/PropertyTableHashMapImplTest.java
new file mode 100644
index 0000000..33d95ae
--- /dev/null
+++ b/jena-csv/src/test/java/org/apache/jena/propertytable/impl/PropertyTableHashMapImplTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.propertytable.impl;
+
+import org.apache.jena.propertytable.AbstractPropertyTableTest;
+import org.junit.After;
+import org.junit.Before;
+
+/**
+ * Tests for PropertyTableHashMapImpl
+ *
+ */
+public class PropertyTableHashMapImplTest extends AbstractPropertyTableTest{
+	
+	@Before
+	public void setUp() {
+		table = new PropertyTableHashMapImpl();
+		table2 = new PropertyTableHashMapImpl();
+		row = table.createRow(rowSubject);
+
+	}
+
+	@After
+	public void tearDown() {
+		table = null;
+		table2 = null;
+		row = null;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/e7ac8b4d/jena-csv/src/test/java/org/apache/jena/propertytable/lang/TestLangCSV.java
----------------------------------------------------------------------
diff --git a/jena-csv/src/test/java/org/apache/jena/propertytable/lang/TestLangCSV.java b/jena-csv/src/test/java/org/apache/jena/propertytable/lang/TestLangCSV.java
new file mode 100644
index 0000000..697ba27
--- /dev/null
+++ b/jena-csv/src/test/java/org/apache/jena/propertytable/lang/TestLangCSV.java
@@ -0,0 +1,113 @@
+/*
+ * 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.propertytable.lang;
+
+import java.io.StringReader;
+
+import org.apache.jena.atlas.junit.BaseTest;
+import org.apache.jena.atlas.lib.StrUtils;
+import org.apache.jena.riot.Lang;
+import org.apache.jena.riot.RDFDataMgr;
+import org.apache.jena.riot.RDFLanguages;
+import org.apache.jena.riot.system.IRIResolver;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.ModelFactory;
+
+
+/**
+ * Tests for the registered LangCSV in RIOT.
+ *
+ */
+public class TestLangCSV extends BaseTest {
+		
+	private static final String FILE_NAME = "src/test/resources/test.csv";
+	private static final String FILE_URI = IRIResolver.resolveString(FILE_NAME);
+
+	@BeforeClass
+	public static void init(){
+		LangCSV.register();
+	}
+	
+	@Test
+	public void testPredicateWithSpace() {
+		String[] s1 = { "Predicate With Space", "PredicateWithSpace" };
+		String[] s2 = {
+				//"<"+ LangCSV.caculateSubject(1, FILE_NAME) + "> <" + FILE_URI + "#Predicate+With+Space> 'PredicateWithSpace' ; ",
+				" [] <" + FILE_URI + "#Predicate%20With%20Space> 'PredicateWithSpace' ; ",
+				" <http://w3c/future-csv-vocab/row> 1 ." };
+		assertIsomorphicWith(s1, s2);
+	}
+	
+	@Test
+	public void testNonURICharacters() {
+		String[] s1 = { "`~!@#$%^&*()-_=+[{]}|\\;:'\"<.>/?", "NonURICharacters" };
+		String[] s2 = {
+				//"<"+ LangCSV.caculateSubject(1, FILE_NAME) + "> <" + FILE_URI + "#%60%7E%21%40%23%24%25%5E%26*%28%29-_%3D%2B%5B%7B%5D%7D%7C%5C%3B%3A%27%22%3C.%3E%2F%3F> 'NonURICharacters' ; ",
+				" [] <" + FILE_URI + "#%60~%21%40%23%24%25%5E%26%2A%28%29-_%3D%2B%5B%7B%5D%7D%7C%5C%3B%3A%27%22%3C.%3E%2F%3F> 'NonURICharacters' ; ",
+				" <http://w3c/future-csv-vocab/row> 1 ." };
+		assertIsomorphicWith(s1, s2);
+	}
+	
+	@Test
+	public void testDigitalLocalName() {
+		String[] s1 = { "1234", "DigitalLocalName" };
+		String[] s2 = {
+				//"<"+ LangCSV.caculateSubject(1, FILE_NAME) + "> <" + FILE_URI + "#1234> 'DigitalLocalName' ; ",
+				" [] <" + FILE_URI + "#1234> 'DigitalLocalName' ; ",
+				" <http://w3c/future-csv-vocab/row> 1 ." };
+		assertIsomorphicWith(s1, s2);
+	}
+
+	@Test
+	public void testMoney() {
+		String[] s1 = { "£", "£" };
+		String[] s2 = {
+				//"<"+ LangCSV.caculateSubject(1, FILE_NAME) + "> <" + FILE_URI + "#1234> 'DigitalLocalName' ; ",
+				" [] <" + FILE_URI + "#%A3> '£' ; ",
+				" <http://w3c/future-csv-vocab/row> 1 ." };
+		assertIsomorphicWith(s1, s2);
+	}
+	
+	@Test
+	public void RDFDataMgrReadTest() {
+		Model m1 = RDFDataMgr.loadModel(FILE_NAME, RDFLanguages.CSV);
+		Model m2 = ModelFactory.createDefaultModel();
+		m2.read(FILE_NAME, "CSV");
+		assertEquals(12, m1.size());
+		assertTrue(m1.isIsomorphicWith(m2));
+	}
+
+	private Model parseToModel(String[] strings, Lang lang) {
+		String string = StrUtils.strjoin("\n", strings);
+		StringReader r = new StringReader(string);
+		Model model = ModelFactory.createDefaultModel();
+		RDFDataMgr.read(model, r, FILE_NAME, lang);
+		return model;
+	}
+	
+	private void assertIsomorphicWith(String[] s1, String[] s2){
+		Model m1 = parseToModel(s1, RDFLanguages.CSV);
+		Model m2 = parseToModel(s2, RDFLanguages.TURTLE);
+		assertTrue(m1.isIsomorphicWith(m2));
+	}
+
+}


Mime
View raw message