You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2015/04/28 23:03:28 UTC
[1/9] jena git commit: Import of lib, io,
logging and iterator packages
Repository: jena
Updated Branches:
refs/heads/master 692118f9d -> 1320f8dbe
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestCache.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestCache.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestCache.java
new file mode 100644
index 0000000..05513fe
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestCache.java
@@ -0,0 +1,149 @@
+/*
+ * 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.lib;
+
+import java.util.Arrays ;
+import java.util.Collection ;
+import java.util.List ;
+
+import org.apache.jena.atlas.iterator.Iter ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.Cache ;
+import org.apache.jena.atlas.lib.CacheFactory ;
+import org.junit.Before ;
+import org.junit.Test ;
+import org.junit.runner.RunWith ;
+import org.junit.runners.Parameterized ;
+import org.junit.runners.Parameterized.Parameters ;
+
+@RunWith(Parameterized.class)
+public class TestCache extends BaseTest
+{
+ // Tests do not apply to cache1.
+ private static interface CacheMaker<K,V> { Cache<K,V> make(int size) ; String name() ; }
+
+ private static CacheMaker<Integer, Integer> simple =
+ new CacheMaker<Integer, Integer>()
+ {
+ @Override
+ public Cache<Integer, Integer> make(int size) { return CacheFactory.createSimpleCache(size) ; }
+ @Override
+ public String name() { return "Simple" ; }
+ }
+ ;
+
+ private static CacheMaker<Integer, Integer> standard =
+ new CacheMaker<Integer, Integer>()
+ {
+ @Override
+ public Cache<Integer, Integer> make(int size) { return CacheFactory.createCache(size) ; }
+ @Override
+ public String name() { return "Standard" ; }
+ }
+ ;
+
+ @Parameters
+ public static Collection<Object[]> cacheMakers()
+ {
+ return Arrays.asList(new Object[][] {
+ { simple , 10 }
+ , { simple , 2 }
+ , { simple , 1 }
+ , { standard , 10 }
+ , { standard , 2 }
+ , { standard , 1 }
+ } ) ;
+ }
+
+ Cache<Integer, Integer> cache ;
+ CacheMaker<Integer,Integer> cacheMaker ;
+ int size ;
+
+
+ public TestCache(CacheMaker<Integer,Integer> cacheMaker, int size)
+ {
+ this.cacheMaker = cacheMaker ;
+ this.size = size ;
+
+ }
+
+ @Before public void before() { cache = cacheMaker.make(size) ; }
+
+ @Test public void cache_00()
+ {
+ assertEquals(0, cache.size()) ;
+ assertTrue(cache.isEmpty()) ;
+ }
+
+ @Test public void cache_01()
+ {
+ Integer x = cache.getIfPresent(7) ;
+ cache.put(7, 7) ;
+ assertEquals(1, cache.size()) ;
+ assertNull(x) ;
+ assertTrue(cache.containsKey(7)) ;
+ assertEquals(Integer.valueOf(7), cache.getIfPresent(7)) ;
+ }
+
+ @Test public void cache_02()
+ {
+ cache.put(7, 7) ;
+ cache.put(8, 8) ;
+ // Not true for Cache1.
+ if ( size > 2 )
+ assertEquals(2, cache.size()) ;
+ if ( size > 2 )
+ assertTrue(cache.containsKey(7)) ;
+
+ if ( size > 2 )
+ assertEquals(Integer.valueOf(7), cache.getIfPresent(7)) ;
+
+ assertTrue(cache.containsKey(8)) ;
+ assertEquals(Integer.valueOf(8), cache.getIfPresent(8)) ;
+ }
+
+ @Test public void cache_03()
+ {
+ cache.put(7, 7) ;
+ Integer x1 = cache.getIfPresent(7) ;
+ cache.put(7, 18) ;
+ assertEquals(1, cache.size()) ;
+ assertEquals(7, x1.intValue()) ;
+ assertTrue(cache.containsKey(7)) ;
+ assertEquals(Integer.valueOf(18), cache.getIfPresent(7)) ;
+ }
+
+ @Test public void cache_04()
+ {
+ cache.clear() ;
+ cache.put(7, 77) ;
+ List<Integer> x = Iter.toList(cache.keys()) ;
+ assertEquals(1, x.size()) ;
+ assertEquals(Integer.valueOf(7), x.get(0)) ;
+ }
+
+ @Test public void cache_05()
+ {
+ cache.clear() ;
+ cache.put(7, 77) ;
+ cache.clear() ;
+ assertEquals(0, cache.size()) ;
+ assertTrue(cache.isEmpty()) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestCache2.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestCache2.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestCache2.java
new file mode 100644
index 0000000..2e640f3
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestCache2.java
@@ -0,0 +1,88 @@
+/*
+ * 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.lib;
+
+import java.util.concurrent.Callable ;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.Cache ;
+import org.apache.jena.atlas.lib.CacheFactory ;
+import org.apache.jena.atlas.lib.cache.Cache1 ;
+import org.junit.Test ;
+
+// Non-parameterized tests
+public class TestCache2 extends BaseTest
+{
+ // Cache1
+ @Test public void cache_10()
+ {
+ Cache<Integer, String> cache = new Cache1<>() ;
+ String str = cache.getIfPresent(1) ;
+ assertNull(str) ;
+
+ cache.put(1, "1") ;
+ str = cache.getIfPresent(1) ;
+ assertEquals("1", str) ;
+
+ cache.put(2, "2") ;
+ str = cache.getIfPresent(1) ;
+ assertNull(str) ;
+
+ cache.put(1, "1") ;
+ str = cache.getIfPresent(2) ;
+ assertNull(str) ;
+ str = cache.getIfPresent(1) ;
+ assertEquals("1", str) ;
+ }
+
+
+
+ static Callable<String> getter(final Integer key) {
+ return new Callable<String>() {
+ @Override
+ public String call() {
+ return key.toString() ; }
+ } ;
+ }
+
+ // Cache + getters
+ @Test public void cacheGetter_1()
+ {
+ Cache<Integer, String> cache = CacheFactory.createCache(2) ;
+ String str = cache.getOrFill(1, getter(1)) ;
+ assertEquals("1", str) ;
+ }
+
+ // Cache + getters
+ @Test public void cacheGetter_2()
+ {
+ Cache<Integer, String> cache = CacheFactory.createCache(2) ;
+ String str1 = cache.getOrFill(1, getter(1)) ;
+ String str2 = cache.getOrFill(2, getter(2)) ;
+ String str3 = cache.getOrFill(3, getter(3)) ;
+ assertEquals("1", str1) ;
+ assertEquals("2", str2) ;
+ assertEquals("3", str3) ;
+ cache.put(1, "10") ;
+ str1 = cache.getIfPresent(1) ;
+ assertEquals("10", str1) ;
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestColumnMap.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestColumnMap.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestColumnMap.java
new file mode 100644
index 0000000..fb44166
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestColumnMap.java
@@ -0,0 +1,107 @@
+/*
+ * 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.lib;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.ColumnMap ;
+import org.apache.jena.atlas.lib.Tuple ;
+import static org.apache.jena.atlas.lib.Tuple.* ;
+import org.junit.Test ;
+
+public class TestColumnMap extends BaseTest
+{
+ @Test public void remap1()
+ {
+ ColumnMap x = new ColumnMap("SPO->POS", 2,0,1) ; // S->2 etc
+
+ Integer[] array = {0,1,2 } ;
+ assertEquals(Integer.valueOf(2), x.mapSlot(0, array) ) ;
+ assertEquals(Integer.valueOf(0), x.mapSlot(1, array) ) ;
+ assertEquals(Integer.valueOf(1), x.mapSlot(2, array) ) ;
+ }
+
+ @Test public void remap2()
+ {
+ ColumnMap x = new ColumnMap("SPO->POS", 2,0,1) ;
+ Integer[] array = { 0,1,2 } ;
+ assertEquals(Integer.valueOf(1), x.fetchSlot(0, array)) ; // The index 1 comes from position 0.
+ assertEquals(Integer.valueOf(2), x.fetchSlot(1, array)) ;
+ assertEquals(Integer.valueOf(0), x.fetchSlot(2, array)) ;
+ }
+
+ @Test public void remap3()
+ {
+ ColumnMap x = new ColumnMap("POS", 2,0,1) ;
+ Tuple<String> tuple = createTuple("S", "P", "O") ;
+ Tuple<String> mapped = x.map(tuple) ;
+ Tuple<String> expected = createTuple("P", "O", "S") ;
+ assertEquals(expected, mapped) ;
+ }
+
+ @Test public void remap4()
+ {
+ ColumnMap x = new ColumnMap("POS", 2,0,1) ;
+ Tuple<String> tuple = createTuple("S", "P", "O") ;
+ Tuple<String> tuple2 = x.map(tuple) ;
+ tuple2 = x.unmap(tuple2) ;
+ assertEquals(tuple, tuple2) ;
+ }
+
+ @Test public void compile1()
+ {
+ int[] x = ColumnMap.compileMapping("SPO", "POS") ;
+ // SPO -> POS so col 0 goes to col 2, col 1 goes to col 0 and col 2 goes to col 1
+ int[] expected = { 2,0,1 } ;
+ assertArrayEquals(expected, x) ;
+ }
+
+ @Test public void compile2()
+ {
+ int[] x = ColumnMap.compileMapping("SPOG", "GOPS") ;
+ int[] expected = { 3, 2, 1, 0 } ;
+ assertArrayEquals(expected, x) ;
+ }
+
+ @Test public void map1()
+ {
+ ColumnMap cmap = new ColumnMap("GSPO", "OSPG") ;
+ Tuple<String> tuple = createTuple("G", "S", "P", "O") ;
+ Tuple<String> mapped = cmap.map(tuple) ;
+ Tuple<String> expected = createTuple("O", "S", "P", "G") ;
+ assertEquals(expected, mapped) ;
+ Tuple<String> unmapped = cmap.unmap(mapped) ;
+ assertEquals(createTuple("G", "S", "P", "O"), unmapped) ;
+ }
+
+ @Test public void map2()
+ {
+ String[] x = { "G", "S", "P", "O" } ;
+ String[] y = { "O", "S", "P", "G" } ;
+
+ ColumnMap cmap = new ColumnMap("Test", x, y) ;
+ Tuple<String> tuple = Tuple.create(x) ;
+ Tuple<String> mapped = cmap.map(tuple) ;
+
+ Tuple<String> expected = Tuple.create(y) ;
+ assertEquals(expected, mapped) ;
+ Tuple<String> unmapped = cmap.unmap(mapped) ;
+ assertEquals(Tuple.create(x), unmapped) ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestDateTimeUtils.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestDateTimeUtils.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestDateTimeUtils.java
new file mode 100644
index 0000000..8aae32b
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestDateTimeUtils.java
@@ -0,0 +1,82 @@
+/*
+ * 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.lib;
+
+import static org.junit.Assert.*;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+import org.apache.jena.atlas.lib.DateTimeUtils ;
+import org.junit.Test;
+
+public class TestDateTimeUtils {
+
+ @Test
+ public void testCalendarToXSDDateTimeString_1() throws Exception {
+ Calendar cal = createCalendar(1984, Calendar.MARCH, 22, 14, 32, 1, 0, "Z") ;
+ assertEquals("1984-03-22T14:32:01+00:00", DateTimeUtils.calendarToXSDDateTimeString(cal));
+ cal.setTimeZone(TimeZone.getTimeZone("MST"));
+ assertEquals("1984-03-22T07:32:01-07:00", DateTimeUtils.calendarToXSDDateTimeString(cal));
+ }
+
+ @Test
+ public void testCalendarToXSDDateTimeString_2() throws Exception {
+ Calendar cal = createCalendar(1984, Calendar.MARCH, 22, 14, 32, 1, 50, "Z") ;
+ assertEquals("1984-03-22T14:32:01.050+00:00", DateTimeUtils.calendarToXSDDateTimeString(cal));
+ cal.setTimeZone(TimeZone.getTimeZone("MST"));
+ assertEquals("1984-03-22T07:32:01.050-07:00", DateTimeUtils.calendarToXSDDateTimeString(cal));
+ }
+
+
+ @Test
+ public void testCalendarToXSDDateString() throws Exception {
+ Calendar cal = createCalendar(1984, Calendar.MARCH, 22, 23, 59, 1, 0, "Z");
+ cal.setTimeZone(TimeZone.getTimeZone("Z")) ;
+ assertEquals("1984-03-22+00:00", DateTimeUtils.calendarToXSDDateString(cal));
+ cal.setTimeZone(TimeZone.getTimeZone("MST"));
+ assertEquals("1984-03-22-07:00", DateTimeUtils.calendarToXSDDateString(cal));
+ }
+
+ @Test
+ public void testCalendarToXSDTimeString_1() throws Exception {
+ Calendar cal = createCalendar(1984, Calendar.MARCH, 22, 14, 32, 1, 0, "GMT+01:00");
+ assertEquals("14:32:01+01:00", DateTimeUtils.calendarToXSDTimeString(cal));
+ // Different timezone - moves the cal point-in-time.
+ cal.setTimeZone(TimeZone.getTimeZone("MST"));
+ assertEquals("06:32:01-07:00", DateTimeUtils.calendarToXSDTimeString(cal));
+ }
+
+ @Test
+ public void testCalendarToXSDTimeString_2() throws Exception {
+ Calendar cal = createCalendar(1984, Calendar.MARCH, 22, 14, 32, 1, 500, "GMT+01:00");
+ assertEquals("14:32:01.500+01:00", DateTimeUtils.calendarToXSDTimeString(cal));
+ // Different timezone - moves the cal point-in-time.
+ cal.setTimeZone(TimeZone.getTimeZone("MST"));
+ assertEquals("06:32:01.500-07:00", DateTimeUtils.calendarToXSDTimeString(cal));
+ }
+
+ private static Calendar createCalendar(int year, int month, int dayOfMonth, int hourOfDay,
+ int minute, int second, int milli, String tz) {
+ GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone(tz)) ;
+ cal.set(year, month, dayOfMonth, hourOfDay, minute, second) ;
+ cal.set(Calendar.MILLISECOND, milli) ;
+ return cal ;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestFileOps.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestFileOps.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestFileOps.java
new file mode 100644
index 0000000..92538f7
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestFileOps.java
@@ -0,0 +1,78 @@
+/*
+ * 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.lib;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.FileOps ;
+import org.apache.jena.atlas.lib.Tuple ;
+import org.junit.Test ;
+
+public class TestFileOps extends BaseTest
+{
+ /*
+ * t("") ;
+ t("/a/b/c") ;
+ t("/aa/bb/cc.ext") ;
+ t("cc.ext") ;
+ t("/cc.ext") ;
+ t("/") ;
+ t("xyz") ;
+ t("xyz/") ;
+ */
+
+ static void test(String fn, String path, String basename, String ext)
+ {
+ Tuple<String> t = FileOps.splitDirBaseExt(fn) ;
+ assertEquals(path, t.get(0)) ;
+ assertEquals(basename, t.get(1)) ;
+ assertEquals(ext, t.get(2)) ;
+
+ if ( basename != null )
+ assertEquals(basename, FileOps.basename(fn)) ;
+ if ( ext != null )
+ assertEquals(ext, FileOps.extension(fn)) ;
+ }
+
+ @Test public void split01()
+ { test("/aa/bb/cc.ext", "/aa/bb", "cc", "ext") ; }
+
+ @Test public void split02()
+ { test("/a/b/c", "/a/b", "c", null) ; }
+
+ @Test public void split03()
+ { test("cc.ext", null, "cc", "ext") ; }
+
+ @Test public void split04()
+ { test("/cc.ext", "", "cc", "ext") ; }
+
+ @Test public void split05()
+ { test("/", "", "", null) ; }
+
+ @Test public void split06()
+ { test("", null, "", null) ; }
+
+ @Test public void split07()
+ { test("xyz", null, "xyz", null) ; }
+
+ @Test public void split08()
+ { test("/xyz", "", "xyz", null) ; }
+
+ @Test public void split09()
+ { test("xyz/", "xyz", "", null) ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestFilenameProcessing.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestFilenameProcessing.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestFilenameProcessing.java
new file mode 100644
index 0000000..7782c55
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestFilenameProcessing.java
@@ -0,0 +1,136 @@
+/*
+ * 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.lib;
+
+import java.io.File ;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+
+public class TestFilenameProcessing extends BaseTest
+{
+ // See also TestFunction2 for tests for encode_for_uri
+ @Test public void encode_1() { encodeComponent("abc", "abc") ; }
+ @Test public void encode_2() { encodeComponent("", "") ; }
+ @Test public void encode_3() { encodeComponent(":/", "%3A%2F") ; }
+
+ // ---- Main tests.
+ // Portablility
+
+ private static String cwd = new File(".").getAbsolutePath() ;
+ // Without trailing slash.
+ static { cwd = cwd.substring(0, cwd.length()-2) ; }
+
+ @Test public void fileIRI_1()
+ {
+ String uri = testFileIRI("D.ttl") ;
+ assertTrue(uri.endsWith("D.ttl")) ;
+ }
+
+ @Test public void fileIRI_2()
+ {
+ String uri = testFileIRI("file:/D.ttl") ;
+ assertTrue(uri.endsWith("D.ttl")) ;
+ }
+
+ @Test public void fileIRI_3()
+ {
+ String uri = testFileIRI("file://D.ttl") ;
+ assertTrue(uri.endsWith("D.ttl")) ;
+ }
+
+ @Test public void fileIRI_4()
+ {
+ String iri = testFileIRI("file:///D.ttl") ;
+ // Even on windows, this is used as-is so no drive letter.
+ assertEquals("file:///D.ttl", iri) ;
+ }
+
+ private static String testFileIRI(String fn)
+ {
+ String uri1 = IRILib.filenameToIRI(fn) ;
+ assertTrue(uri1.startsWith("file:///")) ;
+ String uri2 = IRILib.filenameToIRI(uri1) ;
+ assertEquals(uri1, uri2) ;
+ return uri1 ;
+ }
+
+
+ @Test public void fileURL_1() { assertNotEquals(cwd, "") ; assertNotNull(cwd) ; filenameToIRI("abc", "file://"+cwd+"/abc" ) ; }
+
+ @Test public void fileURL_2() { filenameToIRI("/abc", "file:///abc" ) ; }
+
+ static boolean isWindows = File.pathSeparator.equals(";") ;
+
+
+ @Test public void fileURL_3()
+ {
+ if ( isWindows )
+ filenameToIRI("c:/Program File/App File", "file:///c:/Program%20File/App%20File") ;
+ else
+ filenameToIRI("/Program File/App File", "file:///Program%20File/App%20File") ;
+ }
+
+ @Test public void fileURL_4()
+ {
+ if ( isWindows )
+ filenameToIRI("c:/Program File/App Dir/", "file:///c:/Program%20File/App%20Dir/") ;
+ else
+ filenameToIRI("/Program File/App Dir/", "file:///Program%20File/App%20Dir/") ;
+ }
+
+ @Test public void fileURL_5()
+ {
+ if ( isWindows )
+ filenameToIRI("c:\\Windows\\Path", "file:///c:/Windows/Path") ;
+ else
+ filenameToIRI("c:\\Windows\\Path", "file://"+cwd+"/c:%5CWindows%5CPath") ;
+
+ }
+
+ @Test public void fileURL_6() { filenameToIRI("~user", "file://"+cwd+"/~user") ; }
+ @Test public void fileURL_7() { filenameToIRI(".", "file://"+cwd) ; }
+
+ @Test public void fileURL_10() { filenameToIRI("file:abc", "file://"+cwd+"/abc" ) ; }
+ @Test public void fileURL_11() { filenameToIRI("file:/abc", "file:///abc" ) ; }
+ @Test public void fileURL_12() { filenameToIRI("file:", "file://"+cwd ) ; }
+
+ @Test public void fileURL_13() { filenameToIRI("file:.", "file://"+cwd+"" ) ; }
+ @Test public void fileURL_14() {
+ String x = cwd ;
+ if ( isWindows )
+ x = x.replace('\\', '/') ;
+ x = cwd.replaceAll("/[^/]*$", "") ;
+ filenameToIRI("file:..", "file://"+x ) ;
+ }
+
+
+ private static void encodeComponent(String string, String result)
+ {
+ String r = IRILib.encodeUriComponent(string) ;
+ assertEquals(result, r) ;
+ }
+
+ private static void filenameToIRI(String string, String result)
+ {
+ String r = IRILib.filenameToIRI(string) ;
+ assertEquals(result, r) ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestHex.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestHex.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestHex.java
new file mode 100644
index 0000000..e092e60
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestHex.java
@@ -0,0 +1,81 @@
+/*
+ * 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.lib;
+
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.Hex ;
+import org.junit.Test ;
+
+public class TestHex extends BaseTest
+{
+ @Test public void hex_01()
+ {
+ byte[] b = new byte[16] ;
+ test(0L, 0, b, 16) ;
+ }
+
+ @Test public void hex_02()
+ {
+ byte[] b = new byte[16] ;
+ test(1L, 0, b, 16) ;
+ }
+
+ @Test public void hex_03()
+ {
+ byte[] b = new byte[16] ;
+ test(Long.MAX_VALUE, 0, b, 16) ;
+ }
+
+ @Test public void hex_04()
+ {
+ byte[] b = new byte[16] ;
+ test(Long.MIN_VALUE, 0, b, 16) ;
+ }
+
+ @Test public void hex_05()
+ {
+ byte[] b = new byte[16] ;
+ // -1L
+ test(0xFFFFFFFFFFFFFFFFL, 0, b, 16) ;
+ }
+
+ @Test public void hex_06()
+ {
+ byte[] b = new byte[16] ;
+ test(-1L, 0, b, 16) ;
+ }
+
+ private static void test(long value, int idx, byte[] b, int width)
+ {
+ int x = Hex.formatUnsignedLongHex(b, idx, value, width) ;
+ assertEquals(width, x) ;
+ for ( int i = 0 ; i < width ; i++ )
+ {
+ int v = b[i] ;
+ if ( v >= '0' && v <= '9' ) continue ;
+ if ( v >= 'a' && v <= 'f' ) continue ;
+ if ( v >= 'A' && v <= 'F' ) continue ;
+ fail(String.format("Not a hex digit: %02X",b[i])) ;
+ }
+
+ long v = Hex.getLong(b, idx) ;
+ assertEquals(value, v) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestListUtils.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestListUtils.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestListUtils.java
new file mode 100644
index 0000000..ccaa56a
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestListUtils.java
@@ -0,0 +1,79 @@
+/*
+ * 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.lib;
+
+import static org.apache.jena.atlas.lib.ListUtils.unique ;
+
+import java.util.ArrayList ;
+import java.util.Arrays ;
+import java.util.List ;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+
+public class TestListUtils extends BaseTest
+{
+ @Test public void list01()
+ {
+ List<Integer> x = Arrays.asList(1,2,3) ;
+ x = unique(x) ;
+ assertEquals(3, x.size()) ;
+ test(x, 1,2,3) ;
+ }
+
+ @Test public void list02()
+ {
+ List<Integer> x = Arrays.asList(1,2,3,1,3,2) ;
+ x = unique(x) ;
+ assertEquals(3, x.size()) ;
+ test(x, 1,2,3) ;
+ }
+
+ @Test public void list03()
+ {
+ List<Integer> x = new ArrayList<>() ;
+ x = unique(x) ;
+ assertEquals(0, x.size()) ;
+ test(x) ;
+ }
+
+ @Test public void list04()
+ {
+ List<Integer> x = Arrays.asList(99) ;
+ x = unique(x) ;
+ assertEquals(1, x.size()) ;
+ test(x, 99) ;
+ }
+
+ @Test public void list05()
+ {
+ List<Integer> x = Arrays.asList(1,1,2,3,1,1,3) ;
+ x = unique(x) ;
+ assertEquals(3, x.size()) ;
+ test(x, 1,2,3) ;
+ }
+
+ private void test(List<Integer> x, int... args)
+ {
+ assertEquals(args.length, x.size()) ;
+
+ for ( int i = 0; i < args.length ; i++ )
+ assertEquals(args[i], x.get(i).intValue()) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestMultiSet.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestMultiSet.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestMultiSet.java
new file mode 100644
index 0000000..477386b
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestMultiSet.java
@@ -0,0 +1,143 @@
+/*
+ * 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.lib;
+
+import java.util.Arrays ;
+import java.util.Collections ;
+import java.util.List ;
+
+import org.apache.jena.atlas.iterator.Iter ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.MultiSet ;
+import org.junit.Test ;
+
+
+public class TestMultiSet extends BaseTest
+{
+ @Test public void multiSet_01()
+ {
+ MultiSet<String> x = new MultiSet<>() ;
+ assertTrue(x.isEmpty()) ;
+ assertEquals(0, x.count("A")) ;
+ }
+
+ @Test public void multiSet_02()
+ {
+ MultiSet<String> x = new MultiSet<>() ;
+ x.add("A") ;
+ assertFalse(x.isEmpty()) ;
+ assertEquals(1, x.count("A") ) ;
+ x.add("A") ;
+ assertEquals(2, x.count("A") ) ;
+ }
+
+ @Test public void multiSet_03()
+ {
+ MultiSet<String> x = new MultiSet<>() ;
+ x.add("A") ;
+ x.add("A") ;
+ x.remove("A") ;
+ assertEquals(1, x.count("A") ) ;
+ assertTrue(x.contains("A")) ;
+ x.remove("A") ;
+ assertEquals(0, x.count("A") ) ;
+ assertFalse(x.contains("A")) ;
+ }
+
+ @Test public void multiSet_04()
+ {
+ String[] data = { } ;
+ iterTest(data) ;
+ }
+
+
+ @Test public void multiSet_05()
+ {
+ String[] data = { "A" } ;
+ iterTest(data) ;
+ }
+
+ @Test public void multiSet_06()
+ {
+ String[] data = { "A", "B", "C" } ;
+ iterTest(data) ;
+ }
+
+
+ @Test public void multiSet_07()
+ {
+ String[] data = { "A", "B", "C", "A" } ;
+ iterTest(data) ;
+ }
+
+ @Test public void multiSet_08()
+ {
+ String[] data = { } ;
+ MultiSet<String> x = add(data) ;
+ assertEquals(0, x.size()) ;
+ }
+
+ @Test public void multiSet_09()
+ {
+ String[] data = { "A", "A" } ;
+ MultiSet<String> x = add(data) ;
+ assertEquals(2, x.size()) ;
+ }
+
+ @Test public void multiSet_10()
+ {
+ String[] data = { "A", "A" } ;
+ MultiSet<String> x = add(data) ;
+ x.remove("A") ;
+ assertEquals(1, x.size()) ;
+ x.remove("A") ;
+ assertEquals(0, x.size()) ;
+ x.remove("A") ;
+ assertEquals(0, x.size()) ;
+ }
+
+ @Test public void multiSet_11()
+ {
+ String[] data = { "A", "A" } ;
+ MultiSet<String> x = add(data) ;
+ long c = Iter.count(x.elements()) ;
+ assertEquals(1, c) ;
+ }
+
+ private static MultiSet<String> add(String[] data)
+ {
+ MultiSet<String> x = new MultiSet<>() ;
+ for ( String str : data )
+ x.add(str) ;
+ return x ;
+ }
+
+ private static void iterTest(String[] data)
+ {
+ List<String> expected = Arrays.asList(data) ;
+ MultiSet<String> x = new MultiSet<>() ;
+ for ( String str : data )
+ x.add(str) ;
+ List<String> actual = Iter.toList(x.iterator()) ;
+ Collections.sort(expected) ;
+ Collections.sort(actual) ;
+ assertEquals(expected, actual) ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestNumberUtils.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestNumberUtils.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestNumberUtils.java
new file mode 100644
index 0000000..62c93da
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestNumberUtils.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.atlas.lib;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.NumberUtils ;
+import org.junit.Test ;
+
+public class TestNumberUtils extends BaseTest
+{
+ @Test public void int_format_01() { testInt(1, 1, "1") ; }
+
+ @Test public void int_format_02() { testInt(1, 2, "01") ; }
+
+ @Test public void int_format_03() { testInt(0, 1, "0") ; }
+
+ @Test public void int_format_04() { testInt(0, 2, "00") ; }
+
+ @Test public void int_format_05() { testInt(-1, 2, "-1") ; }
+
+ @Test public void int_format_06() { testInt(-1, 3, "-01") ; }
+
+
+ @Test public void int_format_11() { testSigned(1, 2, "+1") ; }
+
+ @Test public void int_format_12() { testSigned(1, 3, "+01") ; }
+
+ @Test public void int_format_13() { testSigned(0, 2, "+0") ; }
+
+ @Test public void int_format_14() { testSigned(0, 3, "+00") ; }
+
+ @Test public void int_format_15() { testSigned(-1, 2, "-1") ; }
+
+ @Test public void int_format_16() { testSigned(-1, 3, "-01") ; }
+
+ @Test public void int_format_21() { testInt(1, "1") ; }
+
+ @Test public void int_format_22() { testInt(0, "0") ; }
+
+ @Test public void int_format_23() { testInt(-1, "-1") ; }
+
+ @Test public void int_format_24() { testInt(10, "10") ; }
+
+ @Test public void int_format_25() { testInt(100, "100") ; }
+
+ @Test public void int_format_26() { testInt(-10, "-10") ; }
+
+ @Test public void int_format_27() { testInt(-100, "-100") ; }
+
+
+ @Test public void int_format_31() { testUnsigned(1, 2, "01") ; }
+
+ @Test public void int_format_32() { testUnsigned(1, 1, "1") ; }
+
+ @Test public void int_format_33() { testUnsigned(0, 1, "0") ; }
+
+
+ private static void testInt(int value, String expected)
+ {
+ StringBuilder sb = new StringBuilder() ;
+ NumberUtils.formatInt(sb, value) ;
+ String result = sb.toString();
+ assertEquals(expected, result) ;
+ }
+
+ private static void testInt(int value, int width, String expected)
+ {
+ StringBuilder sb = new StringBuilder() ;
+ NumberUtils.formatInt(sb, value, width) ;
+ String result = sb.toString();
+ assertEquals(expected, result) ;
+ }
+
+ private static void testSigned(int value, int width, String expected)
+ {
+ StringBuilder sb = new StringBuilder() ;
+ NumberUtils.formatSignedInt(sb, value, width) ;
+ String result = sb.toString();
+ assertEquals(expected, result) ;
+ }
+
+ private static void testUnsigned(int value, int width, String expected)
+ {
+ StringBuilder sb = new StringBuilder() ;
+ NumberUtils.formatUnsignedInt(sb, value, width) ;
+ String result = sb.toString();
+ assertEquals(expected, result) ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestRefLong.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestRefLong.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestRefLong.java
new file mode 100644
index 0000000..88e683a
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestRefLong.java
@@ -0,0 +1,70 @@
+/*
+ * 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.lib;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.RefLong ;
+import org.junit.Test ;
+
+
+public class TestRefLong extends BaseTest
+{
+ @Test public void ref_01()
+ {
+ RefLong ref1 = new RefLong() ;
+ assertEquals(0, ref1.value()) ;
+ RefLong ref2 = new RefLong() ;
+ assertNotSame(ref1, ref2) ;
+ }
+
+ @Test public void ref_02()
+ {
+ RefLong ref = new RefLong() ;
+ assertEquals(0, ref.value()) ;
+ ref.inc() ;
+ assertEquals(1, ref.value()) ;
+ ref.dec() ;
+ assertEquals(0, ref.value()) ;
+ }
+
+ @Test public void ref_03()
+ {
+ RefLong ref = new RefLong(99) ;
+ assertEquals(99, ref.value()) ;
+ long x = ref.incAndGet() ;
+ assertEquals(100, x) ;
+ assertEquals(100, ref.value()) ;
+ x = ref.getAndInc() ;
+ assertEquals(100, x) ;
+ assertEquals(101, ref.value()) ;
+ }
+
+ @Test public void ref_04()
+ {
+ RefLong ref = new RefLong(99) ;
+ assertEquals(99, ref.value()) ;
+ long x = ref.decAndGet() ;
+ assertEquals(98, x) ;
+ assertEquals(98, ref.value()) ;
+ x = ref.getAndDec() ;
+ assertEquals(98, x) ;
+ assertEquals(97, ref.value()) ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestReverseComparator.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestReverseComparator.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestReverseComparator.java
new file mode 100644
index 0000000..80b9c0d
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestReverseComparator.java
@@ -0,0 +1,91 @@
+/*
+ * 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.lib;
+
+
+import java.util.ArrayList ;
+import java.util.Arrays ;
+import java.util.Collections ;
+import java.util.Comparator ;
+import java.util.List ;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.ReverseComparator ;
+import org.junit.Test ;
+
+public class TestReverseComparator extends BaseTest
+{
+ static Comparator<String> normal = new Comparator<String>()
+ {
+ @Override
+ public int compare(String o1, String o2)
+ {
+ return o1.compareTo(o2);
+ }
+ };
+
+ static Comparator<String> reverse = new ReverseComparator<>(normal);
+
+
+ static Comparator<String> maxMin = new Comparator<String>()
+ {
+ @Override
+ public int compare(String o1, String o2)
+ {
+ int value = o1.compareTo(o2);
+ if (value > 0)
+ return Integer.MAX_VALUE;
+ else if (value < 0)
+ return Integer.MIN_VALUE;
+ else
+ return 0;
+ }
+ };
+
+ static Comparator<String> reverseMaxMin = new ReverseComparator<>(maxMin);
+
+ static List<String> items = Arrays.asList("a", "b", "c", "d");
+ static List<String> itemsReverse = Arrays.asList("d", "c", "b", "a");
+
+ @Test public void reverse_01()
+ {
+ List<String> modified = new ArrayList<>(items);
+ Collections.sort(modified, reverse);
+
+ test(itemsReverse, modified);
+ }
+
+ @Test public void reverse_02()
+ {
+ List<String> modified = new ArrayList<>(items);
+ Collections.sort(modified, reverseMaxMin);
+
+ test(itemsReverse, modified);
+ }
+
+ private void test(List<?> expected, List<?> actual)
+ {
+ assertEquals(expected.size(), actual.size());
+
+ for (int i=0; i<expected.size(); i++)
+ {
+ assertEquals(expected.get(i), actual.get(i)) ;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestSetUtils.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestSetUtils.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestSetUtils.java
new file mode 100644
index 0000000..d147262
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestSetUtils.java
@@ -0,0 +1,146 @@
+/*
+ * 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.lib;
+
+import static org.apache.jena.atlas.lib.ListUtils.asList ;
+
+import java.util.HashSet ;
+import java.util.List ;
+import java.util.Set ;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.SetUtils ;
+import org.junit.Test ;
+
+public class TestSetUtils extends BaseTest
+{
+ @Test public void set01()
+ {
+ Set<Integer> x = set(1,2,3) ;
+ test(x,1,2,3) ;
+ }
+
+ @Test public void set02()
+ {
+ Set<Integer> x1 = set(1,2,3) ;
+ Set<Integer> x2 = set(1,2,3) ;
+ Set<Integer> x3 = SetUtils.intersection(x1, x2) ;
+ test(x3, 1,2,3) ;
+ x3 = SetUtils.intersection(x2, x1) ;
+ test(x3, 1,2,3) ;
+ }
+
+ @Test public void set03()
+ {
+ Set<Integer> x1 = set(1,2,3) ;
+ Set<Integer> x2 = set(2,9) ;
+ Set<Integer> x3 = SetUtils.intersection(x1, x2) ;
+ test(x3, 2) ;
+ x3 = SetUtils.intersection(x2, x1) ;
+ test(x3, 2) ;
+ }
+
+ @Test public void set04()
+ {
+ Set<Integer> x1 = set(1,2,3) ;
+ Set<Integer> x2 = set(6,7,8) ;
+ Set<Integer> x3 = SetUtils.intersection(x1, x2) ;
+ test(x3) ;
+ x3 = SetUtils.intersection(x2, x1) ;
+ test(x3) ;
+ }
+
+ @Test public void set05()
+ {
+ Set<Integer> x1 = set(1,2,3) ;
+ Set<Integer> x2 = set(1,2,3) ;
+ Set<Integer> x3 = SetUtils.union(x1, x2) ;
+ test(x3, 1,2,3) ;
+ x3 = SetUtils.union(x2, x1) ;
+ test(x3, 1,2,3) ;
+ }
+
+ @Test public void set06()
+ {
+ Set<Integer> x1 = set(1,2,3) ;
+ Set<Integer> x2 = set(2,9) ;
+ Set<Integer> x3 = SetUtils.union(x1, x2) ;
+ test(x3, 1,2,3,9) ;
+ x3 = SetUtils.union(x2, x1) ;
+ test(x3, 1,2,3,9) ;
+ }
+
+ @Test public void set07()
+ {
+ Set<Integer> x1 = set(1,2,3) ;
+ Set<Integer> x2 = set() ;
+ Set<Integer> x3 = SetUtils.union(x1, x2) ;
+ test(x3,1,2,3) ;
+ x3 = SetUtils.union(x2, x1) ;
+ test(x3,1,2,3) ;
+ }
+
+ @Test public void set08()
+ {
+ Set<Integer> x1 = set(1,2,3) ;
+ Set<Integer> x2 = set() ;
+ Set<Integer> x3 = SetUtils.difference(x1, x2) ;
+ test(x3,1,2,3) ;
+ x3 = SetUtils.difference(x2, x1) ;
+ test(x3) ;
+ }
+
+ @Test public void set09()
+ {
+ Set<Integer> x1 = set(1,2,3) ;
+ Set<Integer> x2 = set(3) ;
+ Set<Integer> x3 = SetUtils.difference(x1, x2) ;
+ test(x3,1,2) ;
+ x3 = SetUtils.difference(x2, x1) ;
+ test(x3) ;
+ }
+
+ @Test public void set10()
+ {
+ Set<Integer> x1 = set(1,2,3) ;
+ Set<Integer> x2 = set(4,5,6) ;
+ Set<Integer> x3 = SetUtils.difference(x1, x2) ;
+ test(x3,1,2,3) ;
+ x3 = SetUtils.difference(x2, x1) ;
+ test(x3,4,5,6) ;
+ }
+
+ // --------
+
+ private static Set<Integer> set(int... values)
+ {
+ return new HashSet<>(asList(values)) ;
+ }
+
+ private void test(Set<Integer> x, int...values)
+ {
+ List<Integer> y = asList(values) ;
+ assertEquals(y.size(), x.size()) ;
+
+ for ( Integer aY : y )
+ {
+ assertTrue( x.contains( aY ) );
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestStrUtils.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestStrUtils.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestStrUtils.java
new file mode 100644
index 0000000..ff1e8c6
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestStrUtils.java
@@ -0,0 +1,59 @@
+/*
+ * 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.lib;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.StrUtils ;
+import org.junit.Test ;
+
+public class TestStrUtils extends BaseTest
+{
+ static char marker = '_' ;
+ static char esc[] = { ' ' , '_' } ;
+
+ static void test(String x)
+ {
+ test(x, null) ;
+ }
+
+ static void test(String x, String z)
+ {
+ String y = StrUtils.encodeHex(x, marker, esc) ;
+ if ( z != null )
+ assertEquals(z, y) ;
+ String x2 = StrUtils.decodeHex(y, marker) ;
+ assertEquals(x, x2) ;
+ }
+
+ @Test public void enc01() { test("abc") ; }
+
+ @Test public void enc02() { test("") ; }
+
+ @Test public void enc03() { test("_", "_5F" ) ; }
+
+ @Test public void enc04() { test(" ", "_20" ) ; }
+
+ @Test public void enc05() { test("_ _", "_5F_20_5F" ) ; }
+
+ @Test public void enc06() { test("_5F", "_5F5F" ) ; }
+
+ @Test public void enc07() { test("_2") ; }
+
+ @Test public void enc08() { test("AB_CD", "AB_5FCD") ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestTrie.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestTrie.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestTrie.java
new file mode 100644
index 0000000..1cb9e2e
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestTrie.java
@@ -0,0 +1,346 @@
+/*
+ * 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.lib;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests for the {@link Trie} class
+ *
+ */
+public class TestTrie {
+
+ /**
+ * Add a single key value
+ */
+ @Test
+ public void trie_add_01() {
+ Trie<Integer> trie = new Trie<>();
+ trie.add("test", 123);
+ Assert.assertTrue(trie.contains("test"));
+ Assert.assertEquals((Integer) 123, trie.get("test"));
+ }
+
+ /**
+ * Add two key values
+ */
+ @Test
+ public void trie_add_02() {
+ Trie<Integer> trie = new Trie<>();
+ trie.add("test", 123);
+ trie.add("other", 456);
+ Assert.assertTrue(trie.contains("test"));
+ Assert.assertTrue(trie.contains("other"));
+ Assert.assertEquals((Integer) 123, trie.get("test"));
+ Assert.assertEquals((Integer) 456, trie.get("other"));
+ }
+
+ /**
+ * Replace an existing key value
+ */
+ @Test
+ public void trie_add_03() {
+ Trie<Integer> trie = new Trie<>();
+ trie.add("test", 123);
+ trie.add("test", 456);
+ Assert.assertTrue(trie.contains("test"));
+ Assert.assertEquals((Integer) 456, trie.get("test"));
+ }
+
+ /**
+ * Adding a null value is ignored
+ */
+ @Test
+ public void trie_add_04() {
+ Trie<Integer> trie = new Trie<>();
+ trie.add("test", null);
+ Assert.assertFalse(trie.contains("test"));
+ }
+
+ /**
+ * Adding a null key is permitted - provides access to root of Trie
+ */
+ @Test
+ public void trie_add_05() {
+ Trie<Integer> trie = new Trie<>();
+ trie.add(null, 123);
+ Assert.assertTrue(trie.contains(null));
+ Assert.assertEquals((Integer)123, trie.get(null));
+ }
+
+ /**
+ * Adding an empty key is permitted - provides access to root of Trie
+ */
+ @Test
+ public void trie_add_06() {
+ Trie<Integer> trie = new Trie<>();
+ trie.add("", 123);
+ Assert.assertTrue(trie.contains(""));
+ Assert.assertEquals((Integer)123, trie.get(""));
+ }
+
+ /**
+ * Test for non-existent key
+ */
+ @Test
+ public void trie_contains_01() {
+ Trie<Integer> trie = new Trie<>();
+ Assert.assertFalse(trie.contains("test"));
+ }
+
+ /**
+ * Test for keys with and without values required
+ */
+ @Test
+ public void trie_contains_02() {
+ Trie<Integer> trie = new Trie<>();
+ trie.add("test", 123);
+ Assert.assertTrue(trie.contains("test"));
+ Assert.assertTrue(trie.contains("test", true));
+ Assert.assertTrue(trie.contains("test", 123));
+
+ // Any prefix of an added key exists if we don't require it to have a
+ // value
+ Assert.assertFalse(trie.contains("t"));
+ Assert.assertTrue(trie.contains("t", false));
+ }
+
+ /**
+ * Test for non-existent null key
+ */
+ @Test
+ public void trie_contains_03() {
+ Trie<Integer> trie = new Trie<>();
+ Assert.assertFalse(trie.contains(null));
+ Assert.assertTrue(trie.contains(null, false));
+ }
+
+ /**
+ * Test for empty key
+ */
+ @Test
+ public void trie_contains_04() {
+ Trie<Integer> trie = new Trie<>();
+ Assert.assertFalse(trie.contains(""));
+ Assert.assertTrue(trie.contains("", false));
+ }
+
+ /**
+ * Removing a key value
+ */
+ @Test
+ public void trie_remove_01() {
+ Trie<Integer> trie = new Trie<>();
+ trie.add("test", 123);
+ Assert.assertTrue(trie.contains("test"));
+ Assert.assertEquals((Integer) 123, trie.get("test"));
+
+ // Removing does not fully remove the key it merely nulls the value
+ trie.remove("test");
+ Assert.assertFalse(trie.contains("test"));
+ Assert.assertTrue(trie.contains("test", false));
+ Assert.assertNull(trie.get("test"));
+ }
+
+ /**
+ * Removing a key value, removing a key which is a prefix of another leaves
+ * the other intact
+ */
+ @Test
+ public void trie_remove_02() {
+ Trie<Integer> trie = new Trie<>();
+ trie.add("test", 123);
+ trie.add("testing", 456);
+ Assert.assertTrue(trie.contains("test"));
+ Assert.assertEquals((Integer) 123, trie.get("test"));
+ Assert.assertTrue(trie.contains("testing"));
+ Assert.assertEquals((Integer) 456, trie.get("testing"));
+
+ // Removing does not fully remove the key it merely nulls the value
+ trie.remove("test");
+ Assert.assertFalse(trie.contains("test"));
+ Assert.assertTrue(trie.contains("test", false));
+ Assert.assertNull(trie.get("test"));
+
+ // It also does not remove any keys who had the removed key as a prefix
+ Assert.assertTrue(trie.contains("testing"));
+ Assert.assertEquals((Integer) 456, trie.get("testing"));
+ }
+
+ /**
+ * Test for removing null key - provides access to trie root
+ */
+ @Test
+ public void trie_remove_03() {
+ Trie<Integer> trie = new Trie<>();
+ trie.add(null, 123);
+ Assert.assertTrue(trie.contains(null));
+ Assert.assertEquals((Integer)123, trie.get(null));
+
+ trie.remove(null);
+ Assert.assertFalse(trie.contains(null));
+ }
+
+ /**
+ * Test for removing null key - provides access to trie root
+ */
+ @Test
+ public void trie_remove_04() {
+ Trie<Integer> trie = new Trie<>();
+ trie.add("", 123);
+ Assert.assertTrue(trie.contains(""));
+ Assert.assertEquals((Integer)123, trie.get(""));
+
+ trie.remove("");
+ Assert.assertFalse(trie.contains(""));
+ }
+
+ /**
+ * Test prefix search
+ */
+ @Test
+ public void trie_prefix_search_01() {
+ Trie<Integer> trie = new Trie<>();
+ trie.add("test", 123);
+ trie.add("testing", 456);
+
+ //Prefix search on "test" should return two values
+ List<Integer> matches = trie.prefixSearch("test");
+ Assert.assertEquals(2, matches.size());
+
+ //Prefix search on "testi" should return one value
+ matches = trie.prefixSearch("testi");
+ Assert.assertEquals(1, matches.size());
+
+ //Prefix search on "testingly" should return no values
+ matches = trie.prefixSearch("testingly");
+ Assert.assertEquals(0, matches.size());
+
+ //Prefix search on null key should give two values
+ matches = trie.prefixSearch(null);
+ Assert.assertEquals(2, matches.size());
+ }
+
+ /**
+ * Test partial search
+ */
+ @Test
+ public void trie_partial_search_01() {
+ Trie<Integer> trie = new Trie<>();
+ trie.add("test", 123);
+ trie.add("testing", 456);
+
+ //Partial search on "test" should return one values
+ List<Integer> matches = trie.partialSearch("test");
+ Assert.assertEquals(1, matches.size());
+
+ //Prefix search on "testi" should return one values
+ matches = trie.partialSearch("testi");
+ Assert.assertEquals(1, matches.size());
+
+ //Prefix search on "testingly" should return two values
+ matches = trie.partialSearch("testingly");
+ Assert.assertEquals(2, matches.size());
+
+ //Prefix search on null key should give no values
+ matches = trie.partialSearch(null);
+ Assert.assertEquals(0, matches.size());
+ }
+
+ /**
+ * Test longest match
+ */
+ @Test
+ public void trie_longest_match_01() {
+ Trie<Integer> trie = new Trie<>();
+ trie.add("test", 123);
+ trie.add("testing", 456);
+ Assert.assertTrue(trie.contains("test"));
+ Assert.assertTrue(trie.contains("testing"));
+
+ Assert.assertEquals((Integer)456, trie.longestMatch("testing"));
+ }
+
+ /**
+ * Test longest match
+ */
+ @Test
+ public void trie_longest_match_02() {
+ Trie<Integer> trie = new Trie<>();
+ trie.add("test", 123);
+ trie.add("testing", 456);
+
+ Assert.assertEquals((Integer)456, trie.longestMatch("testingly"));
+ }
+
+ /**
+ * Test longest match
+ */
+ @Test
+ public void trie_longest_match_03() {
+ Trie<Integer> trie = new Trie<>();
+ trie.add("test", 123);
+ trie.add("testing", 456);
+ trie.remove("testing");
+
+ Assert.assertEquals((Integer)123, trie.longestMatch("testing"));
+ }
+
+ /**
+ * Test shortest match
+ */
+ @Test
+ public void trie_shortest_match_01() {
+ Trie<Integer> trie = new Trie<>();
+ trie.add("test", 123);
+ trie.add("testing", 456);
+ Assert.assertTrue(trie.contains("test"));
+ Assert.assertTrue(trie.contains("testing"));
+
+ Assert.assertEquals((Integer)123, trie.shortestMatch("testing"));
+ }
+
+ /**
+ * Test shortest match
+ */
+ @Test
+ public void trie_shortest_match_02() {
+ Trie<Integer> trie = new Trie<>();
+ trie.add("test", 123);
+ trie.add("testing", 456);
+
+ Assert.assertEquals((Integer)123, trie.shortestMatch("testingly"));
+ }
+
+ /**
+ * Test shortest match
+ */
+ @Test
+ public void trie_shortest_match_03() {
+ Trie<Integer> trie = new Trie<>();
+ trie.add("test", 123);
+ trie.add("testing", 456);
+ trie.remove("test");
+
+ Assert.assertEquals((Integer)456, trie.shortestMatch("testing"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestXMLLib.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestXMLLib.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestXMLLib.java
new file mode 100644
index 0000000..cae99ef
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestXMLLib.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.atlas.lib;
+
+import org.apache.jena.atlas.lib.XMLLib ;
+import org.junit.Assert ;
+import org.junit.Test ;
+
+/** XML related functionality */
+public class TestXMLLib
+{
+ @Test public void ws_collapse_01() { test("abc", "abc") ; }
+ @Test public void ws_collapse_02() { test(" abc", "abc") ; }
+ @Test public void ws_collapse_03() { test(" abc ", "abc") ; }
+ @Test public void ws_collapse_04() { test(" a b c ", "a b c") ; }
+ @Test public void ws_collapse_05() { test("\babc", "\babc") ; }
+ @Test public void ws_collapse_06() { test("", "") ; }
+ @Test public void ws_collapse_07() { test(" ", "") ; }
+ @Test public void ws_collapse_08() { test(" \t\t\t\t\t\t\t ", "") ; }
+
+ // String.trim : "Returns a copy of the string, with leading and trailing whitespace omitted."
+ // but later says it trims anything <= 0x20. There are lots of control characters in x01-x1F.
+ // We only want to trim \n \r \t and space.
+
+ private static void test(String str1, String str2)
+ {
+ String result = XMLLib.WScollapse(str1) ;
+ Assert.assertEquals(str2, result) ;
+ }
+
+}
[3/9] jena git commit: Import of lib, io,
logging and iterator packages
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/logging/FmtLog.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/logging/FmtLog.java b/jena-base/src/main/java/org/apache/jena/atlas/logging/FmtLog.java
new file mode 100644
index 0000000..590c49e
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/logging/FmtLog.java
@@ -0,0 +1,162 @@
+/**
+ * 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.logging;
+
+import java.util.IllegalFormatException ;
+
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+/** Logging with String.format (which can be a expensive)
+ * The formatting operations are not designed specifically for performance,
+ * but they do delay forming strings for output
+ * until it is know that a log message is actually
+ * required by level setting.
+ *
+ * An odd effect is order of the arguments - vararg arguments must be last
+ * so the order is Logger/Thorwable?/Format/args.
+ *
+ * Also support: Class object instead of logger to help ad hoc usage.
+ */
+public class FmtLog {
+ /* Log at 'trace' level. */
+ public static void trace(Logger log, String fmt, Object...args) {
+ if ( log.isTraceEnabled() )
+ log.trace(format(fmt, args)) ;
+ }
+
+ /* Log at 'trace' level. */
+ public static void trace(Logger log, Throwable th, String fmt, Object...args) {
+ if ( log.isTraceEnabled() )
+ log.trace(format(fmt, args), th) ;
+ }
+
+ /* Log at 'trace' level. */
+ public static void trace(Class<?> cls, String fmt, Object...args) {
+ trace(log(cls), fmt, args) ;
+ }
+
+ /* Log at 'trace' level. */
+ public static void trace(Class<?> cls, Throwable th, String fmt, Object...args) {
+ trace(log(cls), th, fmt, args) ;
+ }
+
+ /* Log at 'debug' level */
+ public static void debug(Logger log, String fmt, Object...args) {
+ if ( log.isDebugEnabled() )
+ log.debug(format(fmt, args)) ;
+ }
+
+ /* Log at 'debug' level */
+ public static void debug(Logger log, Throwable th, String fmt, Object...args) {
+ if ( log.isDebugEnabled() )
+ log.debug(format(fmt, args), th) ;
+ }
+
+ /* Log at 'debug' level */
+ public static void debug(Class<?> cls, String fmt, Object...args) {
+ debug(log(cls), fmt, args) ;
+ }
+
+ /* Log at 'debug' level */
+ public static void debug(Class<?> cls, Throwable th, String fmt, Object...args) {
+ debug(log(cls), th, fmt, args) ;
+ }
+
+ /* Log at 'info' level */
+ public static void info(Logger log, String fmt, Object...args) {
+ if ( log.isInfoEnabled() )
+ log.info(format(fmt, args)) ;
+ }
+
+ /* Log at 'info' level */
+ public static void info(Logger log, Throwable th, String fmt, Object...args) {
+ if ( log.isInfoEnabled() )
+ log.info(format(fmt, args), th) ;
+ }
+
+ /* Log at 'info' level */
+ public static void info(Class<?> cls, String fmt, Object...args) {
+ info(log(cls), fmt, args) ;
+ }
+
+ /* Log at 'info' level */
+ public static void info(Class<?> cls, Throwable th, String fmt, Object...args) {
+ info(log(cls), th, fmt, args) ;
+ }
+
+ /* Log at 'warn' level */
+ public static void warn(Logger log, String fmt, Object...args) {
+ if ( log.isWarnEnabled() )
+ log.warn(format(fmt, args)) ;
+ }
+
+ /* Log at 'warn' level */
+ public static void warn(Logger log, Throwable th, String fmt, Object...args) {
+ if ( log.isWarnEnabled() )
+ log.warn(format(fmt, args), th) ;
+ }
+
+ /* Log at 'warn' level */
+ public static void warn(Class<?> cls, String fmt, Object...args) {
+ warn(log(cls), fmt, args) ;
+ }
+
+ /* Log at 'warn' level */
+ public static void warn(Class<?> cls, Throwable th, String fmt, Object...args) {
+ warn(log(cls), th, fmt, args) ;
+ }
+
+ /* Log at 'error' level */
+ public static void error(Logger log, String fmt, Object...args) {
+ if ( log.isErrorEnabled() )
+ log.error(format(fmt, args)) ;
+ }
+
+ /* Log at 'error' level */
+ public static void error(Logger log, Throwable th, String fmt, Object...args) {
+ if ( log.isErrorEnabled() )
+ log.error(format(fmt, args), th) ;
+ }
+
+ /* Log at 'error' level */
+ public static void error(Class<?> cls, String fmt, Object...args) {
+ error(log(cls), fmt, args) ;
+ }
+
+ /* Log at 'error' level */
+ public static void error(Class<?> cls, Throwable th, String fmt, Object...args) {
+ error(log(cls), th, fmt, args) ;
+ }
+
+
+ private static String format(String fmt, Object[] args) {
+ try {
+ return String.format(fmt, args) ;
+ } catch (IllegalFormatException ex) {
+ // return something, however grotty.
+ return fmt+" "+args ;
+ }
+ }
+
+ private static Logger log(Class<?> cls) {
+ return LoggerFactory.getLogger(cls) ;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/logging/Log.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/logging/Log.java b/jena-base/src/main/java/org/apache/jena/atlas/logging/Log.java
new file mode 100644
index 0000000..47783fc
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/logging/Log.java
@@ -0,0 +1,116 @@
+/*
+ * 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.logging ;
+
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+/* Simple wrappers and operations for convenient, non-time critical logging.
+ */
+public class Log {
+ private Log() {}
+
+ static public void info(String caller, String msg) {
+ log(caller).info(msg) ;
+ }
+
+ static public void info(Object caller, String msg) {
+ log(caller.getClass()).info(msg) ;
+ }
+
+ static public void info(Class<? > cls, String msg) {
+ log(cls).info(msg) ;
+ }
+
+ static public void info(Object caller, String msg, Throwable th) {
+ log(caller.getClass()).info(msg, th) ;
+ }
+
+ static public void info(Class<? > cls, String msg, Throwable th) {
+ log(cls).info(msg, th) ;
+ }
+
+ static public void debug(String caller, String msg) {
+ log(caller).debug(msg) ;
+ }
+
+ static public void debug(Object caller, String msg) {
+ log(caller.getClass()).debug(msg) ;
+ }
+
+ static public void debug(Class<? > cls, String msg) {
+ log(cls).debug(msg) ;
+ }
+
+ static public void debug(Object caller, String msg, Throwable th) {
+ log(caller.getClass()).debug(msg, th) ;
+ }
+
+ static public void debug(Class<? > cls, String msg, Throwable th) {
+ log(cls).debug(msg, th) ;
+ }
+
+ static public void warn(String caller, String msg) {
+ log(caller).warn(msg) ;
+ }
+
+ static public void warn(Object caller, String msg) {
+ warn(caller.getClass(), msg) ;
+ }
+
+ static public void warn(Class<? > cls, String msg) {
+ log(cls).warn(msg) ;
+ }
+
+ static public void warn(Object caller, String msg, Throwable th) {
+ warn(caller.getClass(), msg, th) ;
+ }
+
+ static public void warn(Class<? > cls, String msg, Throwable th) {
+ log(cls).warn(msg, th) ;
+ }
+
+ static public void fatal(Object caller, String msg) {
+ fatal(caller.getClass(), msg) ;
+ }
+
+ static public void fatal(Class<? > cls, String msg) {
+ log(cls).error(msg) ;
+ }
+
+ static public void fatal(Object caller, String msg, Throwable th) {
+ fatal(caller.getClass(), msg, th) ;
+ }
+
+ static public void fatal(Class<? > cls, String msg, Throwable th) {
+ log(cls).error(msg, th) ;
+ }
+
+ static public void fatal(String caller, String msg) {
+ log(caller).error(msg) ;
+ }
+
+ static private Logger log(Class<? > cls) {
+ return LoggerFactory.getLogger(cls) ;
+ }
+
+ static private Logger log(String loggerName) {
+ return LoggerFactory.getLogger(loggerName) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/logging/LogCtl.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/logging/LogCtl.java b/jena-base/src/main/java/org/apache/jena/atlas/logging/LogCtl.java
new file mode 100644
index 0000000..ad1adce
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/logging/LogCtl.java
@@ -0,0 +1,282 @@
+/**
+ * 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.logging;
+
+import java.io.* ;
+import java.util.Properties ;
+
+import org.apache.jena.atlas.AtlasException ;
+import org.apache.jena.atlas.lib.StrUtils ;
+import org.apache.log4j.PropertyConfigurator ;
+import org.apache.log4j.xml.DOMConfigurator ;
+import org.slf4j.Logger ;
+
+/** Setup and control of logging - needs access to log4j binaries */
+public class LogCtl {
+
+ /**
+ * Turn on a logger (all levels). Works for Log4j and Java logging as the
+ * logging provider to Apache common logging or slf4j.
+ */
+
+ static public void enable(Logger logger) {
+ enable(logger.getName()) ;
+ }
+
+ static public void enable(String logger) {
+ set(logger, "all") ;
+ }
+
+ static public void set(Logger logger, String level) {
+ set(logger.getName(), level) ;
+ }
+
+ /** Turn on a logger (specific level levels) */
+ static public void set(Class<? > logger, String level) {
+ set(logger.getName(), level) ;
+ }
+
+ static public void set(String logger, String level) {
+ org.apache.log4j.Level level1 = org.apache.log4j.Level.ALL ;
+ java.util.logging.Level level2 = java.util.logging.Level.ALL ;
+ if ( level.equalsIgnoreCase("info") ) {
+ level1 = org.apache.log4j.Level.INFO ;
+ level2 = java.util.logging.Level.INFO ;
+ }
+
+ if ( level.equalsIgnoreCase("debug") ) {
+ level1 = org.apache.log4j.Level.DEBUG ;
+ level2 = java.util.logging.Level.FINE ;
+ }
+
+ if ( level.equalsIgnoreCase("warn") ) {
+ level1 = org.apache.log4j.Level.WARN ;
+ level2 = java.util.logging.Level.WARNING ;
+ }
+ if ( level.equalsIgnoreCase("error") ) {
+ level1 = org.apache.log4j.Level.ERROR ;
+ level2 = java.util.logging.Level.SEVERE ;
+ }
+ logLevel(logger, level1, level2) ;
+ }
+
+ static public void logLevel(String logger, org.apache.log4j.Level level1, java.util.logging.Level level2) {
+ if ( level1 != null )
+ org.apache.log4j.LogManager.getLogger(logger).setLevel(level1) ;
+ if ( level2 != null )
+ java.util.logging.Logger.getLogger(logger).setLevel(level2) ;
+ }
+
+ /**
+ * Turn on a logger (all levels). Works for Log4j and Java logging as the
+ * logging provider to Apache common logging or slf4j.
+ */
+ static public void enable(Class<? > logger) {
+ org.apache.log4j.LogManager.getLogger(logger).setLevel(org.apache.log4j.Level.ALL) ;
+ java.util.logging.Logger.getLogger(logger.getName()).setLevel(java.util.logging.Level.ALL) ;
+ }
+
+ /**
+ * Turn on a logger (all levels). Works for Log4j and Java logging as the
+ * logging provider to Apache common logging or slf4j.
+ */
+ static public void disable(String logger) {
+ org.apache.log4j.LogManager.getLogger(logger).setLevel(org.apache.log4j.Level.OFF) ;
+ java.util.logging.Logger.getLogger(logger).setLevel(java.util.logging.Level.OFF) ;
+ }
+
+ /**
+ * Turn on a logger (all levels). Works for Log4j and Java logging as the
+ * logging provider to Apache common logging or slf4j.
+ */
+ static public void disable(Class<? > logger) {
+ org.apache.log4j.LogManager.getLogger(logger).setLevel(org.apache.log4j.Level.OFF) ;
+ java.util.logging.Logger.getLogger(logger.getName()).setLevel(java.util.logging.Level.OFF) ;
+ }
+
+ /**
+ * Set to info level. Works for Log4j and Java logging as the logging
+ * provider to Apache common logging or slf4j.
+ */
+ static public void setInfo(String logger) {
+ org.apache.log4j.LogManager.getLogger(logger).setLevel(org.apache.log4j.Level.INFO) ;
+ java.util.logging.Logger.getLogger(logger).setLevel(java.util.logging.Level.INFO) ;
+ }
+
+ /**
+ * Set to info level. Works for Log4j and Java logging as the logging
+ * provider to Apache common logging or slf4j.
+ */
+ static public void setInfo(Class<? > logger) {
+ org.apache.log4j.LogManager.getLogger(logger).setLevel(org.apache.log4j.Level.INFO) ;
+ java.util.logging.Logger.getLogger(logger.getName()).setLevel(java.util.logging.Level.INFO) ;
+ }
+
+ /**
+ * Set to warning level. Works for Log4j and Java logging as the logging
+ * provider to Apache common logging or slf4j.
+ */
+ static public void setWarn(String logger) {
+ org.apache.log4j.LogManager.getLogger(logger).setLevel(org.apache.log4j.Level.WARN) ;
+ java.util.logging.Logger.getLogger(logger).setLevel(java.util.logging.Level.WARNING) ;
+ }
+
+ /**
+ * Set to warning level. Works for Log4j and Java logging as the logging
+ * provider to Apache common logging or slf4j.
+ */
+ static public void setWarn(Class<? > logger) {
+ org.apache.log4j.LogManager.getLogger(logger).setLevel(org.apache.log4j.Level.WARN) ;
+ java.util.logging.Logger.getLogger(logger.getName()).setLevel(java.util.logging.Level.WARNING) ;
+ }
+
+ /**
+ * Set to error level. Works for Log4j and Java logging as the logging
+ * provider to Apache common logging or slf4j.
+ */
+ static public void setError(String logger) {
+ org.apache.log4j.LogManager.getLogger(logger).setLevel(org.apache.log4j.Level.ERROR) ;
+ java.util.logging.Logger.getLogger(logger).setLevel(java.util.logging.Level.SEVERE) ;
+ }
+
+ /**
+ * Set to error level. Works for Log4j and Java logging as the logging
+ * provider to Apache common logging or slf4j.
+ */
+ static public void setError(Class<? > logger) {
+ org.apache.log4j.LogManager.getLogger(logger).setLevel(org.apache.log4j.Level.ERROR) ;
+ java.util.logging.Logger.getLogger(logger.getName()).setLevel(java.util.logging.Level.SEVERE) ;
+ }
+
+ private static String log4Jsetup = StrUtils.strjoinNL
+ ("## Plain output to stdout",
+ "log4j.appender.jena.plain=org.apache.log4j.ConsoleAppender",
+ "log4j.appender.jena.plain.target=System.out",
+ "log4j.appender.jena.plain.layout=org.apache.log4j.PatternLayout",
+ "log4j.appender.jena.plain.layout.ConversionPattern=%m%n"
+ ,
+ "## Plain output with level, to stderr",
+ "log4j.appender.jena.plainlevel=org.apache.log4j.ConsoleAppender",
+ "log4j.appender.jena.plainlevel.target=System.err",
+ "log4j.appender.jena.plainlevel.layout=org.apache.log4j.PatternLayout",
+ "log4j.appender.jena.plainlevel.layout.ConversionPattern=%-5p %m%n"
+
+ , "## Everything", "log4j.rootLogger=INFO, jena.plainlevel",
+ "log4j.logger.com.hp.hpl.jena=WARN",
+ "log4j.logger.org.openjena=WARN",
+ "log4j.logger.org.apache.jena=WARN",
+ "log4j.logger.org.apache.jena.tdb.loader=INFO"
+
+ , "## Parser output"
+ , "log4j.additivity.org.apache.jena.riot=false"
+ , "log4j.logger.org.apache.jena.riot=INFO, jena.plainlevel ") ;
+ // ---- java.util.logging - because that's always present.
+ static String defaultProperties = StrUtils.strjoinNL
+ (
+ // Handlers - output
+ // All (comma
+ // separated)
+ // "handlers=java.util.logging.ConsoleHandler,org.apache.jena.atlas.logging.java.ConsoleHandlerStdout",
+
+ // Atlas.
+ "handlers=org.openjena.atlas.logging.java.ConsoleHandlerStdout",
+ "org.apache.atlas.jena.logging.java.ConsoleHandlerStdout.level=INFO",
+ "java.util.logging.ConsoleHandler.formatter=atlas.logging.java.TextFormatter"
+ ) ;
+
+ /**
+ * Set logging
+ * <ol>
+ * <li>Check for -Dlog4j.configuration.</li>
+ * <li>Looks for log4j.properties file in current directory.</li>
+ * </ol>
+ * Return true if we think Log4J is not initialized.
+ */
+
+ public static void setLog4j() {
+ if ( System.getProperty("log4j.configuration") == null ) {
+ String fn = "log4j.properties" ;
+ File f = new File(fn) ;
+ if ( f.exists() )
+ System.setProperty("log4j.configuration", "file:" + fn) ;
+ }
+ }
+
+ /** Set log4j properties (XML or properties file) */
+ public static void setLog4j(String filename) {
+ if ( filename.toLowerCase().endsWith(".xml") )
+ DOMConfigurator.configure(filename) ;
+ else
+ PropertyConfigurator.configure(filename) ;
+ }
+
+ /**
+ * Set logging, suitable for a command line application.
+ * If "log4j.configuration" not set, then use the built-in default,
+ * else just leave to log4j startup.
+ */
+ public static void setCmdLogging() {
+ setCmdLogging(log4Jsetup) ;
+ }
+
+ /**
+ * Set logging, suitable for a command line application.
+ * If "log4j.configuration" not set, then use the provided default
+ * (log4j properties syntax) else just leave to log4j startup.
+ */
+ public static void setCmdLogging(String defaultConfig) {
+ if (System.getProperty("log4j.configuration") == null )
+ resetLogging(defaultConfig) ;
+ }
+
+ public static void resetLogging(String config) {
+ Properties p = new Properties() ;
+ InputStream in = new ByteArrayInputStream(StrUtils.asUTF8bytes(config)) ;
+ try {
+ p.load(in) ;
+ } catch (IOException ex) {}
+ PropertyConfigurator.configure(p) ;
+ System.setProperty("log4j.configuration", "set") ;
+ }
+
+ public static void setJavaLogging() {
+ setJavaLogging("logging.properties") ;
+ }
+
+ public static void setJavaLogging(String file) {
+ try {
+ InputStream details = new FileInputStream(file) ;
+ java.util.logging.LogManager.getLogManager().readConfiguration(details) ;
+ } catch (Exception ex) {
+ throw new AtlasException(ex) ;
+ }
+ }
+
+ public static void setJavaLoggingDft() {
+ try {
+ InputStream details = new ByteArrayInputStream(defaultProperties.getBytes("UTF-8")) ;
+ java.util.logging.LogManager.getLogManager().readConfiguration(details) ;
+
+ } catch (Exception ex) {
+ throw new AtlasException(ex) ;
+ }
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/logging/ProgressLogger.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/logging/ProgressLogger.java b/jena-base/src/main/java/org/apache/jena/atlas/logging/ProgressLogger.java
new file mode 100644
index 0000000..344885d
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/logging/ProgressLogger.java
@@ -0,0 +1,133 @@
+/*
+ * 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.logging;
+
+import static org.apache.jena.atlas.lib.DateTimeUtils.* ;
+import org.apache.jena.atlas.lib.Timer ;
+import org.slf4j.Logger ;
+
+/** Progress monitor */
+public class ProgressLogger
+{
+ private final Logger log ;
+ private final long tickPoint ;
+ private final int superTick ;
+ private final Timer timer ;
+ private final String label ;
+
+ private long counterBatch = 0 ;
+ private long counterTotal = 0 ;
+
+ private long lastTime = 0 ;
+
+ public ProgressLogger(Logger log, String label, long tickPoint, int superTick)
+ {
+ this.log = log ;
+ this.label = label ;
+ this.tickPoint = tickPoint ;
+ this.superTick = superTick ;
+ this.timer = new Timer() ;
+ }
+
+ public void startMessage() {
+ print("Start:") ;
+ }
+
+ public void finishMessage() {
+ // Elapsed.
+ long timePoint = timer.getTimeInterval() ;
+
+ // *1000L is milli to second conversion
+ if ( timePoint != 0 ) {
+ double time = timePoint/1000.0 ;
+ long runAvgRate = (counterTotal * 1000L) / timePoint ;
+
+ print("Finished: %,d %s %.2fs (Avg: %,d)", counterTotal, label, time, runAvgRate) ;
+ }
+ else
+ print("Finished: %,d %s (Avg: ----)", counterTotal, label) ;
+ }
+
+ public void start()
+ {
+ timer.startTimer() ;
+ lastTime = 0 ;
+ }
+
+ public long finish()
+ {
+ long totalTime = timer.endTimer() ;
+ return totalTime ;
+ }
+
+ public long getTicks()
+ {
+ return counterTotal ;
+ }
+
+ public void tick()
+ {
+ counterBatch++ ;
+ counterTotal++ ;
+
+ if ( tickPoint(counterTotal, tickPoint) )
+ {
+ long timePoint = timer.readTimer() ;
+ long thisTime = timePoint - lastTime ;
+
+ // *1000L is milli to second conversion
+ if ( thisTime != 0 && timePoint != 0 ) {
+ long batchAvgRate = (counterBatch * 1000L) / thisTime;
+ long runAvgRate = (counterTotal * 1000L) / timePoint ;
+ print("Add: %,d %s (Batch: %,d / Avg: %,d)", counterTotal, label, batchAvgRate, runAvgRate) ;
+ } else {
+ print("Add: %,d %s (Batch: ---- / Avg: ----)", counterTotal, label) ;
+ }
+
+ lastTime = timePoint ;
+
+ if ( tickPoint(counterTotal, superTick*tickPoint) )
+ elapsed(timePoint) ;
+ counterBatch = 0 ;
+ lastTime = timePoint ;
+ }
+ }
+
+ private void elapsed(long timerReading)
+ {
+ float elapsedSecs = timerReading/1000F ;
+ print(" Elapsed: %,.2f seconds [%s]", elapsedSecs, nowAsString()) ;
+ }
+
+ /** Print a message in the form for this ProgressLogger */
+ public void print(String fmt, Object...args)
+ {
+ if ( log != null && log.isInfoEnabled() )
+ {
+ String str = String.format(fmt, args) ;
+ log.info(str) ;
+ }
+ }
+
+ static boolean tickPoint(long counter, long quantum)
+ {
+ return counter%quantum == 0 ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/logging/java/ConsoleHandlerStdout.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/logging/java/ConsoleHandlerStdout.java b/jena-base/src/main/java/org/apache/jena/atlas/logging/java/ConsoleHandlerStdout.java
new file mode 100644
index 0000000..7bfab7e
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/logging/java/ConsoleHandlerStdout.java
@@ -0,0 +1,75 @@
+/*
+ * 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.logging.java;
+
+import java.util.logging.Formatter ;
+import java.util.logging.Handler ;
+import java.util.logging.LogManager ;
+import java.util.logging.LogRecord ;
+
+
+public class ConsoleHandlerStdout extends Handler
+{
+
+ private void configure()
+ {
+ LogManager manager = LogManager.getLogManager();
+ String cname = getClass().getName();
+
+ String cls = manager.getProperty(cname+".formatter") ;
+ Formatter fmt = null ;
+
+ try {
+ if (cls != null) {
+ Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(cls);
+ fmt = (Formatter) clz.newInstance();
+ }
+ } catch (Exception ex) {
+ // We got one of a variety of exceptions in creating the
+ // class or creating an instance.
+ // Drop through.
+ }
+ if ( fmt == null )
+ fmt = new TextFormatter() ;
+ setFormatter(fmt) ;
+ }
+
+ public ConsoleHandlerStdout()
+ {
+ configure() ;
+ }
+
+ @Override
+ public void close() throws SecurityException
+ {}
+
+ @Override
+ public void flush()
+ { System.out.flush(); }
+
+ @Override
+ public void publish(LogRecord record)
+ {
+ if ( ! super.isLoggable(record) )
+ return ;
+ String s = getFormatter().format(record) ;
+ System.out.print(s) ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/logging/java/TextFormatter.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/logging/java/TextFormatter.java b/jena-base/src/main/java/org/apache/jena/atlas/logging/java/TextFormatter.java
new file mode 100644
index 0000000..3e97942
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/logging/java/TextFormatter.java
@@ -0,0 +1,53 @@
+/*
+ * 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.logging.java;
+
+import java.text.MessageFormat ;
+import java.util.Date ;
+import java.util.logging.Formatter ;
+import java.util.logging.LogRecord ;
+
+/** A pattern-like log formatter */
+public class TextFormatter extends Formatter
+{
+ @Override
+ public String format(LogRecord record) {
+ String loggerName = record.getLoggerName();
+ if(loggerName == null) {
+ loggerName = "root";
+ }
+
+ int i = loggerName.lastIndexOf('.') ;
+ String loggerNameShort = loggerName.substring(i+1) ;
+
+ String formatted$ = record.getMessage() ;
+ if ( record.getParameters() != null )
+ formatted$ = MessageFormat.format(formatted$, record.getParameters()) ;
+
+ // %tT (%5$tT) is %5$tH:%5$tM:%5$tS
+ // %tF is 2008-11-22 "%tY-%tm-%td"
+ return String.format("%5$tT %3$-5s %2$-25s :: %6$s\n",
+ loggerName, // 1
+ loggerNameShort, // 2
+ record.getLevel(), // 3
+ Thread.currentThread().getName(), // 4
+ new Date(record.getMillis()), // 5
+ formatted$) ; // 6
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/base/Closeable.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/base/Closeable.java b/jena-base/src/main/java/org/apache/jena/base/Closeable.java
new file mode 100644
index 0000000..59a06aa
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/base/Closeable.java
@@ -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.base;
+
+/** Close this object.
+ * This form does not allow Exceptions (it does allow RuntimeExceptions)
+ */
+public interface Closeable {
+ public void close() ;
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/base/Sys.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/base/Sys.java b/jena-base/src/main/java/org/apache/jena/base/Sys.java
new file mode 100644
index 0000000..8dbe8d8
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/base/Sys.java
@@ -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.base;
+
+import java.io.File ;
+
+public class Sys {
+ /** Is this windows? */
+ public static final boolean isWindows = (File.pathSeparatorChar == ';') ;
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/TC_Atlas.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/TC_Atlas.java b/jena-base/src/test/java/org/apache/jena/atlas/TC_Atlas.java
new file mode 100644
index 0000000..f455207
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/TC_Atlas.java
@@ -0,0 +1,41 @@
+/*
+ * 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;
+
+import org.apache.jena.atlas.io.TS_IO ;
+import org.apache.jena.atlas.iterator.TS_Iterator ;
+import org.apache.jena.atlas.lib.TS_Lib ;
+import org.junit.runner.RunWith ;
+import org.junit.runners.Suite ;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses( {
+ // Library
+ TS_Lib.class
+ , TS_Iterator.class
+ , TS_IO.class
+// , TS_Event.class
+// , TS_JSON.class
+// , TS_Data.class
+// , TS_Web.class
+// , TestCSVParser.class
+})
+
+public class TC_Atlas
+{}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/io/AbstractTestPeekInputStream.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/io/AbstractTestPeekInputStream.java b/jena-base/src/test/java/org/apache/jena/atlas/io/AbstractTestPeekInputStream.java
new file mode 100644
index 0000000..d127385
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/io/AbstractTestPeekInputStream.java
@@ -0,0 +1,243 @@
+/*
+ * 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.io;
+
+import org.apache.jena.atlas.io.PeekInputStream ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+
+public abstract class AbstractTestPeekInputStream extends BaseTest
+{
+ static int INIT_LINE = PeekInputStream.INIT_LINE ;
+ static int INIT_COL = PeekInputStream.INIT_COL ;
+
+ abstract PeekInputStream make(String contents, int size) ;
+
+ @Test public void read0()
+ {
+ assertEquals("Init line", 1, INIT_LINE) ;
+ assertEquals("Init col", 1, INIT_COL) ;
+ }
+
+ @Test public void read1()
+ {
+ PeekInputStream in = make("") ;
+ checkLineCol(in, INIT_LINE, INIT_COL) ;
+
+ int x = in.peekByte() ;
+ assertEquals(-1, x) ;
+ x = in.readByte() ;
+ assertEquals(-1, x) ;
+ x = in.readByte() ;
+ assertEquals(-1, x) ;
+ }
+
+ @Test public void read2()
+ {
+ // Assumes we start at (1,1)
+ PeekInputStream in = make("a") ;
+ checkLineCol(in, INIT_LINE, INIT_COL) ;
+
+ int x = in.peekByte() ;
+ assertEquals('a', x) ;
+ checkLineCol(in, INIT_LINE, INIT_COL) ;
+
+ x = in.readByte() ;
+ checkLineCol(in, INIT_LINE, INIT_COL+1) ;
+ assertEquals('a', x) ;
+
+ x = in.peekByte() ;
+ assertEquals(-1, x) ;
+
+ x = in.readByte() ;
+ assertEquals(-1, x) ;
+ }
+
+ @Test public void read3()
+ {
+ String c = "abcde" ;
+ PeekInputStream in = make(c) ;
+
+ for ( int i = 0 ; i < c.length(); i++ )
+ {
+ checkLineCol(in, INIT_LINE, i+INIT_COL) ;
+ long z = in.getPosition() ;
+ assertEquals(i, in.getPosition()) ;
+ assertEquals(c.charAt(i), in.readByte()) ;
+ }
+ assertTrue(in.eof()) ;
+ }
+
+ @Test public void read4()
+ {
+ position("abcde") ;
+ }
+
+ @Test public void read5()
+ {
+ position("abc\nde") ;
+ }
+
+ @Test public void read6()
+ {
+ position("abc\nde\n") ;
+ }
+
+ @Test public void read7()
+ {
+ position("") ;
+ }
+
+ @Test public void read8()
+ {
+ position("x") ;
+ }
+
+
+ @Test public void read9()
+ {
+ PeekInputStream in = make("a\nb\n") ;
+ checkLineCol(in, INIT_LINE, INIT_COL) ;
+ int x = in.peekByte() ;
+ assertEquals('a', x) ;
+ checkLineCol(in, INIT_LINE, INIT_COL) ;
+
+ x = in.readByte() ;
+ assertEquals('a', x) ;
+ checkLineCol(in, INIT_LINE, INIT_COL+1) ;
+
+ x = in.readByte() ;
+ assertEquals('\n', x) ;
+ checkLineCol(in, INIT_LINE+1, INIT_COL) ;
+ }
+
+ @Test public void unread1()
+ {
+ PeekInputStream in = make("abc") ;
+ assertEquals('a', in.peekByte()) ;
+ in.pushbackByte('Z') ;
+ assertEquals('Z', in.peekByte()) ;
+ contains(in, "Zabc") ;
+ }
+
+ @Test public void unread2()
+ {
+ PeekInputStream in = make("abc") ;
+ checkLineCol(in, INIT_LINE, INIT_COL) ;
+ int ch = in.readByte() ;
+ // Pushback does not move line/col backwards.
+ checkLineCol(in, INIT_LINE, INIT_COL+1) ;
+ assertEquals('b', in.peekByte()) ;
+ checkLineCol(in, INIT_LINE, INIT_COL+1) ;
+ in.pushbackByte('a') ;
+ checkLineCol(in, INIT_LINE, INIT_COL+1) ;
+ contains(in, "abc") ;
+ }
+
+ @Test public void unread3()
+ {
+ PeekInputStream in = make("") ;
+ int ch = in.readByte() ;
+ assertEquals(-1, in.peekByte()) ;
+ in.pushbackByte('a') ;
+ contains(in, "a") ;
+ }
+
+ @Test public void unread4()
+ {
+ PeekInputStream in = make("") ;
+ int ch = in.readByte() ;
+ assertEquals(-1, in.peekByte()) ;
+ in.pushbackByte('0') ;
+ in.pushbackByte('1') ;
+ in.pushbackByte('2') ;
+ in.pushbackByte('3') ;
+ contains(in, "3210") ; // Backwards!
+ }
+
+ @Test public void unread5()
+ {
+ PeekInputStream in = make("") ;
+ long lineNum = in.getLineNum() ;
+ long colNum = in.getColNum() ;
+
+ checkLineCol(in, lineNum, colNum) ;
+
+ in.pushbackByte('0') ;
+ checkLineCol(in, lineNum, colNum) ; // Unmoved.
+ in.pushbackByte('1') ;
+ checkLineCol(in, lineNum, colNum) ;
+ assertEquals('1', in.readByte()) ;
+
+ checkLineCol(in, lineNum, colNum) ; // Unmoved.
+ in.pushbackByte('2') ;
+ in.pushbackByte('3') ;
+ checkLineCol(in, lineNum, colNum) ; // Unmoved.
+ assertEquals('3', in.peekByte()) ;
+ contains(in, "320") ;
+ }
+
+ private void checkLineCol(PeekInputStream in, long lineNum, long colNum)
+ {
+ assertEquals("Line", lineNum, in.getLineNum()) ;
+ assertEquals("Column", colNum, in.getColNum()) ;
+ }
+
+ private void position(String contents)
+ {
+ PeekInputStream in = make(contents) ;
+
+ int line = INIT_LINE ;
+ int col = INIT_COL ;
+ checkLineCol(in, line, col) ;
+ assertEquals(0, in.getPosition()) ;
+
+ for ( int i = 0 ; i < contents.length(); i++ )
+ {
+ int x = in.readByte() ;
+ if ( x != -1 )
+ {
+ if ( x == '\n' )
+ {
+ line++ ;
+ col = INIT_COL ;
+ }
+ else
+ col++ ;
+ }
+ assertEquals(contents.charAt(i), x) ;
+ assertEquals(i+1, in.getPosition()) ;
+ checkLineCol(in, line, col) ;
+ }
+ assertTrue(in.eof()) ;
+ }
+
+ private void contains(PeekInputStream in, String contents)
+ {
+ for ( int i = 0 ; i < contents.length(); i++ )
+ {
+ int x = in.readByte() ;
+ assertEquals("\""+contents+"\" -- Index "+i+" Expected:'"+contents.charAt(i)+"' Got: '"+(char)x+"'", contents.charAt(i), x) ;
+ }
+ assertTrue(in.eof()) ;
+ }
+
+ private PeekInputStream make(String contents)
+ { return make(contents, 2) ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/io/AbstractTestPeekReader.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/io/AbstractTestPeekReader.java b/jena-base/src/test/java/org/apache/jena/atlas/io/AbstractTestPeekReader.java
new file mode 100644
index 0000000..7ab67b5
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/io/AbstractTestPeekReader.java
@@ -0,0 +1,243 @@
+/*
+ * 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.io;
+
+import org.apache.jena.atlas.io.PeekReader ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+
+public abstract class AbstractTestPeekReader extends BaseTest
+{
+ static int INIT_LINE = PeekReader.INIT_LINE ;
+ static int INIT_COL = PeekReader.INIT_COL ;
+
+ abstract PeekReader make(String contents, int size) ;
+
+ @Test public void read0()
+ {
+ assertEquals("Init line", 1, INIT_LINE) ;
+ assertEquals("Init col", 1, INIT_COL) ;
+ }
+
+ @Test public void read1()
+ {
+ PeekReader r = make("") ;
+ checkLineCol(r, INIT_LINE, INIT_COL) ;
+
+ int x = r.peekChar() ;
+ assertEquals(-1, x) ;
+ x = r.readChar() ;
+ assertEquals(-1, x) ;
+ x = r.readChar() ;
+ assertEquals(-1, x) ;
+ }
+
+ @Test public void read2()
+ {
+ // Assumes we start at (1,1)
+ PeekReader r = make("a") ;
+ checkLineCol(r, INIT_LINE, INIT_COL) ;
+
+ int x = r.peekChar() ;
+ assertEquals('a', x) ;
+ checkLineCol(r, INIT_LINE, INIT_COL) ;
+
+ x = r.readChar() ;
+ checkLineCol(r, INIT_LINE, INIT_COL+1) ;
+ assertEquals('a', x) ;
+
+ x = r.peekChar() ;
+ assertEquals(-1, x) ;
+
+ x = r.readChar() ;
+ assertEquals(-1, x) ;
+ }
+
+ @Test public void read3()
+ {
+ String c = "abcde" ;
+ PeekReader r = make(c) ;
+
+ for ( int i = 0 ; i < c.length(); i++ )
+ {
+ checkLineCol(r, INIT_LINE, i+INIT_COL) ;
+ long z = r.getPosition() ;
+ assertEquals(i, r.getPosition()) ;
+ assertEquals(c.charAt(i), r.readChar()) ;
+ }
+ assertTrue(r.eof()) ;
+ }
+
+ @Test public void read4()
+ {
+ position("abcde") ;
+ }
+
+ @Test public void read5()
+ {
+ position("abc\nde") ;
+ }
+
+ @Test public void read6()
+ {
+ position("abc\nde\n") ;
+ }
+
+ @Test public void read7()
+ {
+ position("") ;
+ }
+
+ @Test public void read8()
+ {
+ position("x") ;
+ }
+
+
+ @Test public void read9()
+ {
+ PeekReader r = make("a\nb\n") ;
+ checkLineCol(r, INIT_LINE, INIT_COL) ;
+ int x = r.peekChar() ;
+ assertEquals('a', x) ;
+ checkLineCol(r, INIT_LINE, INIT_COL) ;
+
+ x = r.readChar() ;
+ assertEquals('a', x) ;
+ checkLineCol(r, INIT_LINE, INIT_COL+1) ;
+
+ x = r.readChar() ;
+ assertEquals('\n', x) ;
+ checkLineCol(r, INIT_LINE+1, INIT_COL) ;
+ }
+
+ @Test public void unread1()
+ {
+ PeekReader r = make("abc") ;
+ assertEquals('a', r.peekChar()) ;
+ r.pushbackChar('Z') ;
+ assertEquals('Z', r.peekChar()) ;
+ contains(r, "Zabc") ;
+ }
+
+ @Test public void unread2()
+ {
+ PeekReader r = make("abc") ;
+ checkLineCol(r, INIT_LINE, INIT_COL) ;
+ int ch = r.readChar() ;
+ // Pushback does not move line/col backwards.
+ checkLineCol(r, INIT_LINE, INIT_COL+1) ;
+ assertEquals('b', r.peekChar()) ;
+ checkLineCol(r, INIT_LINE, INIT_COL+1) ;
+ r.pushbackChar('a') ;
+ checkLineCol(r, INIT_LINE, INIT_COL+1) ;
+ contains(r, "abc") ;
+ }
+
+ @Test public void unread3()
+ {
+ PeekReader r = make("") ;
+ int ch = r.readChar() ;
+ assertEquals(-1, r.peekChar()) ;
+ r.pushbackChar('a') ;
+ contains(r, "a") ;
+ }
+
+ @Test public void unread4()
+ {
+ PeekReader r = make("") ;
+ int ch = r.readChar() ;
+ assertEquals(-1, r.peekChar()) ;
+ r.pushbackChar('0') ;
+ r.pushbackChar('1') ;
+ r.pushbackChar('2') ;
+ r.pushbackChar('3') ;
+ contains(r, "3210") ; // Backwards!
+ }
+
+ @Test public void unread5()
+ {
+ PeekReader r = make("") ;
+ long lineNum = r.getLineNum() ;
+ long colNum = r.getColNum() ;
+
+ checkLineCol(r, lineNum, colNum) ;
+
+ r.pushbackChar('0') ;
+ checkLineCol(r, lineNum, colNum) ; // Unmoved.
+ r.pushbackChar('1') ;
+ checkLineCol(r, lineNum, colNum) ;
+ assertEquals('1', r.readChar()) ;
+
+ checkLineCol(r, lineNum, colNum) ; // Unmoved.
+ r.pushbackChar('2') ;
+ r.pushbackChar('3') ;
+ checkLineCol(r, lineNum, colNum) ; // Unmoved.
+ assertEquals('3', r.peekChar()) ;
+ contains(r, "320") ;
+ }
+
+ private void checkLineCol(PeekReader r, long lineNum, long colNum)
+ {
+ assertEquals("Line", lineNum, r.getLineNum()) ;
+ assertEquals("Column", colNum, r.getColNum()) ;
+ }
+
+ private void position(String contents)
+ {
+ PeekReader r = make(contents) ;
+
+ int line = INIT_LINE ;
+ int col = INIT_COL ;
+ checkLineCol(r, line, col) ;
+ assertEquals(0, r.getPosition()) ;
+
+ for ( int i = 0 ; i < contents.length(); i++ )
+ {
+ int x = r.readChar() ;
+ if ( x != -1 )
+ {
+ if ( x == '\n' )
+ {
+ line++ ;
+ col = INIT_COL ;
+ }
+ else
+ col++ ;
+ }
+ assertEquals(contents.charAt(i), x) ;
+ assertEquals(i+1, r.getPosition()) ;
+ checkLineCol(r, line, col) ;
+ }
+ assertTrue(r.eof()) ;
+ }
+
+ private void contains(PeekReader r, String contents)
+ {
+ for ( int i = 0 ; i < contents.length(); i++ )
+ {
+ int x = r.readChar() ;
+ assertEquals("\""+contents+"\" -- Index "+i+" Expected:'"+contents.charAt(i)+"' Got: '"+(char)x+"'", contents.charAt(i), x) ;
+ }
+ assertTrue(r.eof()) ;
+ }
+
+ private PeekReader make(String contents)
+ { return make(contents, 2) ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/io/TS_IO.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/io/TS_IO.java b/jena-base/src/test/java/org/apache/jena/atlas/io/TS_IO.java
new file mode 100644
index 0000000..4479243
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/io/TS_IO.java
@@ -0,0 +1,45 @@
+/*
+ * 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.io;
+
+import org.junit.runner.RunWith ;
+import org.junit.runners.Suite ;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses( {
+ // Basic classes
+ TestIndentedWriter.class
+ , TestStreamUTF8.class
+ , TestBlockUTF8.class
+ , TestInputStreamBuffered.class
+
+ // Peek readers.
+ , TestPeekReaderSource.class
+ , TestPeekReaderCharSequence.class
+ , TestPeekInputStreamSource.class
+
+ // Writers
+ , TestBufferingWriter.class
+ // Other
+ , TestPrintUtils.class
+} )
+public class TS_IO
+{
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/io/TestBlockUTF8.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/io/TestBlockUTF8.java b/jena-base/src/test/java/org/apache/jena/atlas/io/TestBlockUTF8.java
new file mode 100644
index 0000000..e29d78a
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/io/TestBlockUTF8.java
@@ -0,0 +1,254 @@
+/*
+ * 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.io;
+
+import java.io.ByteArrayOutputStream ;
+import java.io.IOException ;
+import java.io.OutputStreamWriter ;
+import java.io.Writer ;
+import java.nio.Buffer ;
+import java.nio.ByteBuffer ;
+import java.nio.CharBuffer ;
+import java.nio.charset.Charset ;
+import java.nio.charset.CharsetDecoder ;
+import java.nio.charset.CharsetEncoder ;
+
+import org.apache.jena.atlas.io.BlockUTF8 ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.Chars ;
+import org.junit.Test ;
+
+public class TestBlockUTF8 extends BaseTest
+{
+ // Need array and non-array versions.
+
+ static Charset utf8 = Chars.charsetUTF8 ;
+ static CharsetDecoder dec = utf8.newDecoder() ;
+ static CharsetEncoder enc = utf8.newEncoder() ;
+
+ // UTF-8 encoding.
+ // character '¢' = code point U+00A2 -> C2 A2
+ // character '€' = code point U+20AC -> E2 82 AC
+
+ static private final String asciiBase = "abc" ;
+ static private final String latinBase = "Àéíÿ" ;
+ static private final String latinExtraBase = "ỹfifl" ; // fi-ligature, fl-ligature
+ static private final String greekBase = "αβγ" ;
+ static private final String hewbrewBase = "אבג" ;
+ static private final String arabicBase = "ءآأ";
+ static private final String symbolsBase = "☺☻♪♫" ;
+ static private final String chineseBase = "孫子兵法" ; // The Art of War
+ static private final String japaneseBase = "日本" ; // Japanese
+ static private final String binaryStr1 = "abc\uD800xyz" ; // A single surrogate, without it's pair.
+ static private final String binaryStr2 = "\uD800" ; // A single surrogate, without it's pair.
+ static private final String binaryStr3 = "\u0000" ; // A zero character
+
+ static private final byte[] binaryBytes1 = {} ;
+ static private final byte[] binaryBytes2 = { (byte)0x00 } ; // Java encoding of 0 codepoint is 0
+ static private final byte[] binaryBytes3 = { (byte)0xC0, (byte)0x80 } ; // Modifed unicode zero codepoint.
+
+ @Test public void convert_in_00() { testIn("") ; }
+ @Test public void convert_in_01() { testIn(asciiBase) ; }
+ @Test public void convert_in_02() { testIn(latinBase) ; }
+ @Test public void convert_in_03() { testIn(latinExtraBase) ; }
+ @Test public void convert_in_04() { testIn(greekBase) ; }
+ @Test public void convert_in_05() { testIn(hewbrewBase) ; }
+ @Test public void convert_in_06() { testIn(arabicBase) ; }
+ @Test public void convert_in_07() { testIn(symbolsBase) ; }
+ @Test public void convert_in_08() { testIn(chineseBase) ; }
+ @Test public void convert_in_09() { testIn(japaneseBase) ; }
+ @Test public void convert_in_10() { testInOutBinary(binaryStr1) ; }
+ @Test public void convert_in_11() { testInOutBinary(binaryStr2) ; }
+ @Test public void convert_in_12() { testInOutBinary(binaryStr3) ; }
+
+ @Test public void convert_out_00() { testOut("") ; }
+ @Test public void convert_out_01() { testOut(asciiBase) ; }
+ @Test public void convert_out_02() { testOut(latinBase) ; }
+ @Test public void convert_out_03() { testOut(latinExtraBase) ; }
+ @Test public void convert_out_04() { testOut(greekBase) ; }
+ @Test public void convert_out_05() { testOut(hewbrewBase) ; }
+ @Test public void convert_out_06() { testOut(arabicBase) ; }
+ @Test public void convert_out_07() { testOut(symbolsBase) ; }
+ @Test public void convert_out_08() { testOut(chineseBase) ; }
+ @Test public void convert_out_09() { testOut(japaneseBase) ; }
+ @Test public void convert_out_10() { testOut(binaryStr1) ; }
+ @Test public void convert_out_11() { testOut(binaryStr2) ; }
+ @Test public void convert_out_12() { testOut(binaryStr3) ; }
+
+ // While it is key is chars->bytes-chars, we also test bytes->bytes
+ @Test public void binary_01() { testBinary(binaryBytes1) ; }
+ @Test public void binary_02() { testBinary(binaryBytes2) ; }
+ @Test public void binary_03() { testBinary(binaryBytes3, binaryBytes2) ; }
+
+ @Test public void binary_10() { testBinary(binaryBytes2, CharBuffer.wrap(binaryStr3)) ; }
+ @Test public void binary_11() { testBinary(binaryBytes3, CharBuffer.wrap(binaryStr3)) ; }
+
+
+ static void testIn(String x)
+ {
+ testIn(x, allocByteBufferArray, allocCharBufferArray) ;
+ testIn(x, allocByteBufferDirect, allocCharBufferDirect) ;
+
+ }
+ static void testIn(String x, Alloc<ByteBuffer> allocBB, Alloc<CharBuffer> allocCB)
+ {
+ // Test as binary.
+ testInOutBinary(x) ;
+
+ // Now test, comparing to std Java.
+ // Correct answer, in bytes
+ ByteBuffer bytes = ByteBuffer.wrap(stringAsBytes(x)) ;
+ // To bytes.stringAsBytes
+ int N = x.length() ;
+ CharBuffer cb = CharBuffer.wrap(x.toCharArray()) ;
+ ByteBuffer bb = allocBB.allocate(4*N) ;
+ BlockUTF8.fromChars(cb, bb) ;
+ bb.flip() ;
+
+ assertTrue("Bytes", sameBytes(bytes, bb)) ;
+ // From bytes.
+ CharBuffer cb2 = allocCB.allocate(N) ;
+ BlockUTF8.toChars(bb, cb2) ;
+ cb2.flip() ;
+ String str = cb2.toString() ;
+ assertEquals(x, str) ;
+ }
+
+ // Tesing, but not against what Java would do (it replaces bad chars, we want binary).
+ static void testInOutBinary(String x)
+ {
+ int N = x.length() ;
+ CharBuffer cb = CharBuffer.wrap(x.toCharArray()) ;
+ ByteBuffer bb = ByteBuffer.allocate(4*N) ;
+ BlockUTF8.fromChars(cb, bb) ;
+ bb.flip() ;
+ CharBuffer cb2 = CharBuffer.allocate(N) ;
+ BlockUTF8.toChars(bb, cb2) ;
+ // compare cb and cb2.
+ String str = new String(cb2.array(), 0, cb2.position()) ;
+ assertEquals(x, str) ;
+
+ // And re-code as bytes.
+ CharBuffer cb3 = CharBuffer.wrap(x.toCharArray()) ;
+ ByteBuffer bb3 = ByteBuffer.allocate(4*N) ;
+ BlockUTF8.fromChars(cb3, bb3) ;
+ bb3.flip() ;
+ assertArrayEquals(bb.array(), bb3.array()) ;
+ }
+
+ static void testOut(String x)
+ {
+ testOut(x, allocByteBufferArray, allocCharBufferArray) ;
+ testOut(x, allocByteBufferDirect, allocCharBufferDirect) ;
+ }
+
+ static interface Alloc<T extends Buffer> { T allocate(int len) ; }
+ static Alloc<ByteBuffer> allocByteBufferArray = new Alloc<ByteBuffer>() {
+ @Override public ByteBuffer allocate(int len) { return ByteBuffer.allocate(len) ; }
+ } ;
+ static Alloc<ByteBuffer> allocByteBufferDirect = new Alloc<ByteBuffer>() {
+ @Override public ByteBuffer allocate(int len) { return ByteBuffer.allocateDirect(len) ; }
+ } ;
+ static Alloc<CharBuffer> allocCharBufferArray = new Alloc<CharBuffer>() {
+ @Override public CharBuffer allocate(int len) { return CharBuffer.allocate(len) ; }
+ } ;
+ static Alloc<CharBuffer> allocCharBufferDirect = new Alloc<CharBuffer>() {
+ @Override public CharBuffer allocate(int len) { return ByteBuffer.allocateDirect(2*len).asCharBuffer() ; }
+ } ;
+
+ static void testOut(String x, Alloc<ByteBuffer> allocBB, Alloc<CharBuffer> allocCB)
+ {
+ testBinary(stringAsBytes(x)) ;
+
+ int N = x.length() ;
+ // First - get bytes the Java way.
+ ByteBuffer bytes = ByteBuffer.wrap(stringAsBytes(x)) ;
+ CharBuffer cb = allocCB.allocate(N) ;
+
+ BlockUTF8.toChars(bytes, cb) ;
+ cb.flip() ;
+ bytes.flip() ;
+
+ String str = cb.toString() ;
+ ByteBuffer bytes2 = allocBB.allocate(bytes.capacity()) ;
+ BlockUTF8.fromChars(cb, bytes2) ;
+ bytes2.flip() ;
+ assertTrue("Chars", sameBytes(bytes, bytes2)) ;
+ }
+
+ static void testBinary(byte[] binary, CharBuffer chars)
+ {
+ int N = binary.length ;
+ ByteBuffer bytes = ByteBuffer.wrap(binary) ;
+ CharBuffer cb = CharBuffer.allocate(N) ;
+ BlockUTF8.toChars(bytes, cb) ;
+ cb.flip() ;
+ assertTrue("Binary", sameChars(chars, cb));
+ }
+
+ static void testBinary(byte[] binary)
+ {
+ testBinary(binary, binary) ;
+ }
+
+ static void testBinary(byte[] binary, byte[] expected)
+ {
+ int N = binary.length ;
+ ByteBuffer bytes = ByteBuffer.wrap(binary) ;
+ CharBuffer cb = CharBuffer.allocate(N) ;
+ BlockUTF8.toChars(bytes, cb) ;
+ cb.flip() ;
+ bytes.position(0) ;
+ ByteBuffer bytes2 = ByteBuffer.allocate(2*N) ; // Null bytes get expanded.
+ BlockUTF8.fromChars(cb, bytes2) ;
+ bytes2.flip() ;
+ sameBytes(bytes, bytes2) ;
+ assertTrue("Binary", sameBytes(ByteBuffer.wrap(expected), bytes2)) ;
+ }
+
+ // Does not move position.
+ static boolean sameBytes(ByteBuffer bb1, ByteBuffer bb2)
+ {
+ if ( bb1.remaining() != bb2.remaining() ) return false ;
+
+ for ( int i = 0 ; i < bb1.remaining() ; i++ )
+ if ( bb1.get(i+bb1.position()) != bb2.get(i+bb2.position()) ) return false ;
+ return true ;
+ }
+ // Does not move position.
+ static boolean sameChars(CharBuffer cb1, CharBuffer cb2)
+ {
+ if ( cb1.remaining() != cb2.remaining() ) return false ;
+
+ for ( int i = 0 ; i < cb1.remaining() ; i++ )
+ if ( cb1.get(i+cb1.position()) != cb2.get(i+cb2.position()) ) return false ;
+ return true ;
+ }
+ static byte[] stringAsBytes(String x)
+ {
+ try {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream() ;
+ try(Writer out = new OutputStreamWriter(bout, utf8)) {
+ out.write(x) ;
+ }
+ byte[] bytes = bout.toByteArray() ;
+ return bytes ;
+ } catch (IOException ex) { throw new RuntimeException(ex) ; }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/io/TestBufferingWriter.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/io/TestBufferingWriter.java b/jena-base/src/test/java/org/apache/jena/atlas/io/TestBufferingWriter.java
new file mode 100644
index 0000000..08e81c6
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/io/TestBufferingWriter.java
@@ -0,0 +1,97 @@
+/*
+ * 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.io ;
+
+import java.io.StringWriter ;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+
+public class TestBufferingWriter extends BaseTest {
+ StringWriter sw = null ;
+ BufferingWriter w = null ;
+
+ public void create(int size, int blobSize) {
+ sw = new StringWriter() ;
+ w = new BufferingWriter(sw, size, blobSize) ;
+ }
+
+ public String string() {
+ return sw.toString() ;
+ }
+
+ @Test
+ public void write_01() {
+ create(10, 5) ;
+ w.output("x") ;
+ w.flush() ;
+ String x = string() ;
+ assertEquals("x", x) ;
+ }
+
+ @Test
+ public void write_02() {
+ create(10, 5) ;
+ w.output("foofoo") ; // Large object
+ w.flush() ;
+ String x = string() ;
+ assertEquals("foofoo", x) ;
+ }
+
+ @Test
+ public void write_03() {
+ create(10, 8) ;
+ w.output("a") ;
+ w.output("b") ;
+ w.output("c") ;
+ w.flush() ;
+ String x = string() ;
+ assertEquals("abc", x) ;
+ }
+
+ @Test
+ public void write_04() {
+ create(10, 8) ;
+ w.output("abcdefghijklmnopqrstuvwxyz") ;
+ w.output("XYZ") ;
+ w.flush() ;
+ String x = string() ;
+ assertEquals("abcdefghijklmnopqrstuvwxyzXYZ", x) ;
+ }
+
+ @Test
+ public void write_05() {
+ create(10, 8) ;
+ w.output("") ;
+ w.flush() ;
+ String x = string() ;
+ assertEquals("", x) ;
+ }
+
+ @Test
+ public void write_06() {
+ // Test closing the stream without flushing (the flush should be done
+ // implicitly)
+ create(100, 50) ;
+ w.output("test") ;
+ w.close() ;
+ String x = string() ;
+ assertEquals("test", x) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/io/TestIndentedWriter.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/io/TestIndentedWriter.java b/jena-base/src/test/java/org/apache/jena/atlas/io/TestIndentedWriter.java
new file mode 100644
index 0000000..77608d4
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/io/TestIndentedWriter.java
@@ -0,0 +1,58 @@
+/*
+ * 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.io;
+
+import org.apache.jena.atlas.io.IndentedLineBuffer ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+
+public class TestIndentedWriter extends BaseTest
+{
+ @Test public void write01()
+ {
+ try(IndentedLineBuffer b = new IndentedLineBuffer()) {
+ b.print("hell") ;
+ b.print("o") ;
+ assertEquals("hello", b.asString()) ;
+ }
+ }
+
+ @Test public void write02()
+ {
+ try(IndentedLineBuffer b = new IndentedLineBuffer()) {
+ b.incIndent() ;
+ b.print("hell") ;
+ b.print("o") ;
+ b.decIndent() ;
+ assertEquals(" hello", b.asString()) ;
+ }
+ }
+
+ @Test public void write03()
+ {
+ try(IndentedLineBuffer b = new IndentedLineBuffer()) {
+ b.incIndent() ;
+ b.printf("0x%04X", 1) ;
+ b.println() ;
+ b.print("XX") ;
+ b.decIndent() ;
+ assertEquals(" 0x0001\n XX", b.asString()) ;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/io/TestInputStreamBuffered.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/io/TestInputStreamBuffered.java b/jena-base/src/test/java/org/apache/jena/atlas/io/TestInputStreamBuffered.java
new file mode 100644
index 0000000..292bb64
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/io/TestInputStreamBuffered.java
@@ -0,0 +1,109 @@
+/*
+ * 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.io;
+
+import java.io.ByteArrayInputStream ;
+import java.io.IOException ;
+import java.io.InputStream ;
+
+import org.apache.jena.atlas.io.InputStreamBuffered ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.Bytes ;
+import org.junit.Test ;
+
+public class TestInputStreamBuffered extends BaseTest
+{
+ @Test public void test_01() throws IOException
+ {
+ InputStream in = stream("") ;
+ InputStream in2 = new InputStreamBuffered(in) ;
+ int x = count(in2) ;
+ assertEquals(0, x) ;
+ }
+
+ @Test public void test_02() throws IOException
+ {
+ InputStream in = stream(1,2,3,4) ;
+ InputStream in2 = new InputStreamBuffered(in) ;
+ check(in2, 1,2,3,4) ;
+ }
+
+ @Test public void test_03() throws IOException
+ {
+ InputStream in = stream(1,2,3,4) ;
+ InputStream in2 = new InputStreamBuffered(in, 2) ;
+ check(in2, 1,2,3,4) ;
+ }
+
+ @Test public void test_04() throws IOException
+ {
+ InputStream in = stream(1,2,3,4) ;
+ InputStream in2 = new InputStreamBuffered(in, 1) ;
+ check(in2, 1,2,3,4) ;
+ assertEquals(-1, in.read()) ;
+ }
+
+
+ private static InputStream stream(String data)
+ {
+ byte[] b = Bytes.string2bytes(data) ;
+ return new ByteArrayInputStream(b) ;
+ }
+
+ private static InputStream stream(byte...bytes)
+ {
+ return new ByteArrayInputStream(bytes) ;
+ }
+
+ private static InputStream stream(int...bytes)
+ {
+ return stream(ints2bytes(bytes)) ;
+ }
+
+ // Convenience.
+ private static byte[] ints2bytes(int...values)
+ {
+ byte b[] = new byte[values.length] ;
+ for ( int i = 0 ; i < b.length ; i++ )
+ b[i] = (byte)values[i] ;
+ return b ;
+ }
+
+ private static int count(InputStream in) throws IOException
+ {
+ int count = 0 ;
+ while(in.read() != -1 )
+ count++ ;
+ return count ;
+ }
+
+ private static void check(InputStream in, int ...bytes) throws IOException
+ {
+ check(in, ints2bytes(bytes)) ;
+ }
+
+ private static void check(InputStream in, byte ...bytes) throws IOException
+ {
+ for ( byte b : bytes )
+ {
+ assertEquals(b, (byte)in.read()) ;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/io/TestPeekInputStreamSource.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/io/TestPeekInputStreamSource.java b/jena-base/src/test/java/org/apache/jena/atlas/io/TestPeekInputStreamSource.java
new file mode 100644
index 0000000..379a78a
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/io/TestPeekInputStreamSource.java
@@ -0,0 +1,44 @@
+/*
+ * 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.io;
+
+import java.io.ByteArrayInputStream ;
+import java.io.UnsupportedEncodingException ;
+
+import org.apache.jena.atlas.io.PeekInputStream ;
+
+public class TestPeekInputStreamSource extends AbstractTestPeekInputStream
+{
+ @Override
+ PeekInputStream make(String contents, int size)
+ {
+ // Very carefuly ensure this is not a byte array-based PeekReader
+ ByteArrayInputStream bin ;
+ try
+ {
+ bin = new ByteArrayInputStream(contents.getBytes("ASCII")) ;
+ } catch (UnsupportedEncodingException ex)
+ {
+ ex.printStackTrace();
+ return null ;
+ }
+
+ return PeekInputStream.make(bin, size) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/io/TestPeekReaderCharSequence.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/io/TestPeekReaderCharSequence.java b/jena-base/src/test/java/org/apache/jena/atlas/io/TestPeekReaderCharSequence.java
new file mode 100644
index 0000000..f6c5c42
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/io/TestPeekReaderCharSequence.java
@@ -0,0 +1,32 @@
+/*
+ * 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.io;
+
+import org.apache.jena.atlas.io.PeekReader ;
+
+
+
+public class TestPeekReaderCharSequence extends AbstractTestPeekReader
+{
+ @Override
+ PeekReader make(String contents, int size)
+ {
+ return PeekReader.readString(contents) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/io/TestPeekReaderSource.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/io/TestPeekReaderSource.java b/jena-base/src/test/java/org/apache/jena/atlas/io/TestPeekReaderSource.java
new file mode 100644
index 0000000..2624351
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/io/TestPeekReaderSource.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.atlas.io;
+
+import java.io.StringReader ;
+
+import org.apache.jena.atlas.io.PeekReader ;
+
+public class TestPeekReaderSource extends AbstractTestPeekReader
+{
+ @Override
+ PeekReader make(String contents, int size)
+ {
+ // Very carefuly ensure this is not a string-based PeekReader
+ StringReader r = new StringReader(contents) ;
+ return PeekReader.make(r, size) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/io/TestPrintUtils.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/io/TestPrintUtils.java b/jena-base/src/test/java/org/apache/jena/atlas/io/TestPrintUtils.java
new file mode 100644
index 0000000..aa6f3a6
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/io/TestPrintUtils.java
@@ -0,0 +1,59 @@
+/*
+ * 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.io;
+
+import java.io.ByteArrayOutputStream ;
+import java.io.IOException ;
+import java.io.OutputStreamWriter ;
+import java.io.Writer ;
+
+import org.apache.jena.atlas.io.OutputUtils ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+
+public class TestPrintUtils extends BaseTest
+{
+ @Test public void hex1()
+ {
+ String s = test(0,4) ;
+ assertEquals("0000", s) ;
+ }
+
+ @Test public void hex2()
+ {
+ String s = test(1,8) ;
+ assertEquals("00000001", s) ;
+ }
+
+ @Test public void hex3()
+ {
+ String s = test(0xFF,2) ;
+ assertEquals("FF", s) ;
+ }
+
+ private static String test(int value, int width)
+ {
+ ByteArrayOutputStream x = new ByteArrayOutputStream() ;
+ Writer out = new OutputStreamWriter(x) ;
+ OutputUtils.printHex(out, value, width) ;
+ try { out.flush() ; } catch (IOException ex) {}
+ String s = x.toString() ;
+ return s ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/io/TestStreamUTF8.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/io/TestStreamUTF8.java b/jena-base/src/test/java/org/apache/jena/atlas/io/TestStreamUTF8.java
new file mode 100644
index 0000000..4c92978
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/io/TestStreamUTF8.java
@@ -0,0 +1,118 @@
+/*
+ * 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.io;
+
+import java.io.ByteArrayInputStream ;
+import java.io.ByteArrayOutputStream ;
+import java.io.IOException ;
+import java.io.OutputStreamWriter ;
+import java.io.Writer ;
+import java.nio.charset.Charset ;
+import java.nio.charset.CharsetDecoder ;
+import java.nio.charset.CharsetEncoder ;
+
+import org.apache.jena.atlas.io.InStreamUTF8 ;
+import org.apache.jena.atlas.io.OutStreamUTF8 ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.Chars ;
+import org.junit.Test ;
+
+public class TestStreamUTF8 extends BaseTest
+ {
+ static Charset utf8 = Chars.charsetUTF8 ;
+ static CharsetDecoder dec = utf8.newDecoder() ;
+ static CharsetEncoder enc = utf8.newEncoder() ;
+
+ // UTF-8 encoding.
+ // character '¢' = code point U+00A2 -> C2 A2
+ // character '€' = code point U+20AC -> E2 82 AC
+
+ static private final String asciiBase = "abc" ;
+ static private final String latinBase = "Àéíÿ" ;
+ static private final String latinExtraBase = "ỹfifl" ; // fi-ligature, fl-ligature
+ static private final String greekBase = "αβγ" ;
+ static private final String hewbrewBase = "אבג" ;
+ static private final String arabicBase = "ءآأ";
+ static private final String symbolsBase = "☺☻♪♫" ;
+ static private final String chineseBase = "孫子兵法" ; // The Art of War
+ static private final String japaneseBase = "日本" ; // Japanese
+
+ @Test public void test_in_00() { testIn("") ; }
+ @Test public void test_in_01() { testIn(asciiBase) ; }
+ @Test public void test_in_02() { testIn(latinBase) ; }
+ @Test public void test_in_03() { testIn(latinExtraBase) ; }
+ @Test public void test_in_04() { testIn(greekBase) ; }
+ @Test public void test_in_05() { testIn(hewbrewBase) ; }
+ @Test public void test_in_06() { testIn(arabicBase) ; }
+ @Test public void test_in_07() { testIn(symbolsBase) ; }
+ @Test public void test_in_08() { testIn(chineseBase) ; }
+ @Test public void test_in_09() { testIn(japaneseBase) ; }
+
+ @Test public void test_out_00() { testIn("") ; }
+ @Test public void test_out_01() { testOut(asciiBase) ; }
+ @Test public void test_out_02() { testOut(latinBase) ; }
+ @Test public void test_out_03() { testOut(latinExtraBase) ; }
+ @Test public void test_out_04() { testOut(greekBase) ; }
+ @Test public void test_out_05() { testOut(hewbrewBase) ; }
+ @Test public void test_out_06() { testOut(arabicBase) ; }
+ @Test public void test_out_07() { testOut(symbolsBase) ; }
+ @Test public void test_out_08() { testOut(chineseBase) ; }
+ @Test public void test_out_09() { testOut(japaneseBase) ; }
+
+ static void testIn(String x)
+ {
+ try {
+ byte[] bytes = stringAsBytes(x) ;
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bytes) ;
+ // Create string from bytes
+ try(InStreamUTF8 r = new InStreamUTF8(bin)) {
+ char[] cbuff = new char[x.length()*10] ; // Way too big
+ int len = r.read(cbuff) ;
+ String str = new String(cbuff, 0 , len) ;
+ assertEquals(x, str) ;
+ }
+ } catch (IOException ex) { throw new RuntimeException(ex) ; }
+ }
+
+ static void testOut(String x)
+ {
+ try {
+ byte[] bytes = stringAsBytes(x) ;
+ ByteArrayOutputStream bout = new ByteArrayOutputStream() ;
+ try(Writer out = new OutStreamUTF8(bout)) {
+ out.write(x) ;
+ }
+ byte[] bytes2 = bout.toByteArray() ;
+ assertArrayEquals(bytes, bytes2) ;
+ } catch (IOException ex) { throw new RuntimeException(ex) ; }
+ }
+
+ static byte[] stringAsBytes(String x)
+ {
+ try {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream() ;
+ try(Writer out = new OutputStreamWriter(bout, utf8)) {
+ out.write(x) ;
+ }
+ byte[] bytes = bout.toByteArray() ;
+ return bytes ;
+ } catch (IOException ex) { throw new RuntimeException(ex) ; }
+ }
+ }
[2/9] jena git commit: Import of lib, io,
logging and iterator packages
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/iterator/TS_Iterator.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/iterator/TS_Iterator.java b/jena-base/src/test/java/org/apache/jena/atlas/iterator/TS_Iterator.java
new file mode 100644
index 0000000..37c8430
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/iterator/TS_Iterator.java
@@ -0,0 +1,38 @@
+/*
+ * 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.iterator;
+
+import org.junit.runner.RunWith ;
+import org.junit.runners.Suite ;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses( {
+ TestIter.class
+ , TestIteratorPeek.class
+ , TestIteratorArray.class
+ , TestIteratorPushback.class
+ , TestIteratorWithHistory.class
+ , TestIteratorWithBuffer.class
+ , TestIteratorSlotted.class
+} )
+
+public class TS_Iterator
+{
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIter.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIter.java b/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIter.java
new file mode 100644
index 0000000..56cf8a9
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIter.java
@@ -0,0 +1,539 @@
+/*
+ * 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.iterator;
+
+import static org.junit.Assert.assertEquals ;
+import static org.junit.Assert.assertFalse ;
+import static org.junit.Assert.assertTrue ;
+
+import java.util.ArrayList ;
+import java.util.Arrays ;
+import java.util.Iterator ;
+import java.util.List ;
+
+import org.junit.Test ;
+
+public class TestIter
+{
+ List<String> data0 = new ArrayList<>() ;
+ List<String> data1 = Arrays.asList("a") ;
+ List<String> data2 = Arrays.asList("x","y","z") ;
+ List<String> data3 = Arrays.asList(null, "x", null, null, null, "y", "z", null);
+
+ @Test
+ public void append_1()
+ {
+ Iterator<String> iter = Iter.append(data1.iterator(), data0.iterator()) ;
+ test(iter, "a") ;
+ }
+
+
+ @Test
+ public void append_2()
+ {
+ Iterator<String> iter = Iter.append(data0.iterator(), data1.iterator()) ;
+ test(iter, "a") ;
+ }
+
+ @Test
+ public void append_3()
+ {
+ Iterator<String> iter = Iter.append(data1.iterator(), data2.iterator()) ;
+ test(iter, "a", "x", "y", "z") ;
+ }
+
+ @Test
+ public void append_4()
+ {
+ List<String> L = new ArrayList<>(3);
+ L.add("a");
+ L.add("b");
+ L.add("c");
+ List<String> R = new ArrayList<>(3);
+ R.add("d");
+ R.add("e");
+ R.add("f");
+
+
+ Iterator<String> LR = Iter.append(L.iterator(), R.iterator()) ;
+
+ while (LR.hasNext())
+ {
+ String s = LR.next();
+
+ if ("c".equals(s))
+ {
+ LR.hasNext(); // test for JENA-60
+ LR.remove();
+ }
+ }
+
+ assertEquals("ab", Iter.asString(L, ""));
+ assertEquals("def", Iter.asString(R, ""));
+ }
+
+ @Test
+ public void append_5()
+ {
+ List<String> L = new ArrayList<>(3);
+ L.add("a");
+ L.add("b");
+ L.add("c");
+ List<String> R = new ArrayList<>(3);
+ R.add("d");
+ R.add("e");
+ R.add("f");
+
+
+ Iterator<String> LR = Iter.append(L.iterator(), R.iterator()) ;
+
+ while (LR.hasNext())
+ {
+ String s = LR.next();
+
+ if ("d".equals(s))
+ {
+ LR.hasNext(); // test for JENA-60
+ LR.remove();
+ }
+ }
+
+ assertEquals("abc", Iter.asString(L, ""));
+ assertEquals("ef", Iter.asString(R, ""));
+ }
+
+ @Test
+ public void append_6()
+ {
+ List<String> L = new ArrayList<>(3);
+ L.add("a");
+ L.add("b");
+ L.add("c");
+ List<String> R = new ArrayList<>(3);
+ R.add("d");
+ R.add("e");
+ R.add("f");
+
+
+ Iterator<String> LR = Iter.append(L.iterator(), R.iterator()) ;
+
+ while (LR.hasNext())
+ {
+ LR.next() ;
+ }
+ LR.remove() ;
+
+ assertEquals("abc", Iter.asString(L, "")) ;
+ assertEquals("de", Iter.asString(R, "")) ;
+ }
+
+ @Test
+ public void asString_1()
+ {
+ String x = Iter.asString(data0, "") ;
+ assertEquals("", x) ;
+ }
+
+ @Test
+ public void asString_2()
+ {
+ String x = Iter.asString(data1, "") ;
+ assertEquals("a", x) ;
+ }
+
+ @Test
+ public void asString_3()
+ {
+ String x = Iter.asString(data1, "/") ;
+ assertEquals("a", x) ;
+ }
+
+ @Test
+ public void asString_4()
+ {
+ String x = Iter.asString(data2, "/") ;
+ assertEquals("x/y/z", x) ;
+ }
+
+ private void test(Iterator<?> iter, Object... items)
+ {
+ for ( Object x : items )
+ {
+ assertTrue(iter.hasNext()) ;
+ assertEquals(x, iter.next()) ;
+ }
+ assertFalse(iter.hasNext()) ;
+ }
+
+ static Iter.Folder<String, String> f1 = new Iter.Folder<String, String>() {
+ @Override
+ public String eval(String acc, String arg)
+ {
+ return acc + arg ;
+ }
+ } ;
+
+ @Test
+ public void fold_01()
+ {
+ String[] x = { "a", "b", "c" } ;
+ String z = Iter.foldLeft(Arrays.asList(x), f1, "X") ;
+ assertEquals("Xabc", z) ;
+ }
+
+ @Test
+ public void fold_02()
+ {
+ String[] x = { "a", "b", "c" } ;
+ String z = Iter.foldRight(Arrays.asList(x), f1, "X") ;
+ assertEquals("Xcba", z) ;
+ }
+
+ @Test
+ public void fold_03()
+ {
+ String[] x = { } ;
+ String z = Iter.foldLeft(Arrays.asList(x), f1, "X") ;
+ assertEquals("X", z) ;
+ }
+
+ @Test
+ public void fold_04()
+ {
+ String[] x = { } ;
+ String z = Iter.foldRight(Arrays.asList(x), f1, "X") ;
+ assertEquals("X", z) ;
+ }
+
+
+ @Test
+ public void map_01()
+ {
+ Iterator<String> it = Iter.map(data2.iterator(), new Transform<String,String>()
+ {
+ @Override
+ public String convert(String item)
+ {
+ return item + item;
+ }
+ });
+ test(it, "xx", "yy", "zz");
+ }
+
+ @Test
+ public void mapMany_01()
+ {
+ Iterator<String> it = Iter.mapMany(data2.iterator(), new Transform<String,Iterator<String>>()
+ {
+ @Override
+ public Iterator<String> convert(String item)
+ {
+ List<String> l = new ArrayList<>(2);
+ l.add(item);
+ l.add(item + item);
+ return l.iterator();
+ }
+ });
+
+ test(it, "x", "xx", "y", "yy", "z", "zz");
+ }
+
+ @Test
+ public void mapMany_02()
+ {
+ Iterator<String> it = Iter.mapMany(data2.iterator(), new Transform<String,Iterator<String>>()
+ {
+ @Override
+ public Iterator<String> convert(String item)
+ {
+ return Iter.nullIterator() ;
+ }
+ });
+
+ assertFalse(it.hasNext()) ;
+ }
+
+ @Test
+ public void mapMany_03()
+ {
+ Iterator<String> it = Iter.mapMany(data2.iterator(), new Transform<String,Iterator<String>>()
+ {
+ int count = 0 ;
+ @Override
+ public Iterator<String> convert(String item)
+ {
+ count++ ;
+ if ( count%2 == 1 )
+ return Iter.singleton(item) ;
+ else
+ return Iter.nullIterator() ;
+ }
+ });
+
+ test(it, "x", "z");
+ }
+
+ @Test
+ public void mapMany_04()
+ {
+ Iterator<String> it = Iter.mapMany(data2.iterator(), new Transform<String,Iterator<String>>()
+ {
+ int count = 0 ;
+ @Override
+ public Iterator<String> convert(String item)
+ {
+ count++ ;
+ if ( count%2 == 0 )
+ return Iter.singleton(item) ;
+ else
+ return Iter.nullIterator() ;
+ }
+ });
+
+ test(it, "y");
+ }
+
+
+ Filter<String> filter = new Filter<String>() {
+ @Override
+ public boolean accept(String item)
+ {
+ return item.length() == 1 ;
+ }} ;
+
+ @Test
+ public void first_01()
+ {
+ Iter<String> iter = Iter.nullIter() ;
+ assertEquals(null, Iter.first(iter, filter)) ;
+ }
+
+ @Test
+ public void first_02()
+ {
+ List<String> data = Arrays.asList( "11", "A", "B", "C") ;
+ assertEquals("A", Iter.first(data, filter)) ;
+ }
+
+ @Test
+ public void first_03()
+ {
+ List<String> data = Arrays.asList( "11", "AA", "BB", "CC") ;
+ assertEquals(null, Iter.first(data, filter)) ;
+ }
+
+ @Test
+ public void first_04()
+ {
+ Iter<String> iter = Iter.nullIter() ;
+ assertEquals(-1, Iter.firstIndex(iter, filter)) ;
+ }
+
+ @Test
+ public void first_05()
+ {
+ List<String> data = Arrays.asList( "11", "A", "B", "C") ;
+ assertEquals(1, Iter.firstIndex(data, filter)) ;
+ }
+
+ @Test
+ public void first_06()
+ {
+ List<String> data = Arrays.asList( "11", "AA", "BB", "CC") ;
+ assertEquals(-1, Iter.firstIndex(data, filter)) ;
+ }
+
+ @Test
+ public void last_01()
+ {
+ Iter<String> iter = Iter.nullIter() ;
+ assertEquals(null, Iter.last(iter, filter)) ;
+ }
+
+ @Test
+ public void last_02()
+ {
+ List<String> data = Arrays.asList( "11", "A", "B", "C") ;
+ assertEquals("C", Iter.last(data, filter)) ;
+ }
+
+ @Test
+ public void last_03()
+ {
+ List<String> data = Arrays.asList( "11", "AA", "BB", "CC") ;
+ assertEquals(null, Iter.last(data, filter)) ;
+ }
+
+ @Test
+ public void last_04()
+ {
+ Iter<String> iter = Iter.nullIter() ;
+ assertEquals(-1, Iter.lastIndex(iter, filter)) ;
+ }
+
+ @Test
+ public void last_05()
+ {
+ List<String> data = Arrays.asList( "11", "A", "B", "C") ;
+ assertEquals(3, Iter.lastIndex(data, filter)) ;
+ }
+
+ @Test
+ public void last_06()
+ {
+ List<String> data = Arrays.asList( "11", "AA", "BB", "CC") ;
+ assertEquals(-1, Iter.lastIndex(data, filter)) ;
+ }
+
+ @Test
+ public void take_01()
+ {
+ List<String> data = Arrays.asList( "1", "A", "B", "CC") ;
+ List<String> data2 = Iter.take(data.iterator(), 2) ;
+ assertEquals(2, data2.size()) ;
+ assertEquals("1", data2.get(0)) ;
+ assertEquals("A", data2.get(1)) ;
+ }
+
+
+ @Test
+ public void take_02()
+ {
+ List<String> data = Arrays.asList( "1", "A", "B", "CC") ;
+ List<String> data2 = Iter.take(data.iterator(), 0) ;
+ assertEquals(0, data2.size()) ;
+ }
+
+ @Test
+ public void take_03()
+ {
+ List<String> data = Arrays.asList( "1", "A", "B", "CC") ;
+ List<String> data2 = Iter.take(data.iterator(), 10) ;
+ assertEquals(4, data2.size()) ;
+ assertEquals("1", data2.get(0)) ;
+ assertEquals("A", data2.get(1)) ;
+ assertEquals("B", data2.get(2)) ;
+ assertEquals("CC", data2.get(3)) ;
+ }
+
+ @Test
+ public void filter_01()
+ {
+ test(Iter.removeNulls(data3.iterator()), "x", "y", "z");
+ }
+
+ @Test
+ public void filter_02()
+ {
+ Iterator<String> it = Iter.filter(data3.iterator(), new Filter<String>()
+ {
+ @Override
+ public boolean accept(String item)
+ {
+ return "x".equals(item) || "z".equals(item) ;
+ }
+ });
+
+ test(it, "x", "z");
+ }
+
+ @Test
+ public void filter_03()
+ {
+ Iterator<String> it = Iter.filter(data3.iterator(), new Filter<String>()
+ {
+ @Override
+ public boolean accept(String item)
+ {
+ return (null == item) || "x".equals(item) ;
+ }
+ });
+
+ test(it, null, "x", null, null, null, null);
+ }
+
+ @Test public void distinct_01()
+ {
+ List<String> x = Arrays.asList("a", "b", "a") ;
+ Iterator<String> iter = Iter.distinct(x.iterator()) ;
+ test(iter, "a", "b") ;
+ }
+
+ @Test public void distinct_02()
+ {
+ List<String> x = Arrays.asList("a", "b", "a") ;
+ Iterator<String> iter = Iter.distinctAdjacent(x.iterator()) ;
+ test(iter, "a", "b", "a") ;
+ }
+
+ @Test public void distinct_03()
+ {
+ List<String> x = Arrays.asList("a", "a", "b", "b", "b", "a", "a") ;
+ Iterator<String> iter = Iter.distinct(x.iterator()) ;
+ test(iter, "a", "b") ;
+ }
+
+ @Test public void distinct_04()
+ {
+ List<String> x = Arrays.asList("a", "a", "b", "b", "b", "a", "a") ;
+ Iterator<String> iter = Iter.distinctAdjacent(x.iterator()) ;
+ test(iter, "a", "b", "a") ;
+ }
+
+ private static class AlwaysAcceptFilter implements Filter<Object> {
+ @Override
+ public boolean accept(Object o) {
+ return true;
+ }
+ }
+
+ private static class NeverAcceptFilter implements Filter<Object> {
+ @Override
+ public boolean accept(Object o) {
+ return false;
+ }
+ }
+
+
+ private static class AlwaysAcceptFilterStack extends FilterStack<Object> {
+ public AlwaysAcceptFilterStack(Filter<Object> f) {
+ super(f);
+ }
+
+ @Override
+ public boolean acceptAdditional(Object o) {
+ return true;
+ }
+ }
+
+ @Test
+ public void testFilterStack_01() {
+ Filter<Object> filter = new AlwaysAcceptFilter();
+ FilterStack<Object> filterStack = new AlwaysAcceptFilterStack(filter);
+ assertTrue(filterStack.accept(new Object()));
+ }
+
+ @Test
+ public void testFilterStack_02() {
+ Filter<Object> filter = new NeverAcceptFilter();
+ FilterStack<Object> filterStack = new AlwaysAcceptFilterStack(filter);
+ assertFalse(filterStack.accept(new Object()));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorArray.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorArray.java b/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorArray.java
new file mode 100644
index 0000000..5108865
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorArray.java
@@ -0,0 +1,104 @@
+/*
+ * 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.iterator;
+
+import java.util.Iterator ;
+import java.util.NoSuchElementException ;
+
+import org.apache.jena.atlas.iterator.IteratorArray ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+
+public class TestIteratorArray extends BaseTest
+{
+ IteratorArray<String> create(String ... a)
+ {
+ return IteratorArray.create(a) ;
+ }
+
+ IteratorArray<String> create(int start, int finish, String ... a)
+ {
+ return IteratorArray.create(a, start, finish) ;
+ }
+
+ @Test public void arrayIterator_1()
+ {
+ Iterator<String> iter = create() ;
+ assertFalse(iter.hasNext()) ;
+ assertFalse(iter.hasNext()) ;
+ }
+
+ @Test public void arrayIterator_2()
+ {
+ Iterator<String> iter = create("a") ;
+ assertTrue(iter.hasNext()) ;
+ assertEquals("a", iter.next()) ;
+ assertFalse(iter.hasNext()) ;
+ assertFalse(iter.hasNext()) ;
+ }
+
+
+ @Test public void arrayIterator_3()
+ {
+ Iterator<String> iter = create("a", "b", "c") ;
+ assertTrue(iter.hasNext()) ;
+ assertEquals("a", iter.next()) ;
+ assertTrue(iter.hasNext()) ;
+ assertEquals("b", iter.next()) ;
+ assertTrue(iter.hasNext()) ;
+ assertEquals("c", iter.next()) ;
+ assertFalse(iter.hasNext()) ;
+ assertFalse(iter.hasNext()) ;
+ }
+
+ @Test public void arrayIterator_4()
+ {
+ Iterator<String> iter = create("a") ;
+ assertEquals("a", iter.next()) ;
+ try { iter.next() ; fail("Expected NoSuchElementException") ; }
+ catch (NoSuchElementException ex) {}
+ }
+
+ @Test public void arrayIterator_5()
+ {
+ Iterator<String> iter = create(0,1, "a", "b", "c") ;
+ assertEquals("a", iter.next()) ;
+ assertFalse(iter.hasNext()) ;
+ }
+
+ @Test public void arrayIterator_6()
+ {
+ Iterator<String> iter = create(1, 3, "a", "b", "c", "d") ;
+ assertEquals("b", iter.next()) ;
+ assertEquals("c", iter.next()) ;
+ assertFalse(iter.hasNext()) ;
+ }
+
+ @Test public void arrayIterator_7()
+ {
+ IteratorArray<String> iter = create(1, 3, "a", "b", "c", "d") ;
+ assertEquals("b", iter.current()) ;
+ assertEquals("b", iter.current()) ;
+ assertEquals("b", iter.next()) ;
+ assertEquals("c", iter.current()) ;
+ assertEquals("c", iter.next()) ;
+ assertFalse(iter.hasNext()) ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorPeek.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorPeek.java b/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorPeek.java
new file mode 100644
index 0000000..33f0b70
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorPeek.java
@@ -0,0 +1,107 @@
+/*
+ * 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.iterator;
+
+import java.util.ArrayList ;
+import java.util.List ;
+
+import org.apache.jena.atlas.iterator.Iter ;
+import org.apache.jena.atlas.iterator.IteratorArray ;
+import org.apache.jena.atlas.iterator.PeekIterator ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+
+public class TestIteratorPeek extends BaseTest
+{
+ List<String> data0 = new ArrayList<>() ;
+ List<String> data1 = new ArrayList<>() ;
+ {
+ data1.add("a") ;
+ }
+
+ List<String> data2 = new ArrayList<>() ;
+ {
+ data2.add("x") ;
+ data2.add("y") ;
+ data2.add("z") ;
+ }
+
+ @Test public void iter_01()
+ {
+ Iter<String> iter = Iter.iter(data2) ;
+ iter = iter.append(data2.iterator()) ;
+ test(iter, "x", "y", "z", "x", "y", "z") ;
+ }
+
+ private void test(Iter<?> iter, Object... items)
+ {
+ for ( Object x : items )
+ {
+ assertTrue(iter.hasNext()) ;
+ assertEquals(x, iter.next()) ;
+ }
+ assertFalse(iter.hasNext()) ;
+ }
+
+ private static PeekIterator<String> create(String...a)
+ {
+ return new PeekIterator<>(IteratorArray.create(a)) ;
+ }
+
+ @Test public void peek_1()
+ {
+ PeekIterator<String> peek = create("a", "b", "c") ;
+ assertEquals("a", peek.peek()) ;
+ test(Iter.iter(peek), "a", "b", "c") ;
+ }
+
+ @Test public void peek_2()
+ {
+ PeekIterator<String> peek = create() ;
+ assertFalse(peek.hasNext()) ;
+ }
+
+ @Test public void peek_3()
+ {
+ PeekIterator<String> peek = create("a") ;
+ assertEquals("a", peek.peek()) ;
+ }
+
+ @Test public void peek_4()
+ {
+ PeekIterator<String> peek = create("a") ;
+ assertEquals("a", peek.peek()) ;
+ assertEquals("a", peek.peek()) ;
+ assertEquals("a", peek.next()) ;
+ assertFalse(peek.hasNext()) ;
+ }
+
+ @Test public void peek_5()
+ {
+ PeekIterator<String> peek = create("a", "b") ;
+ assertEquals("a", peek.peek()) ;
+ assertEquals("a", peek.peek()) ;
+ assertEquals("a", peek.next()) ;
+ assertTrue(peek.hasNext()) ;
+ assertEquals("b", peek.peek()) ;
+ assertEquals("b", peek.peek()) ;
+ assertEquals("b", peek.next()) ;
+ assertFalse(peek.hasNext()) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorPushback.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorPushback.java b/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorPushback.java
new file mode 100644
index 0000000..51916a3
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorPushback.java
@@ -0,0 +1,93 @@
+/*
+ * 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.iterator;
+
+import java.util.ArrayList ;
+import java.util.List ;
+
+import org.apache.jena.atlas.iterator.Iter ;
+import org.apache.jena.atlas.iterator.PushbackIterator ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+
+public class TestIteratorPushback extends BaseTest
+{
+
+ static List<String> data = new ArrayList<>() ;
+ static {
+ data.add("a") ;
+ data.add("b") ;
+ data.add("c") ;
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void pushback01() { new PushbackIterator<String>(null) ; }
+
+ @Test public void pushback02()
+ {
+ PushbackIterator<String> iter = new PushbackIterator<>(data.iterator()) ;
+ assertEquals("a", iter.next()) ;
+ assertEquals("b", iter.next()) ;
+ assertEquals("c", iter.next()) ;
+ assertFalse(iter.hasNext()) ;
+ }
+
+ @Test public void pushback03()
+ {
+ PushbackIterator<String> iter = new PushbackIterator<>(data.iterator()) ;
+ iter.pushback("x") ;
+ assertEquals("x", iter.next()) ;
+ assertEquals("a", iter.next()) ;
+ assertEquals(2, Iter.count(iter)) ;
+ }
+
+ @Test public void pushback04()
+ {
+ PushbackIterator<String> iter = new PushbackIterator<>(data.iterator()) ;
+ assertEquals("a", iter.next()) ;
+ iter.pushback("x") ;
+ assertEquals("x", iter.next()) ;
+ assertEquals("b", iter.next()) ;
+ assertEquals(1, Iter.count(iter)) ;
+ }
+
+ @Test public void pushback05()
+ {
+ PushbackIterator<String> iter = new PushbackIterator<>(data.iterator()) ;
+ assertEquals("a", iter.next()) ;
+ iter.pushback("x") ;
+ iter.pushback("y") ;
+ assertEquals("y", iter.next()) ;
+ assertEquals("x", iter.next()) ;
+ assertEquals("b", iter.next()) ;
+ assertEquals(1, Iter.count(iter)) ;
+ }
+
+ @Test public void pushback06()
+ {
+ PushbackIterator<String> iter = new PushbackIterator<>(data.iterator()) ;
+ assertEquals(3, Iter.count(iter)) ;
+ iter.pushback("x") ;
+ iter.pushback("y") ;
+ assertEquals("y", iter.next()) ;
+ assertEquals("x", iter.next()) ;
+ assertFalse(iter.hasNext()) ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorSlotted.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorSlotted.java b/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorSlotted.java
new file mode 100644
index 0000000..8abf440
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorSlotted.java
@@ -0,0 +1,136 @@
+/*
+ * 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.iterator;
+
+import java.util.Arrays ;
+import java.util.Collection ;
+import java.util.Iterator ;
+import java.util.List ;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+import org.junit.runner.RunWith ;
+import org.junit.runners.Parameterized ;
+import org.junit.runners.Parameterized.Parameters ;
+
+@RunWith(Parameterized.class)
+
+public class TestIteratorSlotted extends BaseTest
+{
+ @Parameters(name = "{index}: {0}")
+ public static Collection<Object[]> implementations() {
+ IterFactory factory1 = new IterFactory() {
+ @Override
+ public IteratorSlotted<String> create(String... array) {
+ return new IterStr1(array) ;
+ }} ;
+ IterFactory factory2 = new IterFactory() {
+ @Override
+ public IteratorSlotted<String> create(String... array) {
+ return new IterStr2(array) ;
+ }} ;
+ return Arrays.asList(new Object[][] { {"hasMore accurate", factory1}, {"hasMore always true", factory2} }) ;
+ }
+
+ /** Accurate hasMore */
+ static class IterStr1 extends IteratorSlotted<String>
+ {
+ private List<String> array ;
+ private Iterator<String> iter ;
+
+ IterStr1(String... array) {
+ this.array = Arrays.asList(array) ;
+ iter = this.array.iterator() ;
+ }
+
+ @Override
+ protected String moveToNext() {
+ return iter.next() ;
+ }
+
+ @Override
+ protected boolean hasMore() {
+ return iter.hasNext() ;
+ }
+ }
+
+ /** hasMore ios always true, returns null in moveToNext */
+ static class IterStr2 extends IteratorSlotted<String>
+ {
+ private List<String> array ;
+ private Iterator<String> iter ;
+
+ IterStr2(String... array) {
+ this.array = Arrays.asList(array) ;
+ iter = this.array.iterator() ;
+ }
+
+ @Override
+ protected String moveToNext() {
+ if ( !iter.hasNext() )
+ return null ;
+ return iter.next() ;
+ }
+
+ @Override
+ protected boolean hasMore() {
+ return true ;
+ }
+ }
+
+
+ interface IterFactory { IteratorSlotted<String> create(String...array) ; }
+
+
+ private IterFactory factory ;
+
+ public TestIteratorSlotted(String name, IterFactory factory) {
+ this.factory = factory ;
+ }
+
+ @Test public void iter_01()
+ {
+ IteratorSlotted<String> iter = factory.create() ;
+ assertFalse(iter.hasNext()) ;
+ }
+
+ @Test public void iter_02()
+ {
+ IteratorSlotted<String> iter = factory.create("A") ;
+ assertTrue(iter.hasNext()) ;
+ assertEquals("A", iter.peek()) ;
+ assertEquals("A", iter.peek()) ;
+ assertEquals("A", iter.next()) ;
+ assertFalse(iter.hasNext()) ;
+ assertNull(iter.peek()) ;
+ }
+
+ @Test public void iter_03()
+ {
+ IteratorSlotted<String> iter = factory.create("A", "B") ;
+ assertTrue(iter.hasNext()) ;
+ assertEquals("A", iter.peek()) ;
+ assertEquals("A", iter.next()) ;
+ assertEquals("B", iter.peek()) ;
+ assertEquals("B", iter.next()) ;
+ assertFalse(iter.hasNext()) ;
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorWithBuffer.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorWithBuffer.java b/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorWithBuffer.java
new file mode 100644
index 0000000..5bc70fd
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorWithBuffer.java
@@ -0,0 +1,97 @@
+/*
+ * 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.iterator;
+
+import java.util.Arrays ;
+import java.util.List ;
+
+import org.apache.jena.atlas.iterator.IteratorWithBuffer ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+
+public class TestIteratorWithBuffer extends BaseTest
+{
+
+ @Test public void iterBuffer_01()
+ {
+ IteratorWithBuffer<String> iter = createBuffered(1, "a", "b", "c") ;
+ assertEquals(1, iter.currentSize()) ;
+ assertEquals("a", iter.peek(0)) ;
+ assertEquals(1, iter.currentSize()) ;
+ assertEquals("a", iter.next()) ;
+ assertEquals(1, iter.currentSize()) ;
+ assertEquals("b", iter.peek(0)) ;
+ assertEquals(1, iter.currentSize()) ;
+ assertEquals("b", iter.next()) ;
+ assertEquals(1, iter.currentSize()) ;
+ assertEquals("c", iter.peek(0)) ;
+ assertEquals(1, iter.currentSize()) ;
+ assertEquals("c", iter.next()) ;
+ assertEquals(0, iter.currentSize()) ;
+ assertEquals(null, iter.peek(0)) ;
+ assertEquals(0, iter.currentSize()) ;
+ }
+
+ @Test public void iterBuffer_02()
+ {
+ IteratorWithBuffer<String> iter = createBuffered(2, "a", "b", "c") ;
+ assertEquals(2, iter.currentSize()) ;
+ assertEquals("a", iter.peek(0)) ;
+ assertEquals("b", iter.peek(1)) ;
+ assertEquals("a", iter.next()) ;
+
+ assertEquals("b", iter.peek(0)) ;
+ assertEquals("c", iter.peek(1)) ;
+ assertEquals("b", iter.next()) ;
+
+ assertEquals("c", iter.peek(0)) ;
+ assertEquals(null, iter.peek(1)) ;
+ assertEquals("c", iter.next()) ;
+ assertEquals(null, iter.peek(0)) ;
+ }
+
+ @Test public void iterBuffer_03()
+ {
+ IteratorWithBuffer<String> iter = createBuffered(1) ;
+ assertEquals(null, iter.peek(0)) ;
+ }
+
+ @Test(expected=IndexOutOfBoundsException.class)
+ public void iterBuffer_04()
+ {
+ IteratorWithBuffer<String> iter = createBuffered(0, "a") ;
+ assertEquals(null, iter.peek(0)) ;
+ }
+
+ @Test public void iterBuffer_05()
+ {
+ IteratorWithBuffer<String> iter = createBuffered(2, "a") ;
+ assertEquals("a", iter.peek(0)) ;
+ assertEquals(null, iter.peek(1)) ;
+ assertEquals("a", iter.next()) ;
+ }
+
+ private IteratorWithBuffer<String> createBuffered(int N, String... strings)
+ {
+ List<String> data = Arrays.asList(strings) ;
+ IteratorWithBuffer<String> iter = new IteratorWithBuffer<>(data.iterator(), N) ;
+ return iter ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorWithHistory.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorWithHistory.java b/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorWithHistory.java
new file mode 100644
index 0000000..b2545b2
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/iterator/TestIteratorWithHistory.java
@@ -0,0 +1,87 @@
+/*
+ * 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.iterator;
+
+import java.util.Arrays ;
+import java.util.List ;
+
+import org.apache.jena.atlas.iterator.IteratorWithHistory ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+
+public class TestIteratorWithHistory extends BaseTest
+{
+ @Test public void iterHistory_01()
+ {
+ IteratorWithHistory<String> iter = createHistory(1, "a", "b", "c") ;
+ assertEquals(0, iter.currentSize()) ;
+ assertEquals(null, iter.getPrevious(0)) ;
+ }
+
+ @Test public void iterHistory_02()
+ {
+ IteratorWithHistory<String> iter = createHistory(1, "a", "b", "c") ;
+ assertEquals("a", iter.next()) ;
+ assertEquals(1, iter.currentSize()) ;
+ }
+
+ @Test public void iterHistory_03()
+ {
+ IteratorWithHistory<String> iter = createHistory(2, "a", "b", "c") ;
+ assertEquals("a", iter.next()) ;
+ assertEquals("b", iter.next()) ;
+ assertEquals(2, iter.currentSize()) ;
+ assertEquals("b", iter.getPrevious(0)) ;
+ assertEquals("a", iter.getPrevious(1)) ;
+ }
+
+ @Test(expected=IndexOutOfBoundsException.class)
+ public void iterHistory_04()
+ {
+ IteratorWithHistory<String> iter = createHistory(2, "a", "b", "c") ;
+ iter.getPrevious(2) ;
+ }
+
+ @Test
+ public void iterHistory_05()
+ {
+ IteratorWithHistory<String> iter = createHistory(2, "a", "b", "c") ;
+ assertEquals("a", iter.next()) ;
+ assertEquals("a", iter.getPrevious(0)) ;
+ assertEquals(1, iter.currentSize()) ;
+
+ assertEquals("b", iter.next()) ;
+ assertEquals("b", iter.getPrevious(0)) ;
+ assertEquals("a", iter.getPrevious(1)) ;
+ assertEquals(2, iter.currentSize()) ;
+
+ assertEquals("c", iter.next()) ;
+ assertEquals(2, iter.currentSize()) ;
+ assertEquals("c", iter.getPrevious(0)) ;
+ assertEquals("b", iter.getPrevious(1)) ;
+ }
+
+ private IteratorWithHistory<String> createHistory(int N, String... strings)
+ {
+ List<String> data = Arrays.asList(strings) ;
+ IteratorWithHistory<String> iter = new IteratorWithHistory<>(data.iterator(), N) ;
+ return iter ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/junit/BaseTest.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/junit/BaseTest.java b/jena-base/src/test/java/org/apache/jena/atlas/junit/BaseTest.java
new file mode 100644
index 0000000..6d5f15a
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/junit/BaseTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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.junit;
+
+import java.util.ArrayList ;
+import java.util.List ;
+import java.util.Locale ;
+
+import org.junit.Assert ;
+
+public class BaseTest extends Assert
+{
+ public static void assertEqualsIgnoreCase(String msg, String a, String b)
+ {
+ a = a.toLowerCase(Locale.ROOT) ;
+ b = b.toLowerCase(Locale.ROOT) ;
+ assertEquals(msg, a, b) ;
+ }
+
+ public static <T> void assertEqualsUnordered(List<T> list1, List<T> list2) {
+ if ( list1.size() != list2.size() )
+ fail("Expected: "+list1+" : Actual: "+list2) ;
+ List<T> list2a = new ArrayList<>(list2) ;
+ for ( T elt : list1 )
+ list2a.remove(elt) ;
+ if ( list2a.size() != 0 )
+ fail("Expected: "+list1+" : Actual: "+list2) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TS_Lib.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TS_Lib.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TS_Lib.java
new file mode 100644
index 0000000..b91d4ad
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TS_Lib.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.atlas.lib;
+
+
+import org.junit.runner.RunWith ;
+import org.junit.runners.Suite ;
+
+/**
+ * Tests for the Atlas lib package
+ *
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses( {
+ TestAlg.class
+ , TestBitsLong.class
+ , TestBitsInt.class
+ , TestBytes.class
+ , TestHex.class
+ , TestListUtils.class
+ , TestSetUtils.class
+ , TestCache.class
+ , TestCache2.class
+ , TestColumnMap.class
+ , TestFileOps.class
+ , TestStrUtils.class
+ , TestXMLLib.class
+ , TestAlarmClock.class
+ , TestRefLong.class
+ , TestReverseComparator.class
+ , TestTrie.class
+ , TestFilenameProcessing.class
+ , TestMultiSet.class
+ , TestNumberUtils.class
+ , TestDateTimeUtils.class
+} )
+
+public class TS_Lib
+{
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestAlarmClock.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestAlarmClock.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestAlarmClock.java
new file mode 100644
index 0000000..7d2fbfe
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestAlarmClock.java
@@ -0,0 +1,92 @@
+/*
+ * 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.lib ;
+
+import static org.apache.jena.atlas.lib.Lib.sleep ;
+
+import java.util.concurrent.atomic.AtomicInteger ;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+
+public class TestAlarmClock extends BaseTest {
+ AtomicInteger count = new AtomicInteger(0) ;
+ Runnable callback = new Runnable() {
+ @Override
+ public void run() {
+ count.getAndIncrement() ;
+ }
+ } ;
+
+ @Test
+ public void alarm_01() {
+ AlarmClock alarmClock = new AlarmClock() ;
+ // Very long - never happens.
+ alarmClock.add(callback, 10000000) ;
+ alarmClock.cancel(callback) ;
+ assertEquals(0, count.get()) ;
+ alarmClock.release() ;
+ }
+
+ @Test
+ public void alarm_02() {
+ AlarmClock alarmClock = new AlarmClock() ;
+ // Short - happens.
+ alarmClock.add(callback, 10) ;
+ sleep(150) ;
+ assertEquals(1, count.get()) ;
+ // try to cancel anyway.
+ alarmClock.cancel(callback) ;
+ alarmClock.release() ;
+ }
+
+ @Test
+ public void alarm_03() {
+ AlarmClock alarmClock = new AlarmClock() ;
+ alarmClock.add(callback, 10) ;
+ alarmClock.add(callback, 1000000) ;
+ sleep(150) ;
+ // ping1 went off.
+ assertEquals(1, count.get()) ;
+ alarmClock.cancel(callback) ;
+ alarmClock.release() ;
+ }
+
+ @Test
+ public void alarm_04() {
+ AlarmClock alarmClock = new AlarmClock() ;
+ alarmClock.add(callback, 10) ;
+ alarmClock.add(callback, 20) ;
+ sleep(200) ;
+ // ping1 went off. ping2 went off.
+ assertEquals(2, count.get()) ;
+ alarmClock.release() ;
+ }
+
+ @Test
+ public void alarm_05() {
+ AlarmClock alarmClock = new AlarmClock() ;
+ alarmClock.add(callback, 1000) ;
+ alarmClock.reset(callback, 2000) ;
+ sleep(50) ;
+ // The reset should have removed the callback before it happened.
+ assertEquals(0, count.get()) ;
+ alarmClock.release() ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestAlg.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestAlg.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestAlg.java
new file mode 100644
index 0000000..b7eb6e5
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestAlg.java
@@ -0,0 +1,226 @@
+/*
+ * 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.lib;
+
+import java.nio.ByteBuffer ;
+import java.nio.ByteOrder ;
+import java.nio.IntBuffer ;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.Alg ;
+import org.junit.Test ;
+
+public class TestAlg extends BaseTest
+{
+ // Linear search is really there to test binary search.
+ @Test public void linear1()
+ {
+ int[] data = {1, 2, 3} ;
+ IntBuffer b = make(data) ;
+ int idx = 0 ;
+
+ idx = Alg.linearSearch(b, 1) ;
+ assertEquals(0, idx) ;
+
+ idx = Alg.linearSearch(b, 2) ;
+ assertEquals(1, idx) ;
+
+ idx = Alg.linearSearch(b, 3) ;
+ assertEquals(2, idx) ;
+
+ }
+
+ @Test public void linear2()
+ {
+ int[] data = {2, 4, 6} ;
+ IntBuffer b = make(data) ;
+ int idx = 0 ;
+
+ idx = Alg.linearSearch(b, 1) ;
+ assertEquals(-1, idx) ;
+
+ idx = Alg.linearSearch(b, 3) ;
+ assertEquals(-2, idx) ;
+
+ idx = Alg.linearSearch(b, 5) ;
+ assertEquals(-3, idx) ;
+
+ idx = Alg.linearSearch(b, 7) ;
+ assertEquals(-4, idx) ;
+ }
+
+ @Test public void linear3()
+ {
+ int[] data = {} ;
+ IntBuffer b = make(data) ;
+ int idx = Alg.linearSearch(b, 1) ;
+ assertEquals(-1, idx) ;
+ }
+
+ @Test public void linear4()
+ {
+ int[] data = {9} ;
+ IntBuffer b = make(data) ;
+ int idx ;
+ idx = Alg.linearSearch(b, 1) ;
+ assertEquals(-1, idx) ;
+ idx = Alg.linearSearch(b, 9) ;
+ assertEquals(0, idx) ;
+ idx = Alg.linearSearch(b, 100) ;
+ assertEquals(-2, idx) ;
+ }
+
+ @Test public void linear5()
+ {
+ int[] data = {2, 4, 6, 8, 10} ;
+ IntBuffer b = make(data) ;
+ int idx = 0 ;
+ idx = Alg.linearSearch(b, 1, 4, 6) ;
+ assertEquals(2, idx) ;
+
+ idx = Alg.linearSearch(b, 1, 4, 5) ;
+ assertEquals(-3, idx) ;
+
+ idx = Alg.linearSearch(b, 1, 4, 2) ;
+ assertEquals(-2, idx) ;
+
+ idx = Alg.linearSearch(b, 1, 4, 10) ;
+ assertEquals(-5, idx) ;
+ }
+
+ @Test public void linear6()
+ {
+ int[] data = {2, 4, 6, 8, 10} ;
+ IntBuffer b = make(data) ;
+ int idx = 0 ;
+ idx = Alg.linearSearch(b, 3, 3, 6) ;
+ assertEquals(-4, idx) ;
+ idx = Alg.linearSearch(b, 3, 3, 5) ;
+ assertEquals(-4, idx) ;
+ idx = Alg.linearSearch(b, 3, 3, 50) ;
+ assertEquals(-4, idx) ;
+ }
+
+ @Test public void linear7()
+ {
+ int[] data = {2, 4, 4, 8, 8} ;
+ IntBuffer b = make(data) ;
+ int idx = 0 ;
+ idx = Alg.linearSearch(b, 4) ;
+ assertEquals(1, idx) ;
+ idx = Alg.linearSearch(b, 8) ;
+ assertEquals(3, idx) ;
+ }
+
+ @Test public void binary1()
+ {
+ int[] data = {1, 2, 3} ;
+ IntBuffer b = make(data) ;
+ search(b, 1) ;
+ search(b, 2) ;
+ search(b, 3) ;
+ }
+
+ @Test public void binary2()
+ {
+ int[] data = {2, 4, 6} ;
+ IntBuffer b = make(data) ;
+ search(b, 1) ;
+ search(b, 3) ;
+ search(b, 5) ;
+ search(b, 7) ;
+ }
+
+ @Test public void binary3()
+ {
+ int[] data = {} ;
+ IntBuffer b = make(data) ;
+ search(b, 1) ;
+ }
+
+ @Test public void binary4()
+ {
+ int[] data = {9} ;
+ IntBuffer b = make(data) ;
+ search(b, 1) ;
+ search(b, 9) ;
+ search(b, 100) ;
+ }
+
+ @Test public void binary5()
+ {
+ int[] data = {2, 4, 6, 8, 10} ;
+ IntBuffer b = make(data) ;
+ search(b, 6, 1, 4) ;
+ search(b, 5, 1, 4) ;
+ search(b, 2, 1, 4) ;
+ search(b, 10, 1, 4) ;
+ }
+
+ @Test public void binary6()
+ {
+ int[] data = {2, 4, 6, 8, 10} ;
+ IntBuffer b = make(data) ;
+ search(b, 6, 3, 3) ;
+ search(b, 5, 3, 3) ;
+ search(b, 50, 3, 3) ;
+ }
+
+ // Binary serach does not state which index is returned for sequenences of same value
+ @Test public void binary7()
+ {
+ int[] data = {2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8} ;
+ IntBuffer b = make(data) ;
+ int idx = 0 ;
+ idx = Alg.binarySearch(b, 4) ;
+ assertEquals(4, data[idx]) ;
+ idx = Alg.linearSearch(b, 8) ;
+ assertEquals(8, data[idx]) ;
+
+ search(b, 3) ;
+ search(b, 5) ;
+ search(b, 9) ;
+ }
+
+ private static IntBuffer make(int[] data)
+ {
+ //IntBuffer x = IntBuffer.allocate(data.length) ;
+ ByteBuffer z = ByteBuffer.allocate(4*data.length) ;
+ z.order(ByteOrder.BIG_ENDIAN) ;
+ IntBuffer x = z.asIntBuffer() ;
+
+ for ( int i = 0 ; i < data.length ; i++ )
+ x.put(i,data[i]) ;
+ return x ;
+ }
+
+ private static void search(IntBuffer b, int k)
+ {
+ int idx1 = Alg.linearSearch(b, k) ;
+ int idx2 = Alg.binarySearch(b, k) ;
+ assertEquals(idx1, idx2) ;
+ }
+
+ private static void search(IntBuffer b, int k, int low, int high)
+ {
+ int idx1 = Alg.linearSearch(b, low, high, k) ;
+ int idx2 = Alg.binarySearch(b, low, high, k) ;
+ assertEquals(idx1, idx2) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestBitsInt.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestBitsInt.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestBitsInt.java
new file mode 100644
index 0000000..769aeb2
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestBitsInt.java
@@ -0,0 +1,468 @@
+/*
+ * 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.lib;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.BitsInt ;
+import org.junit.Test ;
+
+
+public class TestBitsInt extends BaseTest
+{
+ @Test public void testMask1()
+ {
+ int v = BitsInt.mask(0,1) ;
+ check(0x1, v) ;
+ }
+
+ @Test public void testMask2()
+ {
+ int v = BitsInt.mask(0,2) ;
+ check(0x3, v) ;
+ }
+
+ @Test public void testMask3()
+ {
+ int v = BitsInt.mask(1,2) ;
+ check(0x2, v) ;
+ }
+
+ @Test public void testMask4()
+ {
+ int v = BitsInt.mask(0,32) ;
+ check(-1, v) ;
+ }
+
+ @Test public void testMask5()
+ {
+ int v = BitsInt.mask(16,24) ;
+ check(0x00FF0000, v) ;
+ }
+
+ @Test public void testMask6()
+ {
+ int v = BitsInt.mask(16,32) ;
+ check(0xFFFF0000, v) ;
+ }
+
+ @Test public void testMask7()
+ {
+ int v = BitsInt.mask(0, 0) ;
+ check(0, v) ;
+ }
+
+ @Test public void testMaskZero1()
+ {
+ int v = BitsInt.maskZero(0,1) ;
+ check(~0x1, v) ;
+ }
+
+ @Test public void testMaskZero2()
+ {
+ int v = BitsInt.maskZero(0,2) ;
+ check(~0x3, v) ;
+ }
+
+ @Test public void testMaskZero3()
+ {
+ int v = BitsInt.maskZero(1,2) ;
+ check(0xFFFFFFFD, v) ;
+ }
+
+ @Test public void testMaskZero4()
+ {
+ int v = BitsInt.maskZero(0,32) ;
+ check(0, v) ;
+ }
+
+ @Test public void testMaskZero5()
+ {
+ int v = BitsInt.maskZero(16,24) ;
+ check(0xFF00FFFF, v) ;
+ }
+
+ @Test public void testMaskZero6()
+ {
+ int v = BitsInt.maskZero(16,32) ;
+ check(0xFFFF, v) ;
+ }
+
+ @Test public void testMaskZero7()
+ {
+ int v = BitsInt.maskZero(0, 0) ;
+ check(-1, v) ;
+ }
+
+ @Test public void testClear1()
+ {
+ int v = 0xF0F0 ;
+ v = BitsInt.clear(v, 4, 8) ;
+ String s = Integer.toHexString(v) ;
+ check(0xF000, v ) ;
+ }
+
+ @Test public void testClear2()
+ {
+ int v = 0x80000000;
+ v = BitsInt.clear(v, 31, 32) ;
+ String s = Integer.toHexString(v) ;
+ check(0x0, v ) ;
+ }
+
+ @Test public void testClear3()
+ {
+ int v = 0xC0000000;
+ v = BitsInt.clear(v, 31, 32) ;
+ String s = Integer.toHexString(v) ;
+ check(0x40000000, v ) ;
+ }
+
+ @Test public void testClear4()
+ {
+ int v = -1 ;
+ v = BitsInt.clear(v, 31, 32) ;
+ String s = Integer.toHexString(v) ;
+ check(0x7FFFFFFF, v ) ;
+ }
+
+ @Test public void testClear5()
+ {
+ int v = -1 ;
+ v = BitsInt.clear(v, 16, 32) ;
+ String s = Integer.toHexString(v) ;
+ check(0x0000FFFF, v ) ;
+ }
+
+ @Test public void testClear6()
+ {
+ int v = -1 ;
+ v = BitsInt.clear(v, 0, 16) ;
+ String s = Integer.toHexString(v) ;
+ check(0xFFFF0000, v ) ;
+ }
+
+ @Test public void testClear7()
+ {
+ int v = -1 ;
+ v = BitsInt.clear(v, 0, 0) ;
+ String s = Integer.toHexString(v) ;
+ check(-1, v ) ;
+ }
+
+ @Test public void testSet1()
+ {
+ int v = 0x0 ;
+ v = BitsInt.set(v, 0, 1) ;
+ check(1, v) ;
+ }
+
+ @Test public void testSet2()
+ {
+ int v = 0x1 ;
+ v = BitsInt.set(v, 0, 1) ;
+ check(1, v) ;
+ }
+
+ @Test public void testSet3()
+ {
+ int v = 0xF0 ;
+ v = BitsInt.set(v, 0, 1) ;
+ check(0xF1, v) ;
+ }
+
+ @Test public void testSet4()
+ {
+ int v = 0xF0F0F0F0 ;
+ v = BitsInt.set(v, 0, 8) ;
+ check(0xF0F0F0FF, v) ;
+ }
+
+ @Test public void testSet5()
+ {
+ int v = 0 ;
+ v = BitsInt.set(v, 16, 24) ;
+ check(0x00FF0000, v) ;
+ }
+
+ @Test public void testSet6()
+ {
+ int v = 0 ;
+ v = BitsInt.set(v, 31, 32) ;
+ check(0x80000000, v) ;
+ }
+
+ @Test public void testSet7()
+ {
+ int v = 0 ;
+ v = BitsInt.set(v, 30, 32) ;
+ check(0xC0000000, v) ;
+ }
+
+ @Test public void testSet8()
+ {
+ int v = 0 ;
+ v = BitsInt.set(v, 0, 32) ;
+ check(-1, v) ;
+ }
+
+ @Test public void testSet9()
+ {
+ int v = 0 ;
+ v = BitsInt.set(v, 10, 10) ;
+ check(0, v) ;
+ }
+
+ @Test public void testSetBit1()
+ {
+ int v = 0 ;
+ v = BitsInt.set(v, 0) ;
+ check(1, v) ;
+ }
+
+ @Test public void testSetBit2()
+ {
+ int v = 0 ;
+ v = BitsInt.set(v, 1) ;
+ check(2, v) ;
+ }
+
+ @Test public void testSetBit3()
+ {
+ int v = 1 ;
+ v = BitsInt.set(v, 0) ;
+ check(1, v) ;
+ }
+
+ @Test public void testSetBit4()
+ {
+ int v = -1 ;
+ v = BitsInt.set(v, 0) ;
+ check(-1, v) ;
+ }
+
+ @Test public void testSetBit5()
+ {
+ int v = 0 ;
+ v = BitsInt.set(v, 30) ;
+ check(0x40000000, v) ;
+ }
+
+ @Test public void testSetBit6()
+ {
+ int v = 0 ;
+ v = BitsInt.set(v, 31) ;
+ check(0x80000000, v) ;
+ }
+
+ @Test public void testBitTest1()
+ {
+ int v = 0 ;
+ assertTrue(BitsInt.test(v, false, 0)) ;
+ }
+
+ @Test public void testBitTest2()
+ {
+ int v = 1 ;
+ assertTrue(BitsInt.test(v, true, 0)) ;
+ }
+
+ @Test public void testBitTest3()
+ {
+ int v = -1 ;
+ assertTrue(BitsInt.test(v, true, 31)) ;
+ }
+
+ @Test public void testBitTest4()
+ {
+ int v = 0x7FFFFFFF ;
+ assertTrue(BitsInt.test(v, false, 31)) ;
+ }
+
+ @Test public void testBitsTest1()
+ {
+ int v = 0x76543210 ;
+ assertTrue(BitsInt.test(v, 0x0, 0, 4)) ;
+ }
+
+ @Test public void testBitsTest2()
+ {
+ int v = 0x76543210 ;
+ assertTrue(BitsInt.test(v, 0x10, 0, 8)) ;
+ }
+
+ @Test public void testBitsTest3()
+ {
+ int v = 0x76543210 ;
+ assertTrue(BitsInt.test(v, v, 0, 32)) ;
+ }
+
+ @Test public void testBitsTest4()
+ {
+ int v = 0x76543210 ;
+ assertFalse(BitsInt.test(v, 0, 0, 32)) ;
+ }
+
+ @Test public void testBitsTest5()
+ {
+ int v = 0x76543210 ;
+ assertTrue(BitsInt.test(v, 0x00543200, 8, 24)) ;
+ }
+
+ @Test public void testIsSet1()
+ {
+ int v = 0x00000010 ;
+ BitsInt.isSet(v, 4) ;
+ assertTrue(BitsInt.isSet(v, 4)) ;
+ assertFalse(BitsInt.isSet(v, 3)) ;
+ assertFalse(BitsInt.isSet(v, 5)) ;
+ }
+
+ @Test public void testAccess1()
+ {
+ int v = -1 ;
+ v = BitsInt.access(v, 4, 8) ;
+ check(0xF0, v ) ;
+ }
+
+ @Test public void testAccess2()
+ {
+ int v = 0x76543210 ;
+ v = BitsInt.access(v, 0, 8) ;
+ check(0x10, v ) ;
+ }
+
+ @Test public void testAccess3()
+ {
+ int v = 0x76543210 ;
+ v = BitsInt.access(v, 0, 32) ;
+ check(0x76543210, v ) ;
+ }
+
+ @Test public void testAccess4()
+ {
+ int v = 0xFEF43210 ;
+ v = BitsInt.access(v, 30, 32) ;
+ check(0xC0000000, v ) ;
+ }
+
+ @Test public void testAccess5()
+ {
+ int v = 0x76543210 ;
+ v = BitsInt.access(v, 0, 2) ;
+ check(0, v ) ;
+ }
+
+ @Test public void testPack1()
+ {
+ int v = 0 ;
+ v = BitsInt.pack(v, 0xF, 0, 4) ;
+ check(0xF, v ) ;
+ }
+
+ @Test public void testPack2()
+ {
+ int v = 0xF0 ;
+ v = BitsInt.pack(v, 0x2, 0, 4) ;
+ check(0xF2, v ) ;
+ }
+
+ @Test public void testPack3()
+ {
+ int v = -1 ;
+ v = BitsInt.pack(v, 0x2, 0, 8) ;
+ check(0xFFFFFF02, v ) ;
+ }
+
+ @Test public void testPack4()
+ {
+ int v = 0xFFFF0000 ;
+ v = BitsInt.pack(v, 0x2, 8, 16) ;
+ check(0xFFFF0200, v ) ;
+ }
+
+ @Test public void testPack5()
+ {
+ int v = 0xFFFF0000 ;
+ v = BitsInt.pack(v, 0xFF, 8, 16) ;
+ check(0xFFFFFF00, v ) ;
+ }
+
+ @Test public void testUnpack1()
+ {
+ int v = 0xABCDABCD ;
+ v = BitsInt.unpack(v, 0, 4) ;
+ check(0xD, v ) ;
+ }
+
+ @Test public void testUnpack2()
+ {
+ int v = 0xABCDABCD ;
+ v = BitsInt.unpack(v, 31, 32) ;
+ check(1, v ) ;
+ }
+
+ @Test public void testUnpack3()
+ {
+ int v = 0xABCDABCD ;
+ v = BitsInt.unpack(v, 24, 32) ;
+ check(0xAB, v ) ;
+ }
+
+ @Test public void testUnpack4()
+ {
+ int v = 0xAB1234CD ;
+ v = BitsInt.unpack(v, 8, 24) ;
+ check(0x1234, v ) ;
+ }
+
+ @Test public void testUnpackStr1()
+ {
+ String s = "ABCD" ;
+ int v = BitsInt.unpack(s, 0, 4) ;
+ check(0xABCD, v ) ;
+ }
+
+ @Test public void testUnpackStr2()
+ {
+ String s = "ABCD" ;
+ int v = BitsInt.unpack(s, 2, 4) ;
+ check(0xCD, v ) ;
+ }
+
+ @Test public void testUnpackStr3()
+ {
+ String s = "ABCD" ;
+ int v = BitsInt.unpack(s, 0, 2) ;
+ check(0xAB, v ) ;
+ }
+
+ private void check(int expected, int actual)
+ {
+ check(null, expected, actual) ;
+ }
+
+ private void check(String msg, int expected, int actual)
+ {
+ if ( expected == actual ) return ;
+ String s = "Expected: "+Integer.toHexString(expected)+" : Got: "+Integer.toHexString(actual) ;
+ if ( msg != null )
+ s = msg+": "+s ;
+ assertFalse(s, true) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestBitsLong.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestBitsLong.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestBitsLong.java
new file mode 100644
index 0000000..1fea546
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestBitsLong.java
@@ -0,0 +1,468 @@
+/*
+ * 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.lib;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.BitsLong ;
+import org.junit.Test ;
+
+
+public class TestBitsLong extends BaseTest
+{
+ @Test public void testMask1()
+ {
+ long v = BitsLong.mask(0,1) ;
+ check(0x1L, v) ;
+ }
+
+ @Test public void testMask2()
+ {
+ long v = BitsLong.mask(0,2) ;
+ check(0x3L, v) ;
+ }
+
+ @Test public void testMask3()
+ {
+ long v = BitsLong.mask(1,2) ;
+ check(0x2L, v) ;
+ }
+
+ @Test public void testMask4()
+ {
+ long v = BitsLong.mask(0,64) ;
+ check(-1L, v) ;
+ }
+
+ @Test public void testMask5()
+ {
+ long v = BitsLong.mask(16,48) ;
+ check(0x0000FFFFFFFF0000L, v) ;
+ }
+
+ @Test public void testMask6()
+ {
+ long v = BitsLong.mask(16,64) ;
+ check(0xFFFFFFFFFFFF0000L, v) ;
+ }
+
+ @Test public void testMask7()
+ {
+ long v = BitsLong.mask(0, 0) ;
+ check(0L, v) ;
+ }
+
+ @Test public void testMaskZero1()
+ {
+ long v = BitsLong.maskZero(0,1) ;
+ check(~0x1L, v) ;
+ }
+
+ @Test public void testMaskZero2()
+ {
+ long v = BitsLong.maskZero(0,2) ;
+ check(~0x3L, v) ;
+ }
+
+ @Test public void testMaskZero3()
+ {
+ long v = BitsLong.maskZero(1,2) ;
+ check(0xFFFFFFFFFFFFFFFDL, v) ;
+ }
+
+ @Test public void testMaskZero4()
+ {
+ long v = BitsLong.maskZero(0,64) ;
+ check(0, v) ;
+ }
+
+ @Test public void testMaskZero5()
+ {
+ long v = BitsLong.maskZero(16,48) ;
+ check(0xFFFF00000000FFFFL, v) ;
+ }
+
+ @Test public void testMaskZero6()
+ {
+ long v = BitsLong.maskZero(16,64) ;
+ check(0xFFFFL, v) ;
+ }
+
+ @Test public void testMaskZero7()
+ {
+ long v = BitsLong.maskZero(0, 0) ;
+ check(-1L, v) ;
+ }
+
+ @Test public void testClear1()
+ {
+ long v = 0xF0F0 ;
+ v = BitsLong.clear(v, 4, 8) ;
+ String s = Long.toHexString(v) ;
+ check(0xF000L, v ) ;
+ }
+
+ @Test public void testClear2()
+ {
+ long v = 0x8000000000000000L;
+ v = BitsLong.clear(v, 63, 64) ;
+ String s = Long.toHexString(v) ;
+ check(0x0L, v ) ;
+ }
+
+ @Test public void testClear3()
+ {
+ long v = 0xC000000000000000L;
+ v = BitsLong.clear(v, 63, 64) ;
+ String s = Long.toHexString(v) ;
+ check(0x4000000000000000L, v ) ;
+ }
+
+ @Test public void testClear4()
+ {
+ long v = -1 ;
+ v = BitsLong.clear(v, 63, 64) ;
+ String s = Long.toHexString(v) ;
+ check(0x7FFFFFFFFFFFFFFFL, v ) ;
+ }
+
+ @Test public void testClear5()
+ {
+ long v = -1 ;
+ v = BitsLong.clear(v, 32, 64) ;
+ String s = Long.toHexString(v) ;
+ check(0x00000000FFFFFFFFL, v ) ;
+ }
+
+ @Test public void testClear6()
+ {
+ long v = -1 ;
+ v = BitsLong.clear(v, 0, 32) ;
+ String s = Long.toHexString(v) ;
+ check(0xFFFFFFFF00000000L, v ) ;
+ }
+
+ @Test public void testClear7()
+ {
+ long v = -1L ;
+ v = BitsLong.clear(v, 0, 0) ;
+ String s = Long.toHexString(v) ;
+ check(-1L, v ) ;
+ }
+
+ @Test public void testSet1()
+ {
+ long v = 0x0 ;
+ v = BitsLong.set(v, 0, 1) ;
+ check(1, v) ;
+ }
+
+ @Test public void testSet2()
+ {
+ long v = 0x1 ;
+ v = BitsLong.set(v, 0, 1) ;
+ check(1, v) ;
+ }
+
+ @Test public void testSet3()
+ {
+ long v = 0xF0 ;
+ v = BitsLong.set(v, 0, 1) ;
+ check(0xF1, v) ;
+ }
+
+ @Test public void testSet4()
+ {
+ long v = 0xF0F0F0F0F0F0F0F0L ;
+ v = BitsLong.set(v, 0, 8) ;
+ check(0xF0F0F0F0F0F0F0FFL, v) ;
+ }
+
+ @Test public void testSet5()
+ {
+ long v = 0 ;
+ v = BitsLong.set(v, 16, 48) ;
+ check(0x0000FFFFFFFF0000L, v) ;
+ }
+
+ @Test public void testSet6()
+ {
+ long v = 0 ;
+ v = BitsLong.set(v, 63, 64) ;
+ check(0x8000000000000000L, v) ;
+ }
+
+ @Test public void testSet7()
+ {
+ long v = 0 ;
+ v = BitsLong.set(v, 62, 64) ;
+ check(0xC000000000000000L, v) ;
+ }
+
+ @Test public void testSet8()
+ {
+ long v = 0 ;
+ v = BitsLong.set(v, 0, 64) ;
+ check(-1L, v) ;
+ }
+
+ @Test public void testSet9()
+ {
+ long v = 0 ;
+ v = BitsLong.set(v, 10, 10) ;
+ check(0, v) ;
+ }
+
+ @Test public void testSetBit1()
+ {
+ long v = 0 ;
+ v = BitsLong.set(v, 0) ;
+ check(1, v) ;
+ }
+
+ @Test public void testSetBit2()
+ {
+ long v = 0 ;
+ v = BitsLong.set(v, 1) ;
+ check(2, v) ;
+ }
+
+ @Test public void testSetBit3()
+ {
+ long v = 1 ;
+ v = BitsLong.set(v, 0) ;
+ check(1, v) ;
+ }
+
+ @Test public void testSetBit4()
+ {
+ long v = -1 ;
+ v = BitsLong.set(v, 0) ;
+ check(-1, v) ;
+ }
+
+ @Test public void testSetBit5()
+ {
+ long v = 0 ;
+ v = BitsLong.set(v, 62) ;
+ check(0x4000000000000000L, v) ;
+ }
+
+ @Test public void testSetBit6()
+ {
+ long v = 0 ;
+ v = BitsLong.set(v, 63) ;
+ check(0x8000000000000000L, v) ;
+ }
+
+ @Test public void testBitTest1()
+ {
+ long v = 0 ;
+ assertTrue(BitsLong.test(v, false, 0)) ;
+ }
+
+ @Test public void testBitTest2()
+ {
+ long v = 1 ;
+ assertTrue(BitsLong.test(v, true, 0)) ;
+ }
+
+ @Test public void testBitTest3()
+ {
+ long v = -1 ;
+ assertTrue(BitsLong.test(v, true, 63)) ;
+ }
+
+ @Test public void testBitTest4()
+ {
+ long v = 0x7FFFFFFFFFFFFFFFL ;
+ assertTrue(BitsLong.test(v, false, 63)) ;
+ }
+
+ @Test public void testBitsTest1()
+ {
+ long v = 0xFEDCBA9876543210L ;
+ assertTrue(BitsLong.test(v, 0x0, 0, 4)) ;
+ }
+
+ @Test public void testBitsTest2()
+ {
+ long v = 0xFEDCBA9876543210L ;
+ assertTrue(BitsLong.test(v, 0x10, 0, 8)) ;
+ }
+
+ @Test public void testBitsTest3()
+ {
+ long v = 0xFEDCBA9876543210L ;
+ assertTrue(BitsLong.test(v, v, 0, 64)) ;
+ }
+
+ @Test public void testBitsTest4()
+ {
+ long v = 0xFEDCBA9876543210L ;
+ assertFalse(BitsLong.test(v, 0, 0, 64)) ;
+ }
+
+ @Test public void testBitsTest5()
+ {
+ long v = 0xFEDCBA9876543210L ;
+ assertTrue(BitsLong.test(v, 0x0000BA9876540000L, 16, 48)) ;
+ }
+
+ @Test public void testIsSet1()
+ {
+ long v = 0x0000000000000010L ;
+ BitsLong.isSet(v, 4) ;
+ assertTrue(BitsLong.isSet(v, 4)) ;
+ assertFalse(BitsLong.isSet(v, 3)) ;
+ assertFalse(BitsLong.isSet(v, 5)) ;
+ }
+
+ @Test public void testAccess1()
+ {
+ long v = -1 ;
+ v = BitsLong.access(v, 4, 8) ;
+ check(0xF0L, v ) ;
+ }
+
+ @Test public void testAccess2()
+ {
+ long v = 0xFEDCBA9876543210L ;
+ v = BitsLong.access(v, 0, 8) ;
+ check(0x10L, v ) ;
+ }
+
+ @Test public void testAccess3()
+ {
+ long v = 0xFEDCBA9876543210L ;
+ v = BitsLong.access(v, 0, 64) ;
+ check(0xFEDCBA9876543210L, v ) ;
+ }
+
+ @Test public void testAccess4()
+ {
+ long v = 0xFEDCBA9876543210L ;
+ v = BitsLong.access(v, 62, 64) ;
+ check(0xC000000000000000L, v ) ;
+ }
+
+ @Test public void testAccess5()
+ {
+ long v = 0xFEDCBA9876543210L ;
+ v = BitsLong.access(v, 0, 2) ;
+ check(0L, v ) ;
+ }
+
+ @Test public void testPack1()
+ {
+ long v = 0 ;
+ v = BitsLong.pack(v, 0xFL, 0, 4) ;
+ check(0xFL, v ) ;
+ }
+
+ @Test public void testPack2()
+ {
+ long v = 0xF0 ;
+ v = BitsLong.pack(v, 0x2, 0, 4) ;
+ check(0xF2L, v ) ;
+ }
+
+ @Test public void testPack3()
+ {
+ long v = -1 ;
+ v = BitsLong.pack(v, 0x2, 0, 8) ;
+ check(0xFFFFFFFFFFFFFF02L, v ) ;
+ }
+
+ @Test public void testPack4()
+ {
+ long v = 0xFFFFFFFF00000000L ;
+ v = BitsLong.pack(v, 0x2, 16, 32) ;
+ check(0xFFFFFFFF00020000L, v ) ;
+ }
+
+ @Test public void testPack5()
+ {
+ long v = 0xFFFFFFFF00000000L ;
+ v = BitsLong.pack(v, 0xFFFF, 16, 32) ;
+ check(0xFFFFFFFFFFFF0000L, v ) ;
+ }
+
+ @Test public void testUnpack1()
+ {
+ long v = 0xABCDABCDABCDABCDL ;
+ v = BitsLong.unpack(v, 0, 4) ;
+ check(0xDL, v ) ;
+ }
+
+ @Test public void testUnpack2()
+ {
+ long v = 0xABCDABCDABCDABCDL ;
+ v = BitsLong.unpack(v, 63, 64) ;
+ check(1L, v ) ;
+ }
+
+ @Test public void testUnpack3()
+ {
+ long v = 0xABCDABCDABCDABCDL ;
+ v = BitsLong.unpack(v, 56, 64) ;
+ check(0xABL, v ) ;
+ }
+
+ @Test public void testUnpack4()
+ {
+ long v = 0xABCD12345678ABCDL ;
+ v = BitsLong.unpack(v, 32, 48) ;
+ check(0x1234L, v ) ;
+ }
+
+ @Test public void testUnpackStr1()
+ {
+ String s = "ABCD" ;
+ long v = BitsLong.unpack(s, 0, 4) ;
+ check(0xABCDL, v ) ;
+ }
+
+ @Test public void testUnpackStr2()
+ {
+ String s = "ABCD" ;
+ long v = BitsLong.unpack(s, 2, 4) ;
+ check(0xCDL, v ) ;
+ }
+
+ @Test public void testUnpackStr3()
+ {
+ String s = "ABCD" ;
+ long v = BitsLong.unpack(s, 0, 2) ;
+ check(0xABL, v ) ;
+ }
+
+ private void check(long expected, long actual)
+ {
+ check(null, expected, actual) ;
+ }
+
+ private void check(String msg, long expected, long actual)
+ {
+ if ( expected == actual ) return ;
+ String s = "Expected: "+Long.toHexString(expected)+" : Got: "+Long.toHexString(actual) ;
+ if ( msg != null )
+ s = msg+": "+s ;
+ assertFalse(s, true) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/test/java/org/apache/jena/atlas/lib/TestBytes.java
----------------------------------------------------------------------
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/lib/TestBytes.java b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestBytes.java
new file mode 100644
index 0000000..a857509
--- /dev/null
+++ b/jena-base/src/test/java/org/apache/jena/atlas/lib/TestBytes.java
@@ -0,0 +1,198 @@
+/*
+ * 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.lib;
+
+import java.nio.ByteBuffer ;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.Bytes ;
+import org.junit.Test ;
+
+public class TestBytes extends BaseTest
+{
+ @Test public void packInt1()
+ {
+ byte[] b = new byte[4] ;
+ Bytes.setInt(0x01020304,b) ;
+ assertEquals(0x01, b[0]) ;
+ assertEquals(0x02, b[1]) ;
+ assertEquals(0x03, b[2]) ;
+ assertEquals(0x04, b[3]) ;
+ }
+
+ @Test public void packInt2()
+ {
+ byte[] b = new byte[8] ;
+ Bytes.setInt(0x01020304,b,0) ;
+ Bytes.setInt(0x05060708,b,4) ;
+ assertEquals(0x01, b[0]) ;
+ assertEquals(0x02, b[1]) ;
+ assertEquals(0x03, b[2]) ;
+ assertEquals(0x04, b[3]) ;
+ assertEquals(0x05, b[4]) ;
+ assertEquals(0x06, b[5]) ;
+ assertEquals(0x07, b[6]) ;
+ assertEquals(0x08, b[7]) ;
+ }
+
+ @Test public void packInt3()
+ {
+ byte[] b = new byte[4] ;
+ Bytes.setInt(0xF1F2F3F4,b) ;
+ int i = Bytes.getInt(b) ;
+ assertEquals(0xF1F2F3F4, i) ;
+ }
+
+ @Test public void packInt4()
+ {
+ byte[] b = new byte[8] ;
+ Bytes.setInt(0x01020304,b,0) ;
+ Bytes.setInt(0x05060708,b,4) ;
+
+ int i1 = Bytes.getInt(b,0) ;
+ int i2 = Bytes.getInt(b,4) ;
+ assertEquals(0x01020304, i1) ;
+ assertEquals(0x05060708, i2) ;
+ }
+
+ @Test public void packLong5()
+ {
+ byte[] b = new byte[8] ;
+ Bytes.setLong(0x0102030405060708L,b) ;
+ assertEquals(0x01, b[0]) ;
+ assertEquals(0x02, b[1]) ;
+ assertEquals(0x03, b[2]) ;
+ assertEquals(0x04, b[3]) ;
+ assertEquals(0x05, b[4]) ;
+ assertEquals(0x06, b[5]) ;
+ assertEquals(0x07, b[6]) ;
+ assertEquals(0x08, b[7]) ;
+ }
+
+ @Test public void packLong6()
+ {
+ byte[] b = new byte[16] ;
+ Bytes.setLong(0x0102030405060708L,b,0) ;
+ Bytes.setLong(0x1112131415161718L,b,8) ;
+ assertEquals(0x01, b[0]) ;
+ assertEquals(0x02, b[1]) ;
+ assertEquals(0x03, b[2]) ;
+ assertEquals(0x04, b[3]) ;
+ assertEquals(0x05, b[4]) ;
+ assertEquals(0x06, b[5]) ;
+ assertEquals(0x07, b[6]) ;
+ assertEquals(0x08, b[7]) ;
+
+ assertEquals(0x11, b[0+8]) ;
+ assertEquals(0x12, b[1+8]) ;
+ assertEquals(0x13, b[2+8]) ;
+ assertEquals(0x14, b[3+8]) ;
+ assertEquals(0x15, b[4+8]) ;
+ assertEquals(0x16, b[5+8]) ;
+ assertEquals(0x17, b[6+8]) ;
+ assertEquals(0x18, b[7+8]) ;
+ }
+
+ @Test public void packLong7()
+ {
+ byte[] b = new byte[8] ;
+ Bytes.setLong(0xF1F2F3F4F5F6F7F8L,b) ;
+ long i = Bytes.getLong(b) ;
+ assertEquals (0xF1F2F3F4F5F6F7F8L,i) ;
+ }
+
+ @Test public void packLong8()
+ {
+ byte[] b = new byte[16] ;
+ Bytes.setLong(0xF1F2F3F4F5F6F7F8L,b,0) ;
+ Bytes.setLong(0xA1A2A3A4A5A6A7A8L,b,8) ;
+
+ long i1 = Bytes.getLong(b,0) ;
+ long i2 = Bytes.getLong(b,8) ;
+ assertEquals(0xF1F2F3F4F5F6F7F8L,i1) ;
+ assertEquals(0xA1A2A3A4A5A6A7A8L,i2) ;
+ }
+
+ @Test public void compare1() { compare(0, new byte[]{}, new byte[]{}) ; }
+ @Test public void compare2() { compare(+1, new byte[]{1}, new byte[]{}) ; }
+ @Test public void compare3() { compare(-1, new byte[]{1}, new byte[]{1,2}) ; }
+
+ @Test public void compare4() { compare(+1, new byte[]{1,3}, new byte[]{1,2}) ; }
+ @Test public void compare5() { compare(+1, new byte[]{1,3}, new byte[]{1,2,3}) ; }
+ @Test public void compare6() { compare(-1, new byte[]{1,2}, new byte[]{1,2,3}) ; }
+
+ byte[] bytes = { 1, 2, 3, 4, 5, 6 } ;
+
+ @Test public void slice1()
+ {
+ byte[] x = Bytes.copyOf(bytes) ;
+ assertArrayEquals(bytes, x) ;
+ }
+
+ @Test public void slice3()
+ {
+ byte[] x = Bytes.copyOf(bytes,3) ;
+ byte[] y = new byte[]{4,5,6} ;
+ assertArrayEquals(y, x) ;
+ }
+
+ @Test public void slice2()
+ {
+ byte[] x = Bytes.copyOf(bytes,3,2) ;
+ byte[] y = new byte[]{4,5} ;
+ assertArrayEquals(y, x) ;
+ }
+
+ private static void compare(int expected, byte[] b1, byte[] b2)
+ {
+ int x = Bytes.compare(b1, b2) ;
+ if ( x > 0 && expected > 0 ) return ;
+ if ( x == 0 && expected == 0 ) return ;
+ if ( x < 0 && expected < 0 ) return ;
+ fail("Does not compare: "+Bytes.asHex(b1)+" :: "+Bytes.asHex(b2)) ;
+ }
+
+ private static void codec(String str)
+ {
+ ByteBuffer bb = ByteBuffer.allocate(16) ;
+ Bytes.toByteBuffer(str, bb) ;
+ bb.flip() ;
+ String str2 = Bytes.fromByteBuffer(bb) ;
+ assertEquals(str, str2) ;
+ }
+
+ static private final String asciiBase = "abc" ;
+ static private final String latinBase = "Àéíÿ" ;
+ static private final String latinExtraBase = "ỹfifl" ; // fi-ligature, fl-ligature
+ static private final String greekBase = "αβγ" ;
+ static private final String hewbrewBase = "אבג" ;
+ static private final String arabicBase = "ءآأ";
+ static private final String symbolsBase = "☺☻♪♫" ;
+ static private final String chineseBase = "孫子兵法" ; // The Art of War
+ static private final String japaneseBase = "日本" ; // Japanese
+
+ @Test public void codec1() { codec(asciiBase) ; }
+ @Test public void codec2() { codec("") ; }
+ @Test public void codec3() { codec(greekBase) ; }
+ @Test public void codec4() { codec(hewbrewBase) ; }
+ @Test public void codec5() { codec(arabicBase) ; }
+ @Test public void codec6() { codec(symbolsBase) ; }
+ @Test public void codec7() { codec(chineseBase) ; }
+ @Test public void codec8() { codec(japaneseBase) ; }
+}
[5/9] jena git commit: Import of lib, io,
logging and iterator packages
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/FileOps.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/FileOps.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/FileOps.java
new file mode 100644
index 0000000..6862f4a
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/FileOps.java
@@ -0,0 +1,239 @@
+/*
+ * 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.lib ;
+
+import java.io.File ;
+import java.io.FileInputStream ;
+import java.io.FileOutputStream ;
+import java.io.IOException ;
+import java.nio.channels.FileChannel ;
+
+import org.apache.jena.atlas.AtlasException ;
+import org.apache.jena.atlas.io.IO ;
+import org.apache.jena.atlas.logging.Log ;
+
+/** A library of utility operations on files and the filing system */
+public class FileOps {
+ // Update implementations as standard library functions appear that meet the contract.
+ private FileOps() {}
+
+ /**
+ * Delete a file
+ *
+ * @param filename
+ */
+ public static void delete(String filename) {
+ delete(new File(filename), true) ;
+ }
+
+ /* Delete a file - don't check it worked */
+
+ public static void deleteSilent(String filename) {
+ delete(new File(filename), false) ;
+ }
+
+ public static void delete(File f, boolean reportExistsAfter) {
+ try {
+ /*
+ * Note: On windows, deleting a file which has been memory mapped
+ * does not delete the file.
+ */
+ f.delete() ;
+ if ( reportExistsAfter && f.exists() )
+ Log.warn(FileOps.class, "delete: *** File still exists: " + f) ;
+ }
+ catch (SecurityException ex) {
+ Log.warn(FileOps.class, "delete: " + f + ": Security exception; " + ex.getMessage()) ;
+ }
+
+ }
+
+ /** Delete all files in a directory */
+ public static void clearDirectory(String dir) {
+ File d = new File(dir) ;
+ for ( File f : d.listFiles() ) {
+ if ( f.isFile() )
+ delete(f, false) ;
+ }
+ }
+
+ /** Delete all files and directories (recursively) in a directory */
+ public static void clearAll(String d) {
+ clearAll(new File(d)) ;
+ }
+
+ /** Delete all files and directories (recursively) in a directory */
+ public static void clearAll(File d) {
+ if ( ! d.exists() )
+ return ;
+
+ for ( File f : d.listFiles() ) {
+ if ( ".".equals(f.getName()) || "..".equals(f.getName()) )
+ continue ;
+ if ( f.isDirectory() )
+ clearAll(f) ;
+ f.delete() ;
+ }
+ }
+
+ /** See if there are any files in this directory */
+ public static boolean existsAnyFiles(String dir) {
+ File d = new File(dir) ;
+ File[] entries = d.listFiles() ;
+ if ( entries == null )
+ // Not a directory
+ return false ;
+ return entries.length > 0 ;
+ }
+
+ /** Test for existence */
+ public static boolean exists(String path) {
+ File f = new File(path) ;
+ return f.exists() ;
+ }
+
+ /** Test for an empty file */
+ public static boolean isEmpty(String filename) {
+ File f = new File(filename) ;
+ if ( f.exists() )
+ return true ;
+ if ( f.isFile() )
+ return f.length() == 0 ;
+ throw new AtlasException("Not a file") ;
+ }
+
+ /** Ensure a directory exists */
+ public static void ensureDir(String dirname) {
+ File dir = new File(dirname) ;
+ if ( !dir.exists() )
+ dir.mkdirs() ;
+ }
+
+ /**
+ * Split a file name into path, basename and extension. Nulls returned if
+ * don't make sense.
+ */
+ public static Tuple<String> splitDirBaseExt(String filename) {
+ String path = null ;
+ String basename = filename ;
+ String ext = null ;
+
+ int j = filename.lastIndexOf('/') ;
+ if ( j < 0 )
+ j = filename.lastIndexOf('\\') ;
+
+ if ( j >= 0 ) {
+ path = filename.substring(0, j) ;
+ basename = filename.substring(j + 1) ;
+ }
+
+ int i = basename.lastIndexOf('.') ;
+
+ if ( i > -1 ) {
+ ext = basename.substring(i + 1) ;
+ basename = basename.substring(0, i) ;
+ }
+
+ return Tuple.createTuple(path, basename, ext) ;
+ }
+
+ /**
+ * Split a file name into path and filename. Nulls returned if don't make
+ * sense.
+ */
+ public static Tuple<String> splitDirFile(String filename) {
+ String path = null ;
+ String fn = filename ;
+
+ int j = filename.lastIndexOf('/') ;
+ if ( j < 0 )
+ j = filename.lastIndexOf('\\') ;
+
+ if ( j >= 0 ) {
+ path = filename.substring(0, j) ;
+ fn = filename.substring(j + 1) ;
+ }
+ return Tuple.createTuple(path, fn) ;
+ }
+
+ /** Return the basename (no path, no extension) */
+ public static String basename(String filename) {
+ int j = filename.lastIndexOf('/') ;
+ if ( j < 0 )
+ j = filename.lastIndexOf('\\') ;
+
+ String fn = (j >= 0) ? filename.substring(j + 1) : filename ;
+ int i = fn.lastIndexOf('.') ;
+
+ if ( i > -1 )
+ return fn.substring(0, i) ;
+ return fn ;
+ }
+
+ /** Return the extension (or "") */
+ public static String extension(String filename) {
+ int iSlash = filename.lastIndexOf('/') ;
+ int iBack = filename.lastIndexOf('\\') ;
+ int iExt = filename.lastIndexOf('.') ;
+ if ( iBack > iSlash )
+ iSlash = iBack ;
+ return iExt > iSlash ? filename.substring(iExt + 1).toLowerCase() : "" ;
+ }
+
+ public static String fullPath(String filename) {
+ File f = new File(filename) ;
+ return f.getAbsolutePath() ;
+ }
+
+ public static String fullDirectoryPath(String filename) {
+ File f = new File(filename) ;
+ if ( f.isDirectory() ) {
+ return f.getAbsolutePath() ;
+ } else if ( f.getParentFile() != null ) {
+ return f.getParentFile().getAbsolutePath() ;
+ } else {
+ return f.getAbsolutePath() ;
+ }
+ }
+
+ /** Copy a file */
+ public static void copyFile(File source, File dest) {
+ try {
+ @SuppressWarnings("resource")
+ FileChannel sourceChannel = new FileInputStream(source).getChannel() ;
+ @SuppressWarnings("resource")
+ FileChannel destChannel = new FileOutputStream(dest).getChannel() ;
+ destChannel.transferFrom(sourceChannel, 0, sourceChannel.size()) ;
+ sourceChannel.close() ;
+ destChannel.close() ;
+ }
+ catch (IOException ex) {
+ IO.exception(ex) ;
+ }
+ }
+
+ // public static String getExt(String filename)
+ // {
+ // int i = filename.lastIndexOf('.') ;
+ // int j = filename.lastIndexOf('/') ;
+ // if ( i > j )
+ // return filename.substring(i+1) ;
+ // return null ;
+ // }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Hex.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Hex.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Hex.java
new file mode 100644
index 0000000..27ebbb5
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Hex.java
@@ -0,0 +1,97 @@
+/*
+ * 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.lib;
+
+import org.apache.jena.atlas.AtlasException ;
+
+/** Working in hex ... */
+public class Hex
+{
+ // No checking, fixed width.
+ public static int formatUnsignedLongHex(final byte[] b, final int start, final long value, final int width)
+ {
+ // Insert from low value end to high value end.
+ int idx = start+width-1 ;
+ int w = width ;
+ long x = value ;
+
+ while ( w > 0 )
+ {
+ int d = (int)(x & 0xF) ;
+ x = x>>>4 ; // Unsigned shift.
+ byte ch = Bytes.hexDigitsUC[d] ;
+ b[idx] = ch ;
+ w-- ;
+ idx-- ;
+
+ if ( x == 0 )
+ break ;
+ }
+
+ if ( x != 0 )
+ throw new AtlasException("formatUnsignedLongHex: overflow") ;
+
+ while ( w > 0 )
+ {
+ b[idx] = '0' ;
+ idx-- ;
+ w-- ;
+ }
+ return width ;
+ }
+
+ // No checking, fixed width.
+ public static long getLong(byte[] arr, int idx)
+ {
+ long x = 0 ;
+ for ( int i = 0 ; i < 16 ; i++ )
+ {
+ byte c = arr[idx] ;
+ int v = hexByteToInt(c) ;
+ x = x << 4 | v ;
+ idx++ ;
+ }
+ return x ;
+ }
+
+ public static int hexByteToInt(int c)
+ {
+ if ( '0' <= c && c <= '9' )
+ return c-'0' ;
+ else if ( 'A' <= c && c <= 'F' )
+ return c-'A'+10 ;
+ else if ( 'a' <= c && c <= 'f' )
+ return c-'a'+10 ;
+ else
+ throw new IllegalArgumentException("Bad index char : "+c) ;
+ }
+
+ /** Return the value of the hex digit, or the marker value if not a hex digit.*/
+ public static int hexByteToInt(int c, int marker)
+ {
+ if ( '0' <= c && c <= '9' )
+ return c-'0' ;
+ else if ( 'A' <= c && c <= 'F' )
+ return c-'A'+10 ;
+ else if ( 'a' <= c && c <= 'f' )
+ return c-'a'+10 ;
+ else
+ return marker ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/IRILib.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/IRILib.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/IRILib.java
new file mode 100644
index 0000000..daafb74
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/IRILib.java
@@ -0,0 +1,243 @@
+/*
+ * 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.lib;
+
+import java.io.File ;
+import java.io.IOException ;
+
+import org.apache.jena.atlas.AtlasException ;
+import org.apache.jena.base.Sys ;
+
+/** Operations related to IRIs */
+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.
+ // Should this include "~"?
+ { '!', '*', '"', '\'', '(', ')', ';', /*':',*/ '@', '&',
+ '=', '+', '$', ',', /*'/',*/ '?', '%', '#', '[', ']',
+ '{', '}', '|', '\\', '`', '^',
+ ' ', '<', '>', '\n', '\r', '\t'} ;
+
+ private static char[] charsPath =
+ { // Reserved except leave the separators 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.
+ * <li>The file name may already have {@code file:}.
+ * <li>The file name may be relative.
+ * <li>Encode using the rules for a path (e.g. ':' and'/' do not get encoded)
+ * <li>Non-IRI characters 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 a file: 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 ( Sys.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 and 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/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/InternalErrorException.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/InternalErrorException.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/InternalErrorException.java
new file mode 100644
index 0000000..b20b2d6
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/InternalErrorException.java
@@ -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.lib;
+
+public class InternalErrorException extends RuntimeException
+{
+ public InternalErrorException() { super() ; }
+ public InternalErrorException(String msg) { super(msg) ; }
+ public InternalErrorException(Throwable th) { super(th) ; }
+ public InternalErrorException(String msg, Throwable th) { super(msg, th) ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Lib.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Lib.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Lib.java
new file mode 100644
index 0000000..6c9c442
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Lib.java
@@ -0,0 +1,126 @@
+/*
+ * 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.lib;
+
+import java.util.List ;
+import java.util.zip.Adler32 ;
+import java.util.zip.CRC32 ;
+import java.util.zip.Checksum ;
+
+import org.apache.jena.atlas.logging.Log ;
+
+public class Lib
+{
+ private Lib() {}
+
+ public static final void sync(Object object)
+ {
+ if ( object instanceof Sync )
+ ((Sync)object).sync() ;
+ }
+
+ /** Return true if obj1 and obj are both null or are .equals, else return false */
+ public static final <T> boolean equal(T obj1, T obj2)
+ {
+ if ( obj1 == null )
+ return obj2 == null ;
+ // obj1 != null
+ if ( obj2 == null )
+ return false ;
+ return obj1.equals(obj2) ;
+ }
+
+ /** Return true if obj1 and obj are both null or are .equals, else return false */
+ public static final boolean equalsIgnoreCase(String str1, String str2)
+ {
+ if ( str1 == null )
+ return str2 == null ;
+ return str1.equalsIgnoreCase(str2) ;
+ }
+
+
+ /** Return true if obj1 and obj are ! equal */
+ public static final <T> boolean notEqual(T obj1, T obj2)
+ {
+ return ! equal(obj1, obj2) ;
+ }
+
+ /** Safely return the class short name for an object -- obj.getClass().getSimpleName() */
+ static public final String className(Object obj) {
+ if ( obj == null )
+ return "null" ;
+ return classShortName(obj.getClass()) ;
+ }
+
+ /** Safely return the class short name for a class */
+ static public final String classShortName(Class<? > cls) {
+ if ( cls == null )
+ return "null" ;
+ return cls.getSimpleName() ;
+ }
+
+ /** Do two lists have the same elements? */
+ public static <T> boolean equalsListAsSet(List<T> list1, List<T> list2) {
+ if ( list1 == null && list2 == null )
+ return true ;
+ if ( list1 == null ) return false ;
+ if ( list2 == null ) return false ;
+ return list1.containsAll(list2) && list2.containsAll(list1) ;
+ }
+
+ /** HashCode - allow nulls */
+ public static final int hashCodeObject(Object obj) { return hashCodeObject(obj, -4) ; }
+
+ /** HashCode - allow nulls */
+ public static final int hashCodeObject(Object obj, int nullHashCode)
+ {
+ if ( obj == null )
+ return nullHashCode ;
+ return obj.hashCode() ;
+ }
+
+ public static final void sleep(int milliSeconds)
+ {
+ try { Thread.sleep(milliSeconds) ; }
+ catch (InterruptedException ex) { Log.warn(Lib.class, "interrupted", ex) ; }
+ }
+
+ /**
+ * @see CRC32
+ */
+ public static long crc32(byte[] bytes)
+ {
+ return crc(new CRC32(), bytes) ;
+ }
+
+ /** Faster than CRC32, nearly as good.
+ * @see Adler32
+ */
+ public static long adler32(byte[] bytes)
+ {
+ return crc(new Adler32(), bytes) ;
+ }
+
+ private static long crc(Checksum alg, byte[] bytes)
+ {
+ alg.reset() ;
+ alg.update(bytes, 0, bytes.length) ;
+ return alg.getValue() ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/ListUtils.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/ListUtils.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/ListUtils.java
new file mode 100644
index 0000000..78d591a
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/ListUtils.java
@@ -0,0 +1,150 @@
+/*
+ * 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.lib;
+
+import java.util.ArrayList ;
+import java.util.List ;
+
+
+import org.apache.jena.atlas.io.IndentedWriter ;
+import org.apache.jena.atlas.iterator.Action ;
+import org.apache.jena.atlas.iterator.FilterUnique ;
+import org.apache.jena.atlas.iterator.Iter ;
+import org.apache.jena.atlas.logging.Log ;
+
+/** Various things for lists */
+public class ListUtils
+{
+ private ListUtils() {}
+
+ public static <T>
+ List<T> unique(List<T> list)
+ {
+ Iter<T> iter = Iter.iter(list.iterator()) ;
+ return iter.filter(new FilterUnique<T>()).toList() ;
+ }
+
+ public static
+ List<Integer> asList(int... values)
+ {
+ List<Integer> x = new ArrayList<>() ;
+ for ( int v : values )
+ x.add(v) ;
+ return x ;
+ }
+
+ public static <T> String str(T[] array)
+ {
+ StringBuilder buff = new StringBuilder() ;
+ String sep = "[" ;
+
+ for ( T anArray : array )
+ {
+ buff.append( sep );
+ sep = ", ";
+ buff.append( anArray );
+ }
+ buff.append("]") ;
+ return buff.toString() ;
+ }
+
+ public static String str(int[] array)
+ {
+ StringBuilder buff = new StringBuilder() ;
+ String sep = "[" ;
+
+ for ( int anArray : array )
+ {
+ buff.append( sep );
+ sep = ", ";
+ buff.append( anArray );
+ }
+ buff.append("]") ;
+ return buff.toString() ;
+ }
+
+ public static String str(long[] array)
+ {
+ StringBuilder buff = new StringBuilder() ;
+ String sep = "[" ;
+
+ for ( long anArray : array )
+ {
+ buff.append( sep );
+ sep = ", ";
+ buff.append( anArray );
+ }
+ buff.append("]") ;
+ return buff.toString() ;
+ }
+
+ public static <T> void print(IndentedWriter out, List<T> list)
+ {
+ print(out, list, " ") ;
+ }
+
+ public static <T> void print(final IndentedWriter out, List<T> list, final String sep)
+ {
+ Action<T> output = new Action<T>() {
+ boolean first = true ;
+ @Override
+ public void apply(T item)
+ {
+ if ( ! first ) out.print(sep) ;
+ out.print(item.toString()) ;
+ first = false ;
+ }
+ } ;
+ Iter.apply(list.iterator(), output) ;
+ }
+
+ /** Return a list of lists of all the elements of collection in every order
+ * Easy to run out of heap memory.
+ */
+ static public <T> List<List<T>> permute(List<T> c)
+ {
+ if ( c.size() > 5 )
+ {
+ Log.warn(ListUtils.class, "Attempt to permute more than 5 items - think again") ;
+ return null ;
+ }
+
+ List<List<T>> x = new ArrayList<>() ;
+ if ( c.size() == 1 )
+ {
+ x.add(c) ;
+ return x ;
+ }
+
+ for ( T obj : c )
+ {
+ List<T> c2 = new ArrayList<>(c) ;
+ c2.remove(obj) ;
+ List<List<T>> x2 = permute(c2) ;
+ // For each list returned
+ for ( List<T> x3 : x2 )
+ {
+ // Gives a more expected ordering
+ x3.add(0,obj) ;
+ x.add(x3) ;
+ }
+ }
+ return x ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Map2.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Map2.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Map2.java
new file mode 100644
index 0000000..75697e0
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Map2.java
@@ -0,0 +1,104 @@
+/*
+ * 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.lib;
+
+
+import java.util.Iterator ;
+import java.util.Map ;
+
+import org.apache.jena.atlas.iterator.Iter ;
+
+
+/**
+ * A map with parent sharing. New entries go into a map but lookup is passed to
+ * the parent map if nothing is found at this level.
+ */
+public class Map2<K, V> implements Iterable<K>
+{
+ private final Map<K, V> map1 ;
+ private final Map2<K, V> map2 ;
+
+ public Map2(Map<K,V> map1, Map2<K,V> map2)
+ {
+ this.map1 = map1 ;
+ this.map2 = map2 ;
+ }
+
+ public boolean containsKey(K key)
+ {
+ if ( map1.containsKey(key) )
+ return true ;
+ if ( map2 != null )
+ return map2.containsKey(key) ;
+ return false;
+ }
+
+// public boolean containsValue(V value)
+// {
+// if ( map1.containsValue(value) )
+// return true ;
+// if ( map2 != null )
+// return map2.containsValue(value) ;
+// return false;
+// }
+
+ public V get(K key)
+ {
+ V v = map1.get(key) ;
+ if ( v != null ) return v ;
+ if ( map2 != null )
+ return map2.get(key) ;
+ return null ;
+ }
+
+ public void put(K key, V value)
+ {
+ if ( map2 != null && map2.containsKey(key) )
+ throw new IllegalArgumentException("Parent map already contains "+key) ;
+ map1.put(key, value) ;
+ }
+
+ // The keys.
+ @Override
+ public Iterator<K> iterator()
+ {
+ Iter<K> iter1 = Iter.iter(map1.keySet().iterator()) ;
+ if ( map2 == null )
+ return iter1 ;
+ return iter1.append(map2.iterator()) ;
+ }
+
+ public boolean isEmpty()
+ {
+ boolean x = map1.isEmpty() ;
+ if ( ! x ) return false ;
+ if ( map2 != null )
+ return map2.isEmpty() ;
+ return true ;
+ }
+
+ public int size()
+ {
+ int x = map1.size() ;
+ if ( map2 != null )
+ x += map2.size();
+ return x ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/MapUtils.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/MapUtils.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/MapUtils.java
new file mode 100644
index 0000000..7999a25
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/MapUtils.java
@@ -0,0 +1,45 @@
+/*
+ * 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.lib;
+
+import java.util.Map ;
+
+/** Map specific functions */
+public class MapUtils
+{
+ private MapUtils() {}
+
+ public static <K, V> void apply(Map<K, V> map, ActionKeyValue<K, V> action)
+ {
+ for ( Map.Entry<K,V> entry : map.entrySet() )
+ action.apply(entry.getKey(), entry.getValue()) ;
+ }
+
+ public static <T> void increment(Map<T, Integer> countMap, T key)
+ { increment(countMap, key, 1) ; }
+
+ public static <T> void increment(Map<T, Integer> countMap, T key, int incr)
+ {
+ Integer integer = countMap.get(key) ;
+ if ( integer == null )
+ countMap.put(key, incr) ;
+ else
+ countMap.put(key, integer+incr) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/MultiMap.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/MultiMap.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/MultiMap.java
new file mode 100644
index 0000000..2782ea6
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/MultiMap.java
@@ -0,0 +1,146 @@
+/*
+ * 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.lib;
+
+import java.util.* ;
+
+import org.apache.jena.atlas.iterator.IteratorConcat ;
+
+/* Map from K to collection of V */
+
+public abstract class MultiMap<K, V>
+{
+ private Map<K, Collection<V>> map = new HashMap<>() ;
+
+ protected abstract Collection<V> createCollection() ;
+
+ public static <K, V> MultiMapToList<K, V> createMapList() { return new MultiMapToList<>() ; }
+ public static <K, V> MultiMapToSet<K, V> createMapSet() { return new MultiMapToSet<>() ; }
+
+ protected MultiMap() { }
+
+ protected Collection<V> getByKey(K key) {
+ return map.get(key) ;
+ }
+
+ public abstract Collection<V> get(K key) ;
+
+ public V getOne(K key) {
+ Collection<V> c = map.get(key) ;
+ if ( c == null || c.size() == 0 )
+ return null ;
+ return c.iterator().next() ;
+ }
+
+ public void putAll(K key, @SuppressWarnings("unchecked") V ... values)
+ {
+ for ( V v : values)
+ put(key, v) ;
+ }
+
+ public void put(K key, V value)
+ {
+ Collection<V> x = map.get(key) ;
+ if ( x == null )
+ {
+ x = createCollection() ;
+ map.put(key, x) ;
+ }
+ x.add(value) ;
+ }
+
+ public void remove(K key, V value) {
+ if ( map.containsKey(key))
+ map.get(key).remove(value) ;
+ }
+ public void removeKey(K key) { map.remove(key) ; }
+
+ protected Collection<V> valuesForKey(K key) { return map.get(key); }
+ public abstract Collection<V> values(K key) ;
+ public abstract Collection<V> values() ;
+
+ public boolean containsKey(K key) { return map.containsKey(key) ; }
+
+ public Set<K> keys() { return map.keySet() ; }
+
+ public void clear() { map.clear() ; }
+
+ public boolean isEmpty() { return map.isEmpty() ; }
+
+ /** Does not materialise the contents */
+ public Iterator<V> flatten()
+ {
+ IteratorConcat<V> all = new IteratorConcat<>() ;
+ for ( K k : map.keySet() )
+ {
+ Collection<V> x = map.get(k) ;
+ all.add(x.iterator()) ;
+ }
+ return all ;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if ( this == obj )
+ return true ;
+ if ( obj == null )
+ return false ;
+ if ( getClass() != obj.getClass() )
+ return false ;
+ MultiMap<?,?> other = (MultiMap<?,?>)obj ;
+ if ( map == null ) {
+ if ( other.map != null )
+ return false ;
+ } else if ( !map.equals(other.map) )
+ return false ;
+ return true ;
+ }
+
+ @Override
+ public int hashCode() { return map.hashCode()^ 0x01010101 ; }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder() ;
+ sb.append("{ ") ;
+ boolean firstKey = true ;
+ for ( K key : keys() )
+ {
+ if ( ! firstKey )
+ sb.append(", ") ;
+ firstKey = false ;
+ sb.append(key) ;
+ sb.append(" => [") ;
+ boolean firstValue = true ;
+ for ( V value : values(key) )
+ {
+ if ( firstValue )
+ sb.append(" ") ;
+ else
+ sb.append(", ") ;
+ sb.append(value) ;
+ firstValue = false ;
+ }
+ sb.append(" ] ") ;
+ }
+ sb.append("}") ;
+ return sb.toString() ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/MultiMapToList.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/MultiMapToList.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/MultiMapToList.java
new file mode 100644
index 0000000..ac1ba70
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/MultiMapToList.java
@@ -0,0 +1,43 @@
+/**
+ * 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.lib;
+
+import java.util.ArrayList ;
+import java.util.Collection ;
+import java.util.List ;
+
+import org.apache.jena.atlas.iterator.Iter ;
+
+public class MultiMapToList<K,V> extends MultiMap<K,V> {
+ public static <K, V> MultiMapToList<K, V> create() { return new MultiMapToList<>() ; }
+
+ @Override
+ protected Collection<V> createCollection() {
+ return new ArrayList<>() ;
+ }
+
+ @Override
+ public List<V> get(K key) { return (List<V>)getByKey(key); }
+
+ @Override
+ public List<V> values(K key) { return (List<V>)valuesForKey(key); }
+
+ @Override
+ public List<V> values() { return Iter.toList(flatten()) ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/MultiMapToSet.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/MultiMapToSet.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/MultiMapToSet.java
new file mode 100644
index 0000000..b89e05b
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/MultiMapToSet.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.atlas.lib;
+
+import java.util.Collection ;
+import java.util.HashSet ;
+import java.util.Set ;
+
+import org.apache.jena.atlas.iterator.Iter ;
+
+public class MultiMapToSet<K,V> extends MultiMap<K,V> {
+ public static <K, V> MultiMapToSet<K, V> create() { return new MultiMapToSet<>() ; }
+
+ @Override
+ protected Collection<V> createCollection()
+ {
+ return new HashSet<>() ;
+ }
+
+ @Override
+ public Set<V> get(K key) { return (Set<V>)getByKey(key) ; }
+
+ @Override
+ public Set<V> values(K key) { return (Set<V>)valuesForKey(key); }
+
+ @Override
+ public Set<V> values() { return Iter.toSet(flatten()) ; }
+
+
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/MultiSet.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/MultiSet.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/MultiSet.java
new file mode 100644
index 0000000..3701042
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/MultiSet.java
@@ -0,0 +1,218 @@
+/*
+ * 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.lib;
+
+import java.util.ArrayList ;
+import java.util.HashMap ;
+import java.util.Iterator ;
+import java.util.List ;
+import java.util.Map ;
+import java.util.NoSuchElementException ;
+
+/** A MultiSet - also known as a Bag
+ */
+
+public class MultiSet<T> implements Iterable<T>
+{
+ private Map<T,RefLong> map = new HashMap<>() ;
+ private int multiSetSize = 0 ;
+
+ private RefLong _get(T obj)
+ {
+ RefLong z = map.get(obj) ;
+ if ( z == null )
+ {
+ z = new RefLong(0) ;
+ map.put(obj, z) ;
+ }
+ return z ;
+ }
+
+ /** Does it contain any elements at all? */
+ public boolean isEmpty() { return map.isEmpty() ; }
+
+ /** Does it contain the object? */
+ public boolean contains(T obj) { return map.containsKey(obj) ; }
+
+ /** Yield one object per element (i.e without counts) */
+ public Iterator<T> elements() { return map.keySet().iterator() ; }
+
+ /** Add an object */
+ public void add(T obj) { _get(obj).inc(); multiSetSize++ ; }
+
+ /** Add an object, with cardinality n */
+ public void add(T obj, long n)
+ {
+ if ( n <= 0 ) return ;
+ _get(obj).add(n) ;
+ multiSetSize += n ;
+ }
+
+ /** Remove one occurrence of the object from the multiset */
+ public void remove(T obj)
+ {
+ RefLong x = map.get(obj) ;
+ if ( x == null ) return ;
+ x.dec() ;
+ multiSetSize-- ;
+ if ( x.value() == 0 )
+ map.remove(obj) ;
+ }
+
+ /** Remove N occurrences of the object from the multiset */
+ public void remove(T obj, long n)
+ {
+ RefLong x = map.get(obj) ;
+ if ( x == null ) return ;
+ long z = x.value() ;
+ if ( z < n )
+ n = z ;
+ x.subtract(n) ;
+ multiSetSize -= n ;
+ if ( x.value() <= 0 )
+ map.remove(obj) ;
+ }
+
+
+ /** Remove all occurrences of the object in themultiset */
+ public void removeAll(T obj)
+ {
+ RefLong x = map.get(obj) ;
+ if ( x == null )
+ return ;
+ multiSetSize -= x.value() ;
+ map.remove(obj) ;
+ }
+
+ /* Remove everything */
+ public void clear() { map.clear() ; multiSetSize = 0 ; }
+
+
+ /** Get the count of the number of times the object appears in the multiset - i.e. it's cardinality.
+ * Returns zero when not present.
+ */
+ public long count(T obj)
+ {
+ if ( ! map.containsKey(obj) ) return 0 ;
+ return map.get(obj).value() ;
+ }
+
+ public int size()
+ {
+// int count = 0 ;
+// for ( Map.Entry<T, RefLong> e : map.entrySet() )
+// count += e.getValue().value() ;
+// //return count ;
+// if ( count != multiSetSize )
+// {
+// Log.warn(this, "Mismatch") ;
+// return count ;
+// }
+
+ return multiSetSize ;
+ }
+
+ private Iterator<T> iterator1()
+ {
+ // CRUDE
+ List<T> expanded = new ArrayList<>() ;
+ for ( Map.Entry<T, RefLong> e : map.entrySet() )
+ {
+ for ( int i = 0 ; i < e.getValue().value() ; i++ )
+ expanded.add(e.getKey()) ;
+ }
+
+ return expanded.iterator() ;
+ }
+
+ @Override
+ public Iterator<T> iterator()
+ {
+ return new Iterator<T>() {
+
+ Iterator<T> keys = map.keySet().iterator() ;
+ T key = null ;
+ long keyCount = 0 ;
+ T slot = null ;
+
+ @Override
+ public boolean hasNext()
+ {
+ if ( slot != null )
+ return true ;
+
+ if ( keys == null )
+ return false ;
+
+ if ( key != null )
+ {
+ if ( keyCount < count(key) )
+ {
+ keyCount++ ;
+ slot = key ;
+ return true ;
+ }
+ // End of this key.
+ key = null ;
+ }
+
+ if ( keys.hasNext() )
+ {
+ key = keys.next() ;
+ keyCount = 1 ;
+ slot = key ;
+ return true ;
+ }
+ keys = null ;
+ return false ;
+ }
+
+ @Override
+ public T next()
+ {
+ if ( ! hasNext() ) throw new NoSuchElementException() ;
+ T x = slot ;
+ slot = null ;
+ return x ;
+ }
+
+ @Override
+ public void remove()
+ { throw new UnsupportedOperationException() ; }
+ } ;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder() ;
+ sb.append("{") ;
+ String sep = "" ;
+ for ( Map.Entry<T, RefLong> e : map.entrySet() )
+ {
+ sb.append(sep) ;
+ sep = ", " ;
+ sb.append(e.getKey().toString()) ;
+ sb.append("=") ;
+ sb.append(Long.toString(e.getValue().value())) ;
+ }
+ sb.append("}") ;
+ return sb.toString() ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/NotImplemented.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/NotImplemented.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/NotImplemented.java
new file mode 100644
index 0000000..b7e91f1
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/NotImplemented.java
@@ -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.lib;
+
+public class NotImplemented extends InternalErrorException
+{
+ public NotImplemented() { super() ; }
+ public NotImplemented(String msg) { super(msg) ; }
+ public NotImplemented(Throwable th) { super(th) ; }
+ public NotImplemented(String msg, Throwable th) { super(msg, th) ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/NumberUtils.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/NumberUtils.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/NumberUtils.java
new file mode 100644
index 0000000..4f51beb
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/NumberUtils.java
@@ -0,0 +1,133 @@
+/*
+ * 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.lib;
+
+import org.apache.jena.atlas.AtlasException ;
+
+public class NumberUtils
+{
+ // Maximum length of a length 1,2,3,4...
+ private final static int [] maxTable = {
+ 9, 99, 999, 9999, 99999, 999999, 9999999,
+ 99999999, 999999999, Integer.MAX_VALUE };
+
+ /** Fast, but basic, integer to StringBuilder */
+ public static void formatInt(StringBuilder sb, int value)
+ {
+ // SeeAlso Integer.toString.
+ int len = length(value) ;
+ formatInt(sb, value, len, false) ;
+ }
+
+ /** Fast, but basic, integer to StringBuilder : always signed */
+ public static void formatSignedInt(StringBuilder sb, int value)
+ {
+ int len = length(value) ;
+ if ( value >= 0 )
+ len++ ;
+ formatInt(sb, value, len, true) ;
+ }
+
+ static int length(int x)
+ {
+ if ( x < 0 )
+ return length(-x)+1 ;
+
+ for (int i=0; ; i++)
+ if (x <= maxTable[i])
+ return i+1;
+ }
+
+ /** Place a fixed width representation of a non-negative int into the string buffer */
+ public static void formatInt(StringBuilder sb, int value, int width)
+ {
+ formatInt(sb, value, width, false) ;
+ }
+
+ /** Place a fixed width representation into the string buffer : always signed. */
+ public static void formatSignedInt(StringBuilder sb, int value, int width)
+ {
+ formatInt(sb, value, width, true) ;
+ }
+
+ /** Format an integer, which may be signed */
+ public static void formatInt(StringBuilder sb, int value, int width, boolean signAlways)
+ {
+ boolean negative = (value < 0 ) ;
+
+ if ( negative )
+ {
+ value = -value ;
+ width -- ;
+ sb.append('-') ;
+ }
+ else if ( signAlways )
+ {
+ width -- ;
+ sb.append('+') ;
+ }
+
+ formatUnsignedInt(sb, value, width) ;
+ }
+
+ /** Place a fixed width representation into the string buffer : never signed. */
+ public static void formatUnsignedInt(StringBuilder sb, int value, int width)
+ {
+ char chars[] = new char[width] ;
+ formatUnsignedInt$(chars, value, width) ;
+
+ // Append - the buffer was filled backwards.
+ for ( int i = 0 ; i < width ; i++ )
+ // Un-backwards.
+ sb.append(chars[width-1-i]) ;
+
+ }
+
+ // No checking. char[] filled backwards
+ private static int formatUnsignedInt$(char[] b, int x, int width)
+ {
+ // x >= 0
+ // Inserts chars backwards
+ int idx = 0 ;
+ while ( width > 0 )
+ {
+ int i = x%10 ;
+ char ch = Chars.digits10[i] ;
+ b[idx] = ch ;
+ width-- ;
+ idx++ ;
+
+ x = x / 10 ;
+ if ( x == 0 )
+ break ;
+ }
+
+ if ( x != 0 )
+ throw new AtlasException("formatInt: overflow[x="+x+", width="+width+"]") ;
+
+ while ( width > 0 )
+ {
+ b[idx] = '0' ;
+ idx++ ;
+ width-- ;
+ }
+ return width ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Pair.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Pair.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Pair.java
new file mode 100644
index 0000000..4f3b055
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Pair.java
@@ -0,0 +1,62 @@
+/*
+ * 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.lib;
+
+import static org.apache.jena.atlas.lib.Lib.hashCodeObject ;
+import static org.apache.jena.atlas.lib.StrUtils.str ;
+
+public class Pair<A, B>
+{
+ public static <L, R> Pair<L,R> create(L x, R y) { return new Pair<>(x,y) ; }
+
+ final A a ;
+ final B b ;
+ public Pair(A a, B b) { this.a = a; this.b = b ; }
+
+ public A getLeft() { return a ; }
+ public B getRight() { return b ; }
+
+ public A car() { return a ; }
+ public B cdr() { return b ; }
+
+ @Override
+ public int hashCode()
+ {
+ return hashCodeObject(car()) ^ hashCodeObject(cdr())<<1 ;
+ }
+
+ @Override
+ public boolean equals(Object other)
+ {
+ if ( this == other ) return true ;
+
+ // If it's a pair of a different <A,B> then .equals
+ // Pair<A,B>(null,null) is equal to Pair<C,D>(null ,null)
+ // Type erasure makes this hard to check otherwise.
+ // Use class X extends Pair<A,B> and implement .equals to do
+ // instanceof then call super.equals.
+
+ if( ! ( other instanceof Pair<?,?> ) ) return false ;
+ Pair<?,?> p2 = (Pair<?,?>)other ;
+ return Lib.equal(car(), p2.car()) && Lib.equal(cdr(), p2.cdr()) ;
+ }
+
+ @Override
+ public String toString() { return "("+str(a)+", "+str(b)+")" ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Pool.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Pool.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Pool.java
new file mode 100644
index 0000000..f28939e
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Pool.java
@@ -0,0 +1,30 @@
+/*
+ * 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.lib ;
+
+public interface Pool<T>
+{
+ public abstract void put(T item) ;
+
+ /** Get an item from the pool - return null if the pool is empty */
+ public abstract T get() ;
+
+ public abstract boolean isEmpty() ;
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/PoolBase.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/PoolBase.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/PoolBase.java
new file mode 100644
index 0000000..c6cb505
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/PoolBase.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.atlas.lib;
+
+import java.util.ArrayDeque ;
+
+/** A Pool of objects. Base implements a non-blocking pool (returns null on no entry)
+ * with infinite upper bound. Set effective size by creating the right number of
+ * entries when created.
+ */
+public class PoolBase<T> implements Pool<T>
+{
+ // For convenience we operate a LIFO policy.
+ // This not part of the extenal contract of a "pool"
+
+ ArrayDeque<T> pool = new ArrayDeque<>();
+ int maxSize = -1 ; // Unbounded
+
+ public PoolBase() {}
+ //public Pool(int maxSize) { this.maxSize = maxSize ; }
+
+ @Override
+ public void put(T item)
+ {
+ // Currently, unbounded
+ if ( maxSize >= 0 && pool.size() == 0 )
+ {}
+ pool.push(item) ;
+ }
+
+ /** Get an item from the pool - return null if the pool is empty */
+ @Override
+ public T get()
+ {
+ if ( pool.size() == 0 ) return null ;
+ return pool.pop();
+ }
+
+ @Override
+ public boolean isEmpty() { return pool.size() == 0 ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/PoolSync.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/PoolSync.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/PoolSync.java
new file mode 100644
index 0000000..10e0a6a
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/PoolSync.java
@@ -0,0 +1,53 @@
+/*
+ * 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.lib;
+
+
+/** Synchronization wrapper for a pool */
+public class PoolSync<T> implements Pool<T>
+{
+ private Pool<T> pool ;
+
+ public static <T> Pool<T> create(Pool<T> pool)
+ {
+ if ( pool instanceof PoolSync<?>)
+ {
+ PoolSync<T> p = (PoolSync<T>)pool ;
+ return p ;
+ }
+ return new PoolSync<>(pool) ;
+ }
+
+ public PoolSync(Pool<T> pool) { this.pool = pool ; }
+
+ @Override
+ public final synchronized void put(T item)
+ {
+ pool.put(item) ;
+ }
+
+ @Override
+ public final synchronized T get()
+ {
+ return pool.get();
+ }
+
+ @Override
+ public final synchronized boolean isEmpty() { return pool.isEmpty() ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Problem.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Problem.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Problem.java
new file mode 100644
index 0000000..d571fe7
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Problem.java
@@ -0,0 +1,25 @@
+/*
+ * 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.lib;
+
+public class Problem extends RuntimeException
+{
+ public Problem(String msg) { super(msg) ; }
+ public Problem(String msg, Throwable th) { super(msg, th) ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/PropertiesSorted.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/PropertiesSorted.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/PropertiesSorted.java
new file mode 100644
index 0000000..75060ee
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/PropertiesSorted.java
@@ -0,0 +1,87 @@
+/*
+ * 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.lib;
+
+import java.util.ArrayList ;
+import java.util.Collections ;
+import java.util.Comparator ;
+import java.util.Enumeration ;
+import java.util.Iterator ;
+import java.util.List ;
+import java.util.Properties ;
+
+/** Sorted output */
+public class PropertiesSorted extends Properties
+{
+ private Comparator<String> comparator = null ;
+
+ //public SortedProperties() { super() ; }
+
+ public PropertiesSorted(Comparator<String> comparator)
+ {
+ super() ;
+ this.comparator = comparator ;
+ }
+
+
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ @Override
+ public synchronized Enumeration<Object> keys()
+ {
+ // Old world - enumeration, untyped. But we know they are strings (Propetries hides non-strings in get)
+ Enumeration<Object> keys = super.keys() ;
+ List<String> keys2 = new ArrayList<>(super.size()) ;
+
+ for( ; keys.hasMoreElements() ; )
+ {
+ Object obj = keys.nextElement() ;
+ if ( obj instanceof String )
+ keys2.add((String)obj);
+ }
+ // Keys are comparable because they are strings.
+ if ( comparator == null )
+ Collections.sort(keys2);
+ else
+ Collections.sort(keys2, comparator) ;
+
+ return new IteratorToEnumeration(keys2.listIterator()) ;
+ }
+
+ static class IteratorToEnumeration<T> implements Enumeration<T>
+ {
+ private Iterator<T> iterator ;
+
+ public IteratorToEnumeration(Iterator<T> iterator)
+ {
+ this.iterator = iterator ;
+ }
+
+ @Override
+ public boolean hasMoreElements()
+ {
+ return iterator.hasNext() ;
+ }
+
+ @Override
+ public T nextElement()
+ {
+ return iterator.next();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/PropertyUtils.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/PropertyUtils.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/PropertyUtils.java
new file mode 100644
index 0000000..d4ac5b7
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/PropertyUtils.java
@@ -0,0 +1,143 @@
+/*
+ * 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.lib ;
+
+import java.io.* ;
+import java.util.Objects ;
+import java.util.Properties ;
+
+import org.apache.jena.atlas.AtlasException ;
+import org.apache.jena.atlas.io.IO ;
+
+public class PropertyUtils {
+ /** Load properties from a file if the file exists */
+ static public Properties loadFromFile(String filename) throws IOException {
+ Properties properties = new Properties() ;
+ loadFromFile(properties, filename) ;
+ return properties ;
+ }
+
+ /** Load properties from a file if the file exists */
+ static public void loadFromFile(Properties properties, String filename) throws IOException {
+ Objects.requireNonNull(filename, "File name must not be null") ;
+ if ( "-".equals(filename) )
+ throw new IllegalArgumentException("Filename is \"-\" (stdin not supported)") ;
+
+ try (InputStream in = new FileInputStream(filename); Reader r = IO.asBufferedUTF8(in);) {
+ properties.load(r) ;
+ }
+ }
+
+ static public void storeToFile(Properties properties, String comment, String filename) throws IOException {
+ String str = comment ;
+ if ( str == null )
+ str = filename ;
+ try (FileOutputStream fos = new FileOutputStream(filename)) {
+ Writer w = IO.asBufferedUTF8(fos) ;
+ properties.store(w, "Metadata: " + str) ;
+ w.flush() ;
+ }
+ }
+
+ public static int getPropertyAsInteger(Properties properties, String key) {
+ String x = properties.getProperty(key) ;
+ if ( x == null )
+ throw new AtlasException("No such property key: " + key) ;
+ return Integer.parseInt(x) ;
+ }
+
+ public static int getPropertyAsInteger(Properties properties, String key, int defaultValue) {
+ String x = properties.getProperty(key) ;
+ if ( x == null )
+ return defaultValue ;
+ return Integer.parseInt(x) ;
+ }
+
+ public static boolean getPropertyAsBoolean(Properties properties, String key, boolean dftValue) {
+ String x = properties.getProperty(key) ;
+ if ( x == null )
+ return dftValue ;
+ if ( x.equalsIgnoreCase("true") )
+ return true ;
+ if ( x.equalsIgnoreCase("false") )
+ return true ;
+ throw new AtlasException("Value '" + x + "'not recognized for " + key) ;
+ }
+
+ public static Boolean getPropertyAsBoolean(Properties properties, String key) {
+ String x = properties.getProperty(key) ;
+ if ( x == null )
+ throw new AtlasException("No such property key: " + key) ;
+ if ( x.equalsIgnoreCase("true") )
+ return true ;
+ if ( x.equalsIgnoreCase("false") )
+ return true ;
+ throw new AtlasException("Value '" + x + "'not recognized for " + key) ;
+ }
+
+ /** Test whether a property has a value. Null tests equal to not present. */
+ public boolean propertyEquals(Properties properties, String key, String value) {
+ return Lib.equal(properties.getProperty(key), value) ;
+ }
+
+ /** Set property if not already set. */
+ public void ensurePropertySet(Properties properties, String key, String expected) {
+ getOrSetDefault(properties, key, expected) ;
+ }
+
+ /**
+ * Get property or the default value - also set the default value if not
+ * present
+ */
+ public String getOrSetDefault(Properties properties, String key, String expected) {
+ String x = properties.getProperty(key) ;
+ if ( x == null ) {
+ properties.setProperty(key, expected) ;
+ x = expected ;
+ }
+ return x ;
+ }
+
+ /** Check property is an expected value or set if missing */
+ public void checkOrSetProperty(Properties properties, String key, String expected) {
+ String x = properties.getProperty(key) ;
+ if ( x == null ) {
+ properties.setProperty(key, expected) ;
+ return ;
+ }
+ if ( x.equals(expected) )
+ return ;
+
+ inconsistent(properties, key, x, expected) ;
+ }
+
+ /** Check property has the vakue given - throw exception if not. */
+ public void checkMetadata(Properties properties, String key, String expected) {
+ String value = properties.getProperty(key) ;
+
+ if ( !Lib.equal(value, value) )
+ inconsistent(properties, key, value, expected) ;
+ }
+
+ private void inconsistent(Properties properties, String key, String actual, String expected) {
+ String msg = String.format("Inconsistent: key=%s value=%s expected=%s", key, (actual == null ? "<null>" : actual),
+ (expected == null ? "<null>" : expected)) ;
+ throw new AtlasException(msg) ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/RandomLib.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/RandomLib.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/RandomLib.java
new file mode 100644
index 0000000..d2b3516
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/RandomLib.java
@@ -0,0 +1,41 @@
+/*
+ * 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.lib;
+
+import java.security.SecureRandom ;
+import java.util.Random ;
+
+public class RandomLib
+{
+ private RandomLib() {}
+
+ /** Single instance, pure random generator */
+ public static final Random random = new SecureRandom() ;
+
+ /** Random numbers, good seed, cheaper allocation */
+ public static final Random qrandom = randInit() ;
+
+ private static Random randInit()
+ {
+ // Cheap random numbers, well seeded.
+ int seed = random.nextInt() ;
+ return new Random(seed) ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Ref.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Ref.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Ref.java
new file mode 100644
index 0000000..e25b145
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Ref.java
@@ -0,0 +1,54 @@
+/*
+ * 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.lib;
+
+
+/** A mutable container */
+public class Ref<T>
+{
+ private T value ;
+
+ public T getValue() { return value; }
+
+ public Ref(T initial)
+ { setValue(initial); }
+
+ public void setValue(T value)
+ { this.value = value; }
+
+
+ // hashCode and equality are defined on object pointers.
+// @Override
+// public int hashCode() { return value.hashCode()^0x1 ; }
+//
+// @Override
+// public boolean equals(Object other)
+// {
+// if ( !( other instanceof Ref ) )
+// return false ;
+// Ref<?> r = (Ref<?>)other ;
+// return Lib.equals(value, r.value) ;
+// }
+
+ @Override
+ public String toString()
+ {
+ return "ref:"+value.toString() ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/RefLong.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/RefLong.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/RefLong.java
new file mode 100644
index 0000000..30dc663
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/RefLong.java
@@ -0,0 +1,38 @@
+/*
+ * 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.lib;
+
+public final class RefLong
+{
+ private long value ;
+ public RefLong() { this(0) ; }
+ public RefLong(long v) { value = v ; }
+ public long value() { return value ; }
+ public void inc() { value++ ; }
+ public void dec() { --value ; }
+ public long getAndInc() { return value++ ; }
+ public long incAndGet() { return ++value ; }
+ public long getAndDec() { return value-- ; }
+ public long decAndGet() { return --value ; }
+ public void add(long v) { value += v ; }
+ public void subtract(long v) { value -= v ; }
+ public void set(long v) { value = v ; }
+ @Override public String toString() { return "Ref:"+Long.toString(value) ; }
+ // hashCode and equals are Object equality - this is a mutable object
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Registry.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Registry.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Registry.java
new file mode 100644
index 0000000..b1e0d74
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Registry.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.atlas.lib;
+
+import java.util.Collection ;
+import java.util.Map ;
+import java.util.concurrent.ConcurrentHashMap ;
+
+public class Registry<K,T>
+{
+ protected Map<K, T> registry = new ConcurrentHashMap<>() ;
+
+ public Registry() {}
+
+ public void put(K key, T value) { registry.put(key, value) ; }
+ public T get(K key) { return registry.get(key) ; }
+ public boolean isRegistered(K key) { return registry.containsKey(key) ; }
+ public void remove(K key) { registry.remove(key) ; }
+ public Collection<K> keys() { return registry.keySet() ; }
+ //public Iterator<String> keys() { return registry.keySet().iterator() ; }
+ public int size() { return registry.size() ; }
+ public boolean isEmpty() { return registry.isEmpty() ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/ReverseComparator.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/ReverseComparator.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/ReverseComparator.java
new file mode 100644
index 0000000..7019b68
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/ReverseComparator.java
@@ -0,0 +1,38 @@
+/*
+ * 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.lib;
+
+import java.util.Comparator ;
+
+/** Comparator that compares the other way round to it's sub-comparator */
+public class ReverseComparator<T> implements Comparator<T>
+{
+ private final Comparator<T> comparator ;
+
+ public ReverseComparator(Comparator<T> comparator)
+ {
+ this.comparator = comparator ;
+ }
+
+ @Override
+ public int compare(T o1, T o2)
+ {
+ return comparator.compare(o2, o1) ;
+ }
+}
[6/9] jena git commit: Import of lib, io,
logging and iterator packages
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/BitsLong.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/BitsLong.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/BitsLong.java
new file mode 100644
index 0000000..e147033
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/BitsLong.java
@@ -0,0 +1,311 @@
+/*
+ * 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.lib;
+
+// NB shifting is "mod 64" -- <<64 is a no-op (not a clear).
+// http://mindprod.com/jgloss/masking.html
+
+/** Utilities for manipulating a bit pattern which are held in a 64 bit long
+ * @see BitsInt
+ * (java.util.BitSet does not allow getting the pattern as a long)
+ */
+public final class BitsLong
+{
+ private BitsLong() {}
+
+ private static int LongLen = Long.SIZE ;
+
+ /** Extract the value packed into bits start (inclusive) and finish (exclusive),
+ * the value is returned the low part of the returned long.
+ * The low bit is bit zero.
+ * @param bits
+ * @param start
+ * @param finish
+ * @return long
+ */
+
+ public static final
+ long unpack(long bits, int start, int finish)
+ {
+ check(start, finish) ;
+ if ( finish == 0 ) return 0 ;
+ // Remove top bits by moving up. Clear bottom bits by them moving down.
+ return (bits<<(LongLen-finish)) >>> ((LongLen-finish)+start) ;
+ }
+
+ /** Place the value into the bit pattern between start and finish
+ * and returns the new value. Leaves other bits alone.
+ * @param bits
+ * @param value
+ * @param start
+ * @param finish
+ * @return long
+ */
+ public static final
+ long pack(long bits, long value, int start, int finish)
+ {
+ check(start, finish) ;
+ bits = clear$(bits, start, finish) ;
+ long mask = mask(start, finish) ;
+ bits = bits | ( (value<<start) & mask ) ;
+ return bits ;
+ }
+
+ /** Get bits from a hex string.
+ *
+ * @param str
+ * @param startChar Index of first character (counted from the left, string style).
+ * @param finishChar Index after the last character (counted from the left, string style).
+ * @return long
+ */
+
+ public static final
+ long unpack(String str, int startChar, int finishChar)
+ {
+ String s = str.substring(startChar, finishChar) ;
+ return Long.parseLong(s, 16) ;
+ }
+
+ /** Set the bits specificied.
+ *
+ * @param bits Pattern
+ * @param bitIndex
+ * @return Modified pattern
+ */
+ public static final
+ long set(long bits, int bitIndex)
+ {
+ check(bitIndex) ;
+ return set$(bits, bitIndex) ;
+ }
+
+ /** Set the bits from string (inc) to finish (exc) to one
+ *
+ * @param bits Pattern
+ * @param start start (inclusive)
+ * @param finish finish (exclusive)
+ * @return Modified pattern
+ */
+ public static final
+ long set(long bits, int start, int finish)
+ {
+ check(start, finish) ;
+ return set$(bits, start, finish) ;
+ }
+
+ /** Test whether a bit is the same as isSet
+ * @param bits Pattern
+ * @param isSet Test whether is set or not.
+ * @param bitIndex Bit index
+ * @return Boolean
+ */
+ public static final
+ boolean test(long bits, boolean isSet, int bitIndex)
+ {
+ check(bitIndex) ;
+ return test$(bits, isSet, bitIndex) ;
+ }
+
+ /** Test whether a bit is set
+ * @param bits Pattern
+ * @param bitIndex Bit index
+ * @return Boolean
+ */
+ public static final
+ boolean isSet(long bits, int bitIndex)
+ {
+ check(bitIndex) ;
+ return test$(bits, true, bitIndex) ;
+ }
+
+ /** Test whether a range has a specific value or not
+ * @param bits Pattern
+ * @param value Value to test for
+ * @param start start (inclusive)
+ * @param finish finish (exclusive)
+ * @return Boolean
+ */
+ public static final
+ boolean test(long bits, long value, int start, int finish)
+ {
+ check(start, finish) ;
+ return test$(bits, value, start, finish) ;
+ }
+
+ /** Get the bits from start (inclusive) to finish (exclusive),
+ * leaving them aligned in the long. See also unpack, returns
+ * the value found at that place.
+ * @see #unpack(long, int, int)
+ * @param bits
+ * @param start
+ * @param finish
+ * @return lon */
+
+ public static final
+ long access(long bits, int start, int finish)
+ {
+ check(start, finish) ;
+ return access$(bits, start, finish) ;
+ }
+
+ /**
+ * Clear the bits specified.
+ * @param bits
+ * @param start
+ * @param finish
+ * @return long
+ */
+ public static final
+ long clear(long bits, int start, int finish)
+ {
+ check(start, finish) ;
+ return clear$(bits, start, finish) ;
+ }
+
+ /**
+ * Create a mask that has ones between bit positions start (inc) and finish (exc),
+ * and zeros elsewhere.
+ * @param start
+ * @param finish
+ * @return long
+ */
+ public static final
+ long mask(int start, int finish)
+ {
+ check(start, finish) ;
+ return mask$(start, finish) ;
+ }
+
+ /**
+ * Create a mask that has zeros between bit positions start (inc) and finish (exc),
+ * and ones elsewhere
+ * @param start
+ * @param finish
+ * @return long
+ */
+ public static final
+ long maskZero(int start, int finish)
+ {
+ check(start, finish) ;
+ return maskZero$(start, finish) ;
+ }
+
+ private static final
+ long clear$(long bits, int start, int finish)
+ {
+ long mask = maskZero$(start, finish) ;
+ bits = bits & mask ;
+ return bits ;
+ }
+
+ private static final
+ long set$(long bits, int bitIndex)
+ {
+ long mask = mask$(bitIndex) ;
+ return bits | mask ;
+ }
+
+ private static final
+ long set$(long bits, int start, int finish)
+ {
+ long mask = mask$(start, finish) ;
+ return bits | mask ;
+ }
+
+ private static
+ boolean test$(long bits, boolean isSet, int bitIndex)
+ {
+ return isSet == access$(bits, bitIndex) ;
+ }
+
+ private static
+ boolean test$(long bits, long value, int start, int finish)
+ {
+ long v = access$(bits, start, finish) ;
+ return v == value ;
+ }
+
+
+
+ private static final
+ boolean access$(long bits, int bitIndex)
+ {
+ long mask = mask$(bitIndex) ;
+ return (bits & mask) != 0L ;
+ }
+
+ private static final
+ long access$(long bits, int start, int finish)
+ {
+ // Two ways:
+// long mask = mask$(start, finish) ;
+// return bits & mask ;
+
+ return ( (bits<<(LongLen-finish)) >>> (LongLen-finish+start) ) << start ;
+ }
+
+
+ private static final
+ long mask$(int bitIndex)
+ {
+ return 1L << bitIndex ;
+ }
+
+ private static final
+ long mask$(int start, int finish)
+ {
+ // long mask = 0 ;
+ // if ( finish == Long.SIZE )
+ // // <<Long.SIZE is a no-op
+ // mask = -1 ;
+ // else
+ // mask = (1L<<finish)-1 ;
+ if ( finish == 0 )
+ // So start is zero and so the mask is zero.
+ return 0 ;
+
+
+ long mask = -1 ;
+// mask = mask << (LongLen-finish) >>> (LongLen-finish) ; // Clear the top bits
+// return mask >>> start << start ; // Clear the bottom bits
+ return mask << (LongLen-finish) >>> (LongLen-finish+start) << start ;
+ }
+
+ private static final
+ long maskZero$(int start, int finish)
+ {
+
+ return ~mask$(start, finish) ;
+ }
+
+ private static final
+ void check(long bitIndex)
+ {
+ if ( bitIndex < 0 || bitIndex >= LongLen ) throw new IllegalArgumentException("Illegal bit index: "+bitIndex) ;
+ }
+
+ private static final
+ void check(long start, long finish)
+ {
+ if ( start < 0 || start >= LongLen ) throw new IllegalArgumentException("Illegal start: "+start) ;
+ if ( finish < 0 || finish > LongLen ) throw new IllegalArgumentException("Illegal finish: "+finish) ;
+ if ( start > finish ) throw new IllegalArgumentException("Illegal range: ("+start+", "+finish+")") ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/ByteBufferLib.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/ByteBufferLib.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/ByteBufferLib.java
new file mode 100644
index 0000000..c619fed
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/ByteBufferLib.java
@@ -0,0 +1,211 @@
+/*
+ * 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.lib ;
+
+import static java.lang.System.arraycopy ;
+
+import java.io.PrintStream ;
+import java.nio.ByteBuffer ;
+import java.util.Arrays ;
+
+public class ByteBufferLib {
+ public static boolean allowArray = true ;
+
+ private ByteBufferLib() {}
+
+ public static void fill(ByteBuffer bb, byte v) {
+ fill(bb, bb.position(), bb.limit(), v) ;
+ }
+
+ public static void fill(ByteBuffer bb, int start, int finish, byte v) {
+ for ( int i = start ; i < finish ; i++ )
+ bb.put(i, v) ;
+ }
+
+ public static String details(ByteBuffer byteBuffer) {
+ // Like ByteBuffer.toString but without the class.
+ return "[pos=" + byteBuffer.position() + " lim=" + byteBuffer.limit() + " cap=" + byteBuffer.capacity() + "]" ;
+ }
+
+ public static void print(ByteBuffer byteBuffer) {
+ print(System.out, byteBuffer) ;
+ }
+
+ public static void print(PrintStream out, ByteBuffer byteBuffer) {
+ byteBuffer = byteBuffer.duplicate() ;
+
+ out.printf("ByteBuffer[pos=%d lim=%d cap=%d]", byteBuffer.position(), byteBuffer.limit(), byteBuffer.capacity()) ;
+
+ // Print bytes.
+ int i = 0 ;
+ int maxBytes = 3 * 20 ;
+ for ( ; i < maxBytes && i < byteBuffer.limit() ; i++ ) {
+ if ( i % 20 == 0 )
+ out.println() ;
+ out.printf(" 0x%02X", byteBuffer.get(i)) ; // Does not move position
+ }
+ if ( i < byteBuffer.limit() ) {
+ if ( i % 24 == 0 )
+ out.println() ;
+ out.print(" ...") ;
+ }
+ // Print as 4-byte ints
+ // int maxSlots = 8 ;
+ // int i = 0 ;
+ // for ( ; i < maxSlots && 4*i < byteBuffer.limit() ; i++ )
+ // out.printf(" 0x%04X", byteBuffer.getInt(4*i)) ;
+ // if ( i < maxSlots )
+ // out.print(" ...") ;
+ out.println() ;
+ }
+
+ public static boolean sameValue(ByteBuffer bb1, ByteBuffer bb2) {
+ if ( bb1.capacity() != bb2.capacity() )
+ return false ;
+
+ for ( int i = 0 ; i < bb1.capacity() ; i++ )
+ if ( bb1.get(i) != bb2.get(i) )
+ return false ;
+ return true ;
+ }
+
+ /**
+ * Copy of a ByteBuffer - the contents are copied (unlike
+ * ByteBuffer.duplicate)
+ */
+ final public static ByteBuffer duplicate(ByteBuffer bb) {
+ ByteBuffer bb2 = ByteBuffer.allocate(bb.limit() - bb.position()) ;
+ int x = bb.position() ;
+ bb2.put(bb) ;
+ bb.position(x) ;
+
+ bb2.position(0) ;
+ bb2.limit(bb2.capacity()) ;
+ return bb2 ;
+ }
+
+ /** Copy from a byte buffer */
+ final public static byte[] bb2array(ByteBuffer bb, int start, int finish) {
+ byte[] b = new byte[finish - start] ;
+ bb2array(bb, start, finish, b) ;
+ return b ;
+ }
+
+ private static void bb2array(ByteBuffer bb, int start, int finish, byte[] b) {
+ for ( int j = 0, i = start ; i < finish ; i++ )
+ b[j] = bb.get(i) ;
+ }
+
+ // For non-array versions : beware of overlaps.
+ final public static void bbcopy(ByteBuffer bb, int src, int dst, int length, int slotLen) {
+ if ( src == dst )
+ return ;
+
+ if ( allowArray && bb.hasArray() ) {
+ acopyArray(bb, src, dst, length, slotLen) ;
+ return ;
+ }
+
+ if ( src < dst )
+ bbcopy1(bb, src, dst, length, slotLen) ;
+ else
+ bbcopy2(bb, src, dst, length, slotLen) ;
+ }
+
+ private final static void bbcopy1(ByteBuffer bb, int src, int dst, int length, int slotLen) {
+ int bDst = dst * slotLen ;
+ int bSrc = src * slotLen ;
+ int bLen = length * slotLen ;
+ // src < dst so top dst is not in the overlap : work backwards
+ for ( int i = bLen - 1 ; i >= 0 ; i-- )
+ bb.put(bDst + i, bb.get(bSrc + i)) ;
+ }
+
+ private final static void bbcopy2(ByteBuffer bb, int src, int dst, int length, int slotLen) {
+ int bDst = dst * slotLen ;
+ int bSrc = src * slotLen ;
+ int bLen = length * slotLen ;
+ // src > dst so dst[0] is not in the overlap
+ for ( int i = 0 ; i < bLen ; i++ )
+ bb.put(bDst + i, bb.get(bSrc + i)) ;
+ }
+
+ public final static void bbcopy(ByteBuffer bb1, int src, ByteBuffer bb2, int dst, int length, int slotLen) {
+ // Assume bb1 and bb2 are different and do not overlap.
+ if ( allowArray && bb1.hasArray() && bb2.hasArray() ) {
+ acopyArray(bb1, src, bb2, dst, length, slotLen) ;
+ return ;
+ }
+ // One or both does not have an array.
+
+ int bSrc = src * slotLen ;
+ int bDst = dst * slotLen ;
+ int bLen = length * slotLen ;
+
+ for ( int i = 0 ; i < bLen ; i++ )
+ bb2.put(bDst + i, bb1.get(bSrc + i)) ;
+ }
+
+ final public static void bbfill(ByteBuffer bb, int fromIdx, int toIdx, byte fillValue, int slotLen) {
+ if ( allowArray && bb.hasArray() ) {
+ afillArray(bb, fromIdx, toIdx, fillValue, slotLen) ;
+ return ;
+ }
+
+ int bStart = fromIdx * slotLen ;
+ int bFinish = toIdx * slotLen ;
+
+ for ( int i = bStart ; i < bFinish ; i++ )
+ bb.put(i, fillValue) ;
+ }
+
+ // To ArrayOps?
+
+ final private static void acopyArray(ByteBuffer bb, int src, int dst, int length, int slotLen) {
+ byte[] b = bb.array() ;
+
+ int offset = bb.arrayOffset() ;
+
+ int bSrc = src * slotLen ;
+ int bDst = dst * slotLen ;
+ int bLen = length * slotLen ;
+
+ arraycopy(b, offset + bSrc, b, offset + bDst, bLen) ;
+ }
+
+ final private static void acopyArray(ByteBuffer bb1, int src, ByteBuffer bb2, int dst, int length, int slotLen) {
+ byte[] b1 = bb1.array() ;
+ byte[] b2 = bb2.array() ;
+ int offset1 = bb1.arrayOffset() ;
+ int offset2 = bb2.arrayOffset() ;
+
+ int bSrc = src * slotLen ;
+ int bDst = dst * slotLen ;
+ int bLen = length * slotLen ;
+
+ arraycopy(b1, offset1 + bSrc, b2, offset2 + bDst, bLen) ;
+ }
+
+ final private static void afillArray(ByteBuffer bb, int fromIdx, int toIdx, byte fillValue, int slotLen) {
+ int offset = bb.arrayOffset() ;
+ int bStart = fromIdx * slotLen ;
+ int bFinish = toIdx * slotLen ;
+ Arrays.fill(bb.array(), bStart + offset, bFinish + offset, fillValue) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Bytes.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Bytes.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Bytes.java
new file mode 100644
index 0000000..789aeeb
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Bytes.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.atlas.lib;
+
+import java.io.UnsupportedEncodingException ;
+import java.nio.ByteBuffer ;
+import java.nio.CharBuffer ;
+import java.nio.charset.CharsetDecoder ;
+import java.nio.charset.CharsetEncoder ;
+import java.nio.charset.CoderResult ;
+
+/** Byte-oriented operations. Packing and unpacking integers
+ * is in network order (Big endian - which is the preferred order in Java)
+ * {@link "http://en.wikipedia.org/wiki/Endianness"}
+ */
+
+public class Bytes
+{
+ private Bytes() {}
+
+ /** Compare two byte arrays which may be of different lengths */
+ public static int compare(byte[] x1, byte[] x2)
+ {
+ int n = Math.min(x1.length, x2.length) ;
+
+ for ( int i = 0 ; i < n ; i++ )
+ {
+ byte b1 = x1[i] ;
+ byte b2 = x2[i] ;
+ if ( b1 == b2 )
+ continue ;
+ // Treat as unsigned values in the bytes.
+ return (b1&0xFF) - (b2&0xFF) ;
+ }
+
+ return x1.length - x2.length ;
+ }
+
+ public static int compareByte(byte b1, byte b2)
+ {
+ return (b1&0xFF) - (b2&0xFF) ;
+ }
+
+ public static byte[] copyOf(byte[] bytes)
+ {
+ return copyOf(bytes, 0, bytes.length) ;
+ }
+
+ public static byte[] copyOf(byte[] bytes, int start)
+ {
+ return copyOf(bytes, start, bytes.length-start) ;
+ }
+
+ public static byte[] copyOf(byte[] bytes, int start, int length)
+ {
+ byte[] newByteArray = new byte[length] ;
+ System.arraycopy(bytes, start, newByteArray, 0, length) ;
+ return newByteArray ;
+ }
+
+ final public static byte[] hexDigitsUC = {
+ '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' ,
+ '9' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' };
+
+ final public static byte[] hexDigitsLC = {
+ '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' ,
+ '9' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' };
+
+ /** Get an int from a byte array (network order)
+ * @param b Byte Array
+ */
+ public static final int getInt(byte[]b)
+ { return getInt(b, 0) ; }
+
+ /** Get an int from a byte array (network order)
+ * @param b Byte Array
+ * @param idx Starting point of bytes
+ */
+ public static final int getInt(byte[]b, int idx)
+ {
+ return assembleInt(b[idx+0],
+ b[idx+1],
+ b[idx+2],
+ b[idx+3]) ;
+ }
+
+ /** Get a long from a byte array (network order)
+ * @param b Byte Array
+ */
+ public static final long getLong(byte[]b)
+ { return getLong(b, 0) ; }
+
+ /** Get a long from a byte array (network order)
+ * @param b Byte Array
+ * @param idx Starting point of bytes
+ */
+ public static final long getLong(byte[]b, int idx)
+ {
+ return assembleLong(b[idx+0],
+ b[idx+1],
+ b[idx+2],
+ b[idx+3],
+ b[idx+4],
+ b[idx+5],
+ b[idx+6],
+ b[idx+7]) ;
+
+ }
+
+ /** Put an int into a byte array
+ * @param value The integer
+ * @param b byte array
+ */
+ public static final void setInt(int value, byte[]b)
+ { setInt(value, b, 0) ; }
+
+ /** Put an int into a byte array from a given position
+ * @param x The integer
+ * @param b byte array
+ * @param idx starting point
+ */
+ public static final void setInt(int x, byte[]b, int idx)
+ {
+// b[idx+0] = byte3(value) ;
+// b[idx+1] = byte2(value) ;
+// b[idx+2] = byte1(value) ;
+// b[idx+3] = byte0(value) ;
+ b[idx+0] = (byte)((x >> 24)&0xFF) ;
+ b[idx+1] = (byte)((x >> 16)&0xFF);
+ b[idx+2] = (byte)((x >> 8)&0xFF);
+ b[idx+3] = (byte)(x &0xFF);
+
+ }
+
+
+ /** Put a long into a byte array
+ * @param value The integer
+ * @param b byte array
+ */
+ public static final void setLong(long value, byte[]b)
+ { setLong(value, b, 0) ; }
+
+ /** Put a long into a byte array from a given position
+ * @param value The integer
+ * @param b byte array
+ * @param idx starting point
+ */
+ public static final void setLong(long value, byte[] b, int idx) {
+ int lo = (int)(value & 0xFFFFFFFFL) ;
+ int hi = (int)(value >>> 32) ;
+ setInt(hi, b, idx) ;
+ setInt(lo, b, idx + 4) ;
+ }
+
+ /** int to byte array */
+ public static byte[] packInt(int val) {
+ byte[] valBytes = new byte[Integer.SIZE / Byte.SIZE] ;
+ setInt(val, valBytes, 0) ;
+ return valBytes ;
+ }
+
+ /** long to byte array */
+ public static byte[] packLong(long val) {
+ byte[] valBytes = new byte[Long.SIZE / Byte.SIZE] ;
+ setLong(val, valBytes, 0) ;
+ return valBytes ;
+ }
+
+ /** Make an int order of args -- high to low */
+ static private int assembleInt(byte b3, byte b2, byte b1, byte b0) {
+ return ( ((b3 & 0xFF) << 24) |
+ ((b2 & 0xFF) << 16) |
+ ((b1 & 0xFF) << 8) |
+ ((b0 & 0xFF) << 0)
+ );
+ }
+
+ /** Make a long order of args -- high to low */
+ static private Long assembleLong(byte b7, byte b6, byte b5, byte b4, byte b3, byte b2, byte b1, byte b0)
+ {
+
+ return (((long)b7 & 0xFF) << 56) |
+ (((long)b6 & 0xFF) << 48) |
+ (((long)b5 & 0xFF) << 40) |
+ (((long)b4 & 0xFF) << 32) |
+ (((long)b3 & 0xFF) << 24) |
+ (((long)b2 & 0xFF) << 16) |
+ (((long)b1 & 0xFF) << 8) |
+ (((long)b0 & 0xFF) << 0) ;
+ }
+
+ private static byte byte3(int x) { return (byte)(x >> 24); }
+ private static byte byte2(int x) { return (byte)(x >> 16); }
+ private static byte byte1(int x) { return (byte)(x >> 8); }
+ private static byte byte0(int x) { return (byte)(x >> 0); }
+
+ /** Return the UTF-8 bytes for a string */
+ public static byte[] string2bytes(String x) {
+ try {
+ return x.getBytes("UTF-8") ;
+ }
+ catch (UnsupportedEncodingException ex) {
+ // Impossible.
+ ex.printStackTrace() ;
+ return null ;
+ }
+ }
+
+ /** Return the string for some UTF-8 bytes */
+ public static String bytes2string(byte[] x) {
+ try {
+ return new String(x, "UTF-8") ;
+ }
+ catch (UnsupportedEncodingException ex) {
+ // Impossible-ish.
+ ex.printStackTrace() ;
+ return null ;
+ }
+ }
+
+ /** Encode a string into a ByteBuffer : on return position is the end of the encoding */
+ public static int toByteBuffer(CharSequence s, ByteBuffer bb) {
+ //BlockUTF8.fromChars(s, bb) ;
+ CharsetEncoder enc = Chars.allocEncoder();
+ int x = toByteBuffer(s, bb, enc) ;
+ Chars.deallocEncoder(enc) ;
+ return x ;
+ }
+
+ /** Encode a string into a ByteBuffer : on return position is the end of the encoding */
+ public static int toByteBuffer(CharSequence s, ByteBuffer bb, CharsetEncoder enc) {
+ int start = bb.position() ;
+ CharBuffer cBuff = CharBuffer.wrap(s);
+ enc.reset();
+ CoderResult r = enc.encode(cBuff, bb, true) ;
+ if ( r.isOverflow() )
+ throw new InternalErrorException("Bytes.toByteBuffer: encode overflow (1)") ;
+ r = enc.flush(bb) ;
+ if ( r.isOverflow() )
+ throw new InternalErrorException("Bytes.toByteBuffer: encode overflow (2)") ;
+// if ( r.isUnderflow() )
+// throw new InternalErrorException("Bytes.toByteBuffer: encode underflow") ;
+ int finish = bb.position() ;
+ return finish-start ;
+ }
+
+ /** Decode a string into a ByteBuffer */
+ public static String fromByteBuffer(ByteBuffer bb)
+ {
+ //return BlockUTF8.toString(bb) ;
+ // To be removed (Dec 2011)
+ CharsetDecoder dec = Chars.allocDecoder();
+ String x = fromByteBuffer(bb, dec) ;
+ Chars.deallocDecoder(dec) ;
+ return x ;
+ }
+
+ /** Decode a string into a ByteBuffer */
+ public static String fromByteBuffer(ByteBuffer bb, CharsetDecoder dec) {
+ if ( bb.remaining() == 0 )
+ return "" ;
+ dec.reset() ;
+ CharBuffer cBuff = CharBuffer.allocate(bb.remaining()) ;
+ CoderResult r = dec.decode(bb, cBuff, true) ;
+ if ( r.isOverflow() )
+ throw new InternalErrorException("fromByteBuffer: decode overflow (1)") ;
+ r = dec.flush(cBuff) ;
+ if ( r.isOverflow() )
+ throw new InternalErrorException("fromByteBuffer: decode overflow (2)") ;
+ cBuff.flip() ;
+ return cBuff.toString() ;
+ }
+
+ /**
+ * Return a hex string representing the bytes, zero padded to length of byte
+ * array.
+ */
+ public static String asHex(byte[] bytes) {
+ return asHexUC(bytes) ;
+ }
+
+ public static String asHexUC(byte[] bytes) {
+ return asHex(bytes, 0, bytes.length, Chars.hexDigitsUC) ;
+ }
+
+ public static String asHexLC(byte[] bytes) {
+ return asHex(bytes, 0, bytes.length, Chars.hexDigitsLC) ;
+ }
+
+ public static String asHex(byte[] bytes, int start, int finish, char[] hexDigits) {
+ StringBuilder sw = new StringBuilder() ;
+ for ( int i = start ; i < finish ; i++ ) {
+ byte b = bytes[i] ;
+ int hi = (b & 0xF0) >> 4 ;
+ int lo = b & 0xF ;
+ // if ( i != start ) sw.append(' ') ;
+ sw.append(hexDigits[hi]) ;
+ sw.append(hexDigits[lo]) ;
+ }
+ return sw.toString() ;
+ }
+
+ /** Return a hex string representing the bytes, zero padded to length of byte array. */
+ public static String asHex(byte b)
+ {
+ return asHexUC(b) ;
+ }
+
+ public static String asHexUC(byte b)
+ {
+ return asHex(b, Chars.hexDigitsUC) ;
+ }
+
+ public static String asHexLC(byte b)
+ {
+ return asHex(b, Chars.hexDigitsLC) ;
+ }
+
+ private static String asHex(byte b, char[] hexDigits)
+ {
+ int hi = (b & 0xF0) >> 4 ;
+ int lo = b & 0xF ;
+ char[] chars = new char[2] ;
+ chars[0] = hexDigits[hi] ;
+ chars[1] = hexDigits[lo] ;
+ return new String(chars) ;
+ }
+
+
+ public static int hexCharToInt(char c)
+ {
+ if ( '0' <= c && c <= '9' )
+ return c-'0' ;
+ else if ( 'A' <= c && c <= 'F' )
+ return c-'A'+10 ;
+ else if ( 'a' <= c && c <= 'f' )
+ return c-'a'+10 ;
+ else
+ throw new IllegalArgumentException("Bad index char : "+c) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Cache.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Cache.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Cache.java
new file mode 100644
index 0000000..d7fa711
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Cache.java
@@ -0,0 +1,56 @@
+/*
+ * 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.lib;
+
+import java.util.Iterator ;
+import java.util.concurrent.Callable ;
+
+/** A cache */
+public interface Cache<Key, Value>
+{
+
+ /** Does the cache contain the key? */
+ public boolean containsKey(Key key) ;
+
+ /** Get from cache - or return null. */
+ public Value getIfPresent(Key key) ;
+
+ /** Get from cache, of not present, call the {@code callable}
+ * to try to fill the cache.
+ */
+ public Value getOrFill(Key key, Callable<Value> callable) ;
+
+ /** Insert into the cache */
+ public void put(Key key, Value thing) ;
+
+ /** Remove from cache - return true if key referenced an entry */
+ public void remove(Key key) ;
+
+ /** Iterate over all keys. Iteratering over the keys requires the caller be thread-safe. */
+ public Iterator<Key> keys() ;
+
+ public boolean isEmpty() ;
+ public void clear() ;
+
+ /** Current size of cache */
+ public long size() ;
+
+ /** Register a callback - called when an object is dropped from the cache (optional operation) */
+ public void setDropHandler(ActionKeyValue<Key,Value> dropHandler) ;
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/CacheFactory.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/CacheFactory.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/CacheFactory.java
new file mode 100644
index 0000000..e913a9d
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/CacheFactory.java
@@ -0,0 +1,67 @@
+/*
+ * 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.lib ;
+
+import org.apache.jena.atlas.lib.cache.* ;
+
+public class CacheFactory {
+ /**
+ * Create a cache which has space for up to a certain number of objects.
+ * This is an LRU cache, or similar.
+ * The cache returns null for a cache miss.
+ * The cache is thread-safe for single operations.
+ */
+ public static <Key, Value> Cache<Key, Value> createCache(int maxSize) {
+ return new CacheGuava<>(maxSize) ;
+ }
+
+ /** Create a null cache */
+ public static <Key, Value> Cache<Key, Value> createNullCache() {
+ return new Cache0<>() ;
+ }
+
+ /** Create a lightweight cache (e.g. slot replacement) */
+ public static <Key, Value> Cache<Key, Value> createSimpleCache(int size) {
+ return new CacheSimple<>(size) ;
+ }
+
+ /** One slot cache */
+ public static <Key, Value> Cache<Key, Value> createOneSlotCache() {
+ return new Cache1<>() ;
+ }
+
+ /**
+ * Create set-cache, rather than a map-cache.
+ * The cache is thread-safe for single operations.
+ *
+ * @see Pool
+ */
+ public static <Obj> CacheSet<Obj> createCacheSet(int size) {
+ Cache<Obj, Object> c = createCache(size) ;
+ return new CacheSetImpl<Obj>(c) ;
+ }
+
+ /** Add a synchronization wrapper to an existing set-cache */
+ public static <Obj> CacheSet<Obj> createSync(CacheSet<Obj> cache) {
+ if ( cache instanceof CacheSetSync<? > )
+ return cache ;
+ return new CacheSetSync<>(cache) ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/CacheSet.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/CacheSet.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/CacheSet.java
new file mode 100644
index 0000000..f5c3d22
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/CacheSet.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.atlas.lib;
+
+import org.apache.jena.atlas.iterator.Action ;
+
+public interface CacheSet<T>
+{
+ public void add(T e) ;
+ public void clear() ;
+ public boolean contains(T obj) ;
+ public boolean isEmpty() ;
+// public Iterator<T> iterator() ;
+ public void remove(T obj) ;
+ public long size() ;
+ /** Register a callback - called when an object is dropped from the cache (optional operation) */
+ public void setDropHandler(Action<T> dropHandler) ;
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/CacheStats.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/CacheStats.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/CacheStats.java
new file mode 100644
index 0000000..d71c1a0
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/CacheStats.java
@@ -0,0 +1,28 @@
+/*
+ * 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.lib;
+
+/** A cache with some readable statistics */
+public interface CacheStats<K,V> extends Cache<K,V>
+{
+ public long getCacheEntries() ;
+ public long getCacheHits() ;
+ public long getCacheMisses() ;
+ public long getCacheEjects() ;
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Callback.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Callback.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Callback.java
new file mode 100644
index 0000000..d2f04f9
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Callback.java
@@ -0,0 +1,24 @@
+/*
+ * 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.lib;
+
+public interface Callback<T>
+{
+ public void proc(T arg) ;
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Cell.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Cell.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Cell.java
new file mode 100644
index 0000000..6910c0c
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Cell.java
@@ -0,0 +1,99 @@
+/*
+ * 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.lib ;
+
+
+/** Key-value slot, with chaining for lookup. */
+public class Cell<K,V>
+{
+ private final Cell<K,V> previous ;
+ private final K key ;
+ private final V value ;
+
+ /** Create a slot with no key, value or parent - can be used a slot chain root */
+ public Cell() { this(null, null, null); }
+
+ public Cell(K key, V value) { this(key, value, null); }
+
+ private Cell(K key, V value, Cell<K, V> previous)
+ {
+ this.key = key ;
+ this.value = value ;
+ this.previous = previous ;
+ }
+
+ public Cell<K,V> extend(K key, V value)
+ {
+ return new Cell<>(key, value, this) ;
+ }
+
+ public final V find(K k)
+ {
+ // Java, tail recursion, lack thereof.
+ Cell<K,V> slot = this ;
+
+ while (slot != null)
+ {
+ // Defend against null keys (e.g. the root of a slot chain).
+ if ( k.equals(slot.key) )
+ return slot.value ;
+// if ( previous == null )
+// return null ;
+ slot = slot.previous ;
+ }
+ return null ;
+ }
+
+ /* As it should be ... */
+// public final V find(K k)
+// {
+// if ( k.equals(key) )
+// return value ;
+// if ( previous == null )
+// return null ;
+// return previous.find(k) ;
+// }
+
+ private static final String sep = ", " ;
+ private void str(int level, StringBuilder acc)
+ {
+ if ( key == null && value == null )
+ return ;
+
+ if ( level != 0 )
+ acc.append(sep) ;
+ acc.append("(") ;
+ acc.append(key.toString()) ;
+ acc.append("->") ;
+ acc.append(value.toString()) ;
+ acc.append(")") ;
+ if ( previous != null )
+ previous.str(level+1, acc) ;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder() ;
+ sb.append("{ ") ;
+ str(0, sb) ;
+ sb.append(" }") ;
+ return sb.toString() ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Chars.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Chars.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Chars.java
new file mode 100644
index 0000000..e9d4f55
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Chars.java
@@ -0,0 +1,271 @@
+/*
+ * 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.lib;
+
+import java.nio.charset.Charset ;
+import java.nio.charset.CharsetDecoder ;
+import java.nio.charset.CharsetEncoder ;
+import java.nio.charset.CodingErrorAction ;
+
+public class Chars
+{
+ private Chars() {}
+
+ // So also Bytes.hexDigits to get bytes.
+ final public static char[] digits10 = {
+ '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9'
+ } ;
+
+ /** Hex digits : upper case **/
+ final public static char[] hexDigitsUC = {
+ '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' ,
+ '9' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' } ;
+
+ /** Hex digits : lower case **/
+ final public static char[] hexDigitsLC = {
+ '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' ,
+ '9' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' } ;
+
+
+// , 'g' , 'h' ,
+// 'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
+// 'o' , 'p' , 'q' , 'r' , 's' , 't' ,
+// 'u' , 'v' , 'w' , 'x' , 'y' , 'z'
+
+ /** Java name for UTF-8 encoding */
+ private static final String encodingUTF8 = "utf-8" ;
+ /** Java name for ASCII encoding */
+ private static final String encodingASCII = "ascii" ;
+
+ public static final Charset charsetUTF8 = Charset.forName(encodingUTF8) ;
+ public static final Charset charsetASCII = Charset.forName(encodingASCII) ;
+
+ // Pools for encoders/decoder.
+ // Better? use a ThreadLocal.
+ // Initial pool size. Any additional encoder/decoder are later
+ // placed in the pool - it's an infinite, reusing, growing pool.
+
+ // Better? If so, use these!
+
+ private static final ThreadLocal<CharsetEncoder> threadCharsetEncoder =
+ new ThreadLocal<CharsetEncoder>() {
+ @Override protected CharsetEncoder initialValue() {
+ return createEncoder() ;
+ }
+ };
+
+ private static final ThreadLocal<CharsetDecoder> threadCharsetDecoder =
+ new ThreadLocal<CharsetDecoder>() {
+ @Override protected CharsetDecoder initialValue() {
+ return createDecoder() ;
+ }
+ };
+
+ /** Return a per-thread CharsetEncoder */
+ public static CharsetEncoder getThreadEncoder() { return threadCharsetEncoder.get() ; }
+
+ /** Return a per-thread CharsetDecoder */
+ public static CharsetDecoder getThreadDecoder() { return threadCharsetDecoder.get() ; }
+
+ private static final int PoolSize = 2 ;
+ private static Pool<CharsetEncoder> encoders = PoolSync.create(new PoolBase<CharsetEncoder>()) ;
+ private static Pool<CharsetDecoder> decoders = PoolSync.create(new PoolBase<CharsetDecoder>()) ;
+
+ static {
+ ThreadLocal<CharsetEncoder> t ;
+
+ // Fill the pool.
+ for ( int i = 0 ; i < PoolSize ; i++ )
+ {
+ putEncoder(createEncoder()) ;
+ putDecoder(createDecoder()) ;
+ }
+ }
+
+ /** Create a UTF-8 encoder */
+ public static CharsetEncoder createEncoder() { return charsetUTF8.newEncoder() ; }
+ /** Create a UTF-8 decoder */
+ public static CharsetDecoder createDecoder() { return charsetUTF8.newDecoder() ; }
+
+ /** Get a UTF-8 encoder from the pool (null if pool empty) */
+ public static CharsetEncoder getEncoder() { return encoders.get() ; }
+ /** Add/return a UTF-8 encoder to the pool */
+ public static void putEncoder(CharsetEncoder encoder) { encoders.put(encoder) ; }
+
+ /** Get a UTF-8 decoder from the pool (null if pool empty) */
+ public static CharsetDecoder getDecoder() { return decoders.get() ; }
+ /** Add/return a UTF-8 decoder to the pool */
+ public static void putDecoder(CharsetDecoder decoder) { decoders.put(decoder) ; }
+
+ /** Allocate a CharsetEncoder, creating as necessary */
+ public static CharsetEncoder allocEncoder()
+ {
+ CharsetEncoder enc = Chars.getEncoder();
+ // Blocking finite Pool - does not happen.
+ // Plain Pool (sync wrapped) - might - allocate an extra one.
+ if ( enc == null )
+ enc = Chars.createEncoder() ;
+ enc
+ .onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE)
+ .reset() ;
+
+ return enc ;
+ }
+ /** Deallocate a CharsetEncoder, may increase pool size */
+ public static void deallocEncoder(CharsetEncoder enc) { putEncoder(enc) ; }
+
+ /** Allocate a CharsetDecoder, creating as necessary */
+ public static CharsetDecoder allocDecoder()
+ {
+ CharsetDecoder dec = Chars.getDecoder();
+ // Blocking finite Pool - does not happen.
+ // Plain Pool (sync wrapped) - might - allocate an extra one.
+ if ( dec == null )
+ dec = Chars.createDecoder() ;
+ dec
+ .onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE)
+ .reset() ;
+
+ return dec ;
+ }
+ /** Deallocate a CharsetDecoder, may increase pool size */
+ public static void deallocDecoder(CharsetDecoder dec) { putDecoder(dec) ; }
+
+ /** Is char in the array? */
+ public static boolean charInArray(int ch, char[] chars) {
+ for ( int xch : chars ) {
+ if ( ch == xch )
+ return true ;
+ }
+ return false ;
+ }
+
+ public static void encodeAsHex(StringBuilder buff, char marker, char ch)
+ {
+ if ( ch < 256 )
+ {
+ buff.append(marker) ;
+ int lo = ch & 0xF ;
+ int hi = (ch >> 4) & 0xF ;
+ buff.append(Chars.hexDigitsUC[hi]) ;
+ buff.append(Chars.hexDigitsUC[lo]) ;
+ return ;
+ }
+ int n4 = ch & 0xF ;
+ int n3 = (ch >> 4) & 0xF ;
+ int n2 = (ch >> 8) & 0xF ;
+ int n1 = (ch >> 12) & 0xF ;
+ buff.append(marker) ;
+ buff.append(Chars.hexDigitsUC[n1]) ;
+ buff.append(Chars.hexDigitsUC[n2]) ;
+ buff.append(marker) ;
+ buff.append(Chars.hexDigitsUC[n3]) ;
+ buff.append(Chars.hexDigitsUC[n4]) ;
+
+ }
+
+ /** End of file - not a Unicode codepoint */
+ public static final int EOF = -1 ;
+ // BOM : U+FEFF encoded in bytes as xEF,0xBB,0xBF
+ public static final char BOM = 0xFEFF ;
+
+ /** undefined character (exact meaning depends on use) - not a Unicode codepoint */
+ public static final int UNSET = -2 ;
+ public static final char NL = '\n' ;
+ public static final char CR = '\r' ;
+ public static final char TAB = '\t' ;
+ public static final char SPC = ' ' ;
+ public static final char BSPACE = '\b' ;
+
+ public static final char CH_ZERO = (char)0 ;
+
+ public static final char CH_LBRACKET = '[' ;
+ public static final char CH_RBRACKET = ']' ;
+
+ public static final char CH_LBRACE = '{' ;
+ public static final char CH_RBRACE = '}' ;
+
+ public static final char CH_LPAREN = '(' ;
+ public static final char CH_RPAREN = ')' ;
+
+ public static final char CH_LT = '<' ;
+ public static final char CH_GT = '>' ;
+ public static final char CH_UNDERSCORE = '_' ;
+
+ public static final char CH_QUOTE1 = '\'' ;
+ public static final char CH_QUOTE2 = '"' ;
+
+ public static final char CH_EQUALS = '=' ;
+ public static final char CH_STAR = '*' ;
+ public static final char CH_DOT = '.' ;
+ public static final char CH_COMMA = ',' ;
+ public static final char CH_SEMICOLON = ';' ;
+ public static final char CH_COLON = ':' ;
+ public static final char CH_AMPHERSAND = '&' ;
+ public static final char CH_AT = '@' ;
+ public static final char CH_QMARK = '?' ;
+ public static final char CH_HASH = '#' ;
+ public static final char CH_PLUS = '+' ;
+ public static final char CH_MINUS = '-' ;
+ public static final char CH_DASH = '-' ; // Alt name
+ public static final char CH_SLASH = '/' ;
+ public static final char CH_RSLASH = '\\' ;
+ public static final char CH_PERCENT = '%' ;
+
+ // Byte versions of the above
+ public static final byte B_NL = NL ;
+ public static final byte B_CR = CR ;
+
+ public static final byte B_LBRACKET = '[' ;
+ public static final byte B_RBRACKET = ']' ;
+
+ public static final byte B_LBRACE = '{' ;
+ public static final byte B_RBRACE = '}' ;
+
+ public static final byte B_LPAREN = '(' ;
+ public static final byte B_RPAREN = ')' ;
+
+ public static final byte B_LT = '<' ;
+ public static final byte B_GT = '>' ;
+ public static final byte B_UNDERSCORE = '_' ;
+
+ public static final byte B_QUOTE1 = '\'' ;
+ public static final byte B_QUOTE2 = '"' ;
+
+ public static final byte B_EQUALS = '=' ;
+ public static final byte B_STAR = '*' ;
+ public static final byte B_DOT = '.' ;
+ public static final byte B_COMMA = ',' ;
+ public static final byte B_SEMICOLON = ';' ;
+ public static final byte B_COLON = ':' ;
+ public static final byte B_AT = '@' ;
+ public static final byte B_AMPHERSAND = '&' ;
+ public static final byte B_QMARK = '?' ;
+ public static final byte B_HASH = '#' ;
+ public static final byte B_PLUS = '+' ;
+ public static final byte B_MINUS = '-' ;
+ public static final byte B_DASH = '-' ; // Alt name
+ public static final byte B_SLASH = '/' ;
+ public static final byte B_RSLASH = '\\' ;
+ public static final byte B_PERCENT = '%' ;
+
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Closeable.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Closeable.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Closeable.java
new file mode 100644
index 0000000..2b6002a
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Closeable.java
@@ -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.lib;
+
+/** Close this object.
+ * This form does not allow Exceptions (it does allow RuntimeExceptions).
+ */
+public interface Closeable
+{
+ public void close() ;
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/CollectionUtils.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/CollectionUtils.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/CollectionUtils.java
new file mode 100644
index 0000000..8bae6a4
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/CollectionUtils.java
@@ -0,0 +1,52 @@
+/*
+ * 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.lib;
+
+import java.util.Collection ;
+import java.util.Iterator ;
+
+public class CollectionUtils
+{
+ static public <T> void removeNulls(Collection<T> list)
+ {
+ for ( Iterator<T> iter = list.iterator() ; iter.hasNext() ; )
+ {
+ T e = iter.next() ;
+ if ( e == null )
+ iter.remove() ;
+ }
+ }
+
+ static public <T> boolean disjoint(Collection<T> c1, Collection<T> c2)
+ {
+ if ( c2.size() < c1.size() )
+ {
+ Collection<T> t = c1 ;
+ c1 = c2 ;
+ c2 = t ;
+ }
+
+ for ( T t : c1 )
+ {
+ if ( c2.contains(t) )
+ return false ;
+ }
+ return true ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/ColumnMap.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/ColumnMap.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/ColumnMap.java
new file mode 100644
index 0000000..18db563
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/ColumnMap.java
@@ -0,0 +1,254 @@
+/*
+ * 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.lib;
+
+import static java.lang.String.format ;
+
+import java.util.Arrays ;
+import java.util.List ;
+
+import org.apache.jena.atlas.AtlasException ;
+
+
+
+/** General descriptor of a reordering (mapping) of columns in tuples to columns in indexes,
+ * for example, from triples to triple index order.
+ *
+ * Naming: map is convert to the reordered form, fetch is get back.
+ */
+public class ColumnMap
+{
+ // Map from tuple order to index order
+ // So SPO->POS is (0->2, 1->0, 2->1)
+ // i.e. the location of the element after mapping.
+ private int[] insertOrder ;
+
+ // The mapping from index to tuple order
+ // For POS->SPO, is (0->1, 1->2, 2->0)
+ // i.e. the location to fetch the mapped element from.
+ private int[] fetchOrder ;
+
+ private String label ;
+
+ /** Construct a column mapping that maps the input (one col, one char) to the output */
+ public ColumnMap(String input, String output)
+ {
+ this(input+"->"+output, compileMapping(input, output)) ;
+ }
+
+ public <T> ColumnMap(String label, List<T> input, List<T> output)
+ {
+ this(label, compileMapping(input, output)) ;
+ }
+
+ public <T> ColumnMap(String label, T[] input, T[] output)
+ {
+ this(label, compileMapping(input, output)) ;
+ }
+
+ /** Construct a column map - the elements are the
+ * mappings of a tuple originally in the order 0,1,2,...
+ * so SPO->POS is 2,0,1 (SPO->POS so S->2, P->0, O->1)
+ * and not 1,2,0 (which is the extraction mapping).
+ * The label is just a lable and is not interpretted.
+ */
+ public ColumnMap(String label, int...elements)
+ {
+ this.label = label ;
+
+ this.insertOrder = new int[elements.length] ;
+ System.arraycopy(elements, 0, elements, 0, elements.length) ;
+ Arrays.fill(insertOrder, -1) ;
+
+ this.fetchOrder = new int[elements.length] ;
+ Arrays.fill(fetchOrder, -1) ;
+
+ for ( int i = 0 ; i < elements.length ; i++ )
+ {
+ int x = elements[i] ;
+ if ( x < 0 || x >= elements.length)
+ throw new IllegalArgumentException("Out of range: "+x) ;
+ // Checking
+ if ( insertOrder[i] != -1 || fetchOrder[x] != -1 )
+ throw new IllegalArgumentException("Inconsistent: "+ListUtils.str(elements)) ;
+
+ insertOrder[i] = x ;
+ fetchOrder[x] = i ;
+ }
+ }
+
+ /** Length of mapping */
+
+ public int length() { return fetchOrder.length ; }
+
+ /** Apply to an <em>unmapped</em> tuple to get the i'th slot after mapping : SPO->POS : 0'th slot is P from SPO */
+ public <T> T fetchSlot(int idx, Tuple<T> tuple)
+ {
+ idx = fetchOrder[idx] ; // Apply the reverse mapping as we are doing zero is P, so it's an unmap.
+ return tuple.get(idx) ;
+ }
+
+ /** Apply to an <em>unmapped</em> tuple to get the i'th slot after mapping : SPO->POS : 0'th slot is P from SPO */
+ public <T> T fetchSlot(int idx, T[] tuple)
+ {
+ idx = fetchOrder[idx] ; // Apply the reverse mapping as we are doing zero is P, so it's an unmap.
+ return tuple[idx] ;
+ }
+
+ /** Apply to a <em>mapped</em> tuple to get the i'th slot as it appears after mapping : SPO->POS : 0'th slot is S from POS */
+ public <T> T mapSlot(int idx, Tuple<T> tuple)
+ {
+ idx = insertOrder[idx] ;
+ return tuple.get(idx) ;
+ }
+
+ /** Apply to a <em>mapped</em> tuple to get the i'th slot as it appears after mapping : SPO->POS : 0'th slot is S from POS */
+ public <T> T mapSlot(int idx, T[] tuple)
+ {
+ idx = insertOrder[idx] ; // Yes - it's the insert location we want to access
+ return tuple[idx] ;
+ }
+
+ /** Get the index of the i'th slot as it appears after mapping : SPO->POS : 0'th slot is S from POS so 2->0 */
+ public int mapSlotIdx(int idx)
+ {
+ return insertOrder[idx] ; // Yes - it's the insert location we want to access
+ }
+
+ /** Get the index of the i'th slot as it appears from a mapping : for SPO->POS : 0'th slot is P so 1->0 */
+ public int fetchSlotIdx(int idx)
+ {
+ return fetchOrder[idx] ; // Yes - it's the insert location we want to access
+ }
+
+ /** Apply to an <em>unmapped</em> tuple to get a tuple with the column mapping applied */
+ public <T> Tuple<T> map(Tuple<T> src)
+ {
+ return map(src, insertOrder) ;
+ }
+
+ /** Apply to a <em>mapped</em> tuple to get a tuple with the column mapping reverse-applied */
+ public <T> Tuple<T> unmap(Tuple<T> src)
+ {
+ return map(src, fetchOrder) ;
+ }
+
+ private <T> Tuple<T> map(Tuple<T> src, int[] map)
+ {
+ @SuppressWarnings("unchecked")
+ T[] elts = (T[])new Object[src.size()] ;
+
+ for ( int i = 0 ; i < src.size() ; i++ )
+ {
+ int j = map[i] ;
+ elts[j] = src.get(i) ;
+ }
+ return Tuple.create(elts) ;
+ }
+
+ /** Compile a mapping encoded as single charcaters e.g. "SPO", "POS" */
+ static int[] compileMapping(String domain, String range)
+ {
+ List<Character> input = StrUtils.toCharList(domain) ;
+ List<Character> output = StrUtils.toCharList(range) ;
+ return compileMapping(input, output) ;
+ }
+
+ /** Compile a mapping, encoded two list, the domain and range of the mapping function */
+ static <T> int[] compileMapping(T[] domain, T[] range)
+ {
+ return compileMapping(Arrays.asList(domain), Arrays.asList(range)) ;
+ }
+
+ /** Compile a mapping */
+ static <T> int[] compileMapping(List<T> domain, List<T>range)
+ {
+ if ( domain.size() != range.size() )
+ throw new AtlasException("Bad mapping: lengths not the same: "+domain+" -> "+range) ;
+
+ int[] cols = new int[domain.size()] ;
+ boolean[] mapped = new boolean[domain.size()] ;
+ //Arrays.fill(mapped, false) ;
+
+ for ( int i = 0 ; i < domain.size() ; i++ )
+ {
+ T input = domain.get(i) ;
+ int j = range.indexOf(input) ;
+ if ( j < 0 )
+ throw new AtlasException("Bad mapping: missing mapping: "+domain+" -> "+range) ;
+ if ( mapped[j] )
+ throw new AtlasException("Bad mapping: duplicate: "+domain+" -> "+range) ;
+ cols[i] = j ;
+ mapped[j] = true ;
+ }
+ return cols ;
+ }
+
+ @Override
+ public String toString()
+ {
+ //return label ;
+ return format("%s:%s%s", label, mapStr(insertOrder), mapStr(fetchOrder)) ;
+ }
+
+ private Object mapStr(int[] map)
+ {
+ StringBuilder buff = new StringBuilder() ;
+ String sep = "{" ;
+
+ for ( int i = 0 ; i < map.length ; i++ )
+ {
+ buff.append(sep) ;
+ sep = ", " ;
+ buff.append(format("%d->%d", i, map[i])) ;
+ }
+ buff.append("}") ;
+
+ return buff.toString() ;
+ }
+
+ public String getLabel()
+ {
+ return label ;
+ }
+
+ /** Reorder the letters of a string by the same rules as this column map (forward, map direction)*/
+ public String mapName(String word)
+ {
+ return mapString(word, insertOrder) ;
+ }
+
+ /** Reorder the letters of a string by the same rules as this column map (backward, fetch direction) */
+ public String unmapName(String word)
+ {
+ return mapString(word, fetchOrder) ;
+ }
+
+ // Map is get from i and put to j
+ private String mapString(String src, int[] map)
+ {
+ char[] chars = new char[src.length()] ;
+ for ( int i = 0 ; i < src.length() ; i++ )
+ {
+ int j = map[i] ;
+ chars[j] = src.charAt(i) ;
+ }
+ return new String(chars) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/DS.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/DS.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/DS.java
new file mode 100644
index 0000000..f9c7095
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/DS.java
@@ -0,0 +1,45 @@
+/*
+ * 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.lib;
+
+
+import java.util.* ;
+
+public class DS
+{
+ private DS() {}
+
+ public static <X> Set<X> setOfNone() { return Collections.emptySet() ; }
+ public static <X> Set<X> setOfOne(X element) { return Collections.singleton(element) ; }
+ public static <X> Set<X> set() { return new HashSet<>(); }
+ public static <X> Set<X> set(int initialSize) { return new HashSet<>(initialSize); }
+ public static <X> Set<X> set(Set<X> other) { return new HashSet<>(other); }
+
+ public static <K, V> Map<K,V> mapOfNone() { return Collections.emptyMap() ; }
+ public static <K, V> Map<K,V> mapOfOne(K key, V value) { return Collections.singletonMap(key, value) ; }
+ public static <K, V> Map<K,V> map() { return new HashMap<>(); }
+ public static <K, V> Map<K,V> map(int initialSize) { return new HashMap<>(initialSize); }
+ public static <K, V> Map<K,V> map(Map<K,V> other) { return new HashMap<>(other); }
+
+ public static <T> List<T> listOfNone() { return Collections.emptyList() ; }
+ public static <T> List<T> listOfOne(T element) { return Collections.singletonList(element) ; }
+ public static <T> List<T> list() { return new ArrayList<>(); }
+ public static <T> List<T> list(int initialSize) { return new ArrayList<>(initialSize); }
+ public static <T> List<T> list(List<T> other) { return new ArrayList<>(other); }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/DateTimeUtils.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/DateTimeUtils.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/DateTimeUtils.java
new file mode 100644
index 0000000..b33a514
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/DateTimeUtils.java
@@ -0,0 +1,127 @@
+/**
+ * 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.lib;
+
+import java.util.Calendar ;
+import java.util.Date ;
+import java.util.GregorianCalendar ;
+
+import org.apache.commons.lang3.time.FastDateFormat ;
+
+public class DateTimeUtils {
+
+ // Include timezone (even xsd:dates have timezones; Calendars have timezones)
+ // NB in SimpleDateFormat != FastDateFormat
+ // SimpleDateFormat does not format Calendars.
+ // SimpleDateFormat has "X" for ISO format tmezones (+00:00)
+ // FastDateFormat uses "ZZ" for this.
+ private static final FastDateFormat dateTimeFmt_display = FastDateFormat.getInstance("yyyy/MM/dd HH:mm:ss z") ;
+ private static final FastDateFormat dateFmt_yyyymmdd = FastDateFormat.getInstance("yyyy-MM-ddZZ") ;
+ // For milliseconds == 0
+ private static final FastDateFormat dateTimeFmt_XSD_ms0 = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ssZZ") ;
+ // For milliseconds != 0
+ private static final FastDateFormat dateTimeFmt_XSD_ms = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSSZZ") ;
+ // For milliseconds == 0
+ private static final FastDateFormat timeFmt_XSD_ms0 = FastDateFormat.getInstance("HH:mm:ssZZ") ;
+ // For milliseconds != 0
+ private static final FastDateFormat timeFmt_XSD_ms = FastDateFormat.getInstance("HH:mm:ss.SSSZZ") ;
+
+ public static String nowAsXSDDateTimeString() {
+ return calendarToXSDDateTimeString(new GregorianCalendar()) ;
+ }
+
+ public static String todayAsXSDDateString() {
+ return calendarToXSDDateString(new GregorianCalendar()) ;
+ }
+
+ /** Return "now" as readable string (date in yyyy/MM/dd format) */
+ public static String nowAsString() {
+ return nowAsString(dateTimeFmt_display) ;
+ }
+
+ public static String nowAsString(String formatString) {
+ FastDateFormat df = FastDateFormat.getInstance(formatString) ;
+ return df.format(new Date()) ;
+ }
+
+ public static String nowAsString(FastDateFormat dateFormat) {
+ return dateFormat.format(new Date()) ;
+ }
+
+ private static boolean hasZeroMilliSeconds(Calendar cal) {
+ return ! cal.isSet(Calendar.MILLISECOND) || cal.get(Calendar.MILLISECOND) == 0 ;
+ }
+
+ // Canonical fom : if ms == 0, don't include in the string.
+ public static String calendarToXSDDateTimeString(Calendar cal) {
+ FastDateFormat fmt = hasZeroMilliSeconds(cal)
+ ? dateTimeFmt_XSD_ms0
+ : dateTimeFmt_XSD_ms ;
+ return calendarToXSDString(cal, fmt) ;
+ }
+
+ public static String calendarToXSDDateString(Calendar cal) {
+ return calendarToXSDString(cal, dateFmt_yyyymmdd) ;
+ }
+
+ // Canonical fom : if ms == 0, don't include in the string.
+ public static String calendarToXSDTimeString(Calendar cal) {
+ FastDateFormat fmt = hasZeroMilliSeconds(cal)
+ ? timeFmt_XSD_ms0
+ : timeFmt_XSD_ms ;
+ return calendarToXSDString(cal, fmt) ;
+ }
+
+ private static String calendarToXSDString(Calendar cal, FastDateFormat fmt) {
+ String lex = fmt.format(cal) ;
+ // lex = lex + calcTimezone(cal) ;
+ return lex ;
+ }
+
+ // Not needed because of FastDateFormat
+// private static String calcTimezone(Calendar cal) {
+// Date date = cal.getTime() ;
+// TimeZone z = cal.getTimeZone() ;
+// int tz = z.getRawOffset() ;
+//
+// if ( z.inDaylightTime(date) ) {
+// int tzDst = z.getDSTSavings() ;
+// tz = tz + tzDst ;
+// }
+//
+// String sign = "+" ;
+// if ( tz < 0 ) {
+// sign = "-" ;
+// tz = -tz ;
+// }
+//
+// int tzH = tz / (60 * 60 * 1000) ; // Integer divide towards zero.
+// int tzM = (tz - tzH * 60 * 60 * 1000) / (60 * 1000) ;
+//
+// String tzH_str = Integer.toString(tzH) ;
+// String tzM_str = Integer.toString(tzM) ;
+//
+// if ( tzH < 10 )
+// tzH_str = "0" + tzH_str ;
+// if ( tzM < 10 )
+// tzM_str = "0" + tzM_str ;
+// return sign + tzH_str + ":" + tzM_str ;
+// }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/EscapeStr.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/EscapeStr.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/EscapeStr.java
new file mode 100644
index 0000000..cd387f6
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/EscapeStr.java
@@ -0,0 +1,235 @@
+/*
+ * 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.lib;
+
+import org.apache.jena.atlas.AtlasException ;
+import org.apache.jena.atlas.io.AWriter ;
+import org.apache.jena.atlas.io.IndentedLineBuffer ;
+import org.apache.jena.atlas.io.OutputUtils ;
+
+public class EscapeStr
+{
+ // Tests: TestOutput
+ // See also OutputLangUtils.outputEsc.
+// private final boolean ascii ;
+//
+// public EscapeStr(CharSpace charSpace) { this.ascii = ( charSpace == CharSpace.ASCII ) ; }
+//
+// public void writeURI(AWriter w, String s)
+// {
+// if ( ascii )
+// stringEsc(w, s, true, ascii) ;
+// else
+// // It's a URI - assume legal.
+// w.print(s) ;
+// }
+//
+// public void writeStr(AWriter w, String s)
+// {
+// stringEsc(w, s, true, ascii) ;
+// }
+//
+// public void writeStrMultiLine(AWriter w, String s)
+// {
+// // N-Triples does not have """
+// stringEsc(w, s, false, ascii) ;
+// }
+//
+ // Utility
+ /*
+ * Escape characters in a string according to Turtle rules.
+ */
+ public static String stringEsc(String s)
+ { return stringEsc(s, true, false) ; }
+
+ private static String stringEsc(String s, boolean singleLineString, boolean asciiOnly)
+ {
+ IndentedLineBuffer sb = new IndentedLineBuffer() ;
+ stringEsc(sb, s, singleLineString, asciiOnly) ;
+ return sb.toString() ;
+ }
+
+ public static void stringEsc(AWriter out, String s, boolean singleLineString, boolean asciiOnly)
+ {
+ int len = s.length() ;
+ for (int i = 0; i < len; i++) {
+ char c = s.charAt(i);
+
+ // \\ Escape always possible.
+ if (c == '\\')
+ {
+ out.print('\\') ;
+ out.print(c) ;
+ continue ;
+ }
+ if ( singleLineString )
+ {
+ if ( c == '"' ) { out.print("\\\""); continue ; }
+ else if (c == '\n') { out.print("\\n"); continue ; }
+ else if (c == '\t') { out.print("\\t"); continue ; }
+ else if (c == '\r') { out.print("\\r"); continue ; }
+ else if (c == '\f') { out.print("\\f"); continue ; }
+ }
+ // Not \-style esacpe.
+ if ( c >= 32 && c < 127 )
+ out.print(c);
+ else if ( !asciiOnly )
+ out.print(c);
+ else
+ {
+ // Outside the charset range.
+ // Does not cover beyond 16 bits codepoints directly
+ // (i.e. \U escapes) but Java keeps these as surrogate
+ // pairs and will print as characters
+ out.print( "\\u") ;
+ OutputUtils.printHex(out, c, 4) ;
+ }
+ }
+ }
+
+ // Utilities to remove escapes
+
+ /** Replace \ escapes (\\u, \t, \n etc) in a string */
+ public static String unescapeStr(String s)
+ { return unescapeStr(s, '\\') ; }
+
+ /** Replace \ escapes (\\u, \t, \n etc) in a string */
+ public static String unescapeStr(String s, char escapeChar)
+ { return unescape(s, escapeChar, false) ; }
+
+ // Main worker function for unescaping strings.
+ public static String unescape(String s, char escape, boolean pointCodeOnly) {
+ int i = s.indexOf(escape) ;
+
+ if ( i == -1 )
+ return s ;
+
+ // Dump the initial part straight into the string buffer
+ StringBuilder sb = new StringBuilder(s.substring(0,i)) ;
+
+ for ( ; i < s.length() ; i++ )
+ {
+ char ch = s.charAt(i) ;
+
+ if ( ch != escape )
+ {
+ sb.append(ch) ;
+ continue ;
+ }
+
+ // Escape
+ if ( i >= s.length()-1 )
+ throw new AtlasException("Illegal escape at end of string") ;
+ char ch2 = s.charAt(i+1) ;
+ i = i + 1 ;
+
+ // \\u and \\U
+ if ( ch2 == 'u' )
+ {
+ // i points to the \ so i+6 is next character
+ if ( i+4 >= s.length() )
+ throw new AtlasException("\\u escape too short") ;
+ int x = hex(s, i+1, 4) ;
+ sb.append((char)x) ;
+ // Jump 1 2 3 4 -- already skipped \ and u
+ i = i+4 ;
+ continue ;
+ }
+ if ( ch2 == 'U' )
+ {
+ // i points to the \ so i+6 is next character
+ if ( i+8 >= s.length() )
+ throw new AtlasException("\\U escape too short") ;
+ int x = hex(s, i+1, 8) ;
+ // Convert to UTF-16 codepoint pair.
+ sb.append((char)x) ;
+ // Jump 1 2 3 4 5 6 7 8 -- already skipped \ and u
+ i = i+8 ;
+ continue ;
+ }
+
+ // Are we doing just point code escapes?
+ // If so, \X-anything else is legal as a literal "\" and "X"
+
+ if ( pointCodeOnly )
+ {
+ sb.append('\\') ;
+ sb.append(ch2) ;
+ i = i + 1 ;
+ continue ;
+ }
+
+ // Not just codepoints. Must be a legal escape.
+ char ch3 = 0 ;
+ switch (ch2)
+ {
+ case 'n': ch3 = '\n' ; break ;
+ case 't': ch3 = '\t' ; break ;
+ case 'r': ch3 = '\r' ; break ;
+ case 'b': ch3 = '\b' ; break ;
+ case 'f': ch3 = '\f' ; break ;
+ case '\'': ch3 = '\'' ; break ;
+ case '\"': ch3 = '\"' ; break ;
+ case '\\': ch3 = '\\' ; break ;
+ default:
+ throw new AtlasException("Unknown escape: \\"+ch2) ;
+ }
+ sb.append(ch3) ;
+ }
+ return sb.toString() ;
+ }
+
+ public static int hex(String s, int i, int len)
+ {
+// if ( i+len >= s.length() )
+// {
+//
+// }
+ int x = 0 ;
+ for ( int j = i ; j < i+len ; j++ )
+ {
+ char ch = s.charAt(j) ;
+ int k = 0 ;
+ switch (ch)
+ {
+ case '0': k = 0 ; break ;
+ case '1': k = 1 ; break ;
+ case '2': k = 2 ; break ;
+ case '3': k = 3 ; break ;
+ case '4': k = 4 ; break ;
+ case '5': k = 5 ; break ;
+ case '6': k = 6 ; break ;
+ case '7': k = 7 ; break ;
+ case '8': k = 8 ; break ;
+ case '9': k = 9 ; break ;
+ case 'A': case 'a': k = 10 ; break ;
+ case 'B': case 'b': k = 11 ; break ;
+ case 'C': case 'c': k = 12 ; break ;
+ case 'D': case 'd': k = 13 ; break ;
+ case 'E': case 'e': k = 14 ; break ;
+ case 'F': case 'f': k = 15 ; break ;
+ default:
+ throw new AtlasException("Illegal hex escape: "+ch) ;
+ }
+ x = (x<<4)+k ;
+ }
+ return x ;
+ }
+
+}
[8/9] jena git commit: Import of lib, io,
logging and iterator packages
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/InputStreamBuffered.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/InputStreamBuffered.java b/jena-base/src/main/java/org/apache/jena/atlas/io/InputStreamBuffered.java
new file mode 100644
index 0000000..9b03d43
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/InputStreamBuffered.java
@@ -0,0 +1,104 @@
+/*
+ * 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.io;
+
+import static org.apache.jena.atlas.io.IO.EOF ;
+
+import java.io.IOException ;
+import java.io.InputStream ;
+
+/** InputStream optimizing for one byte at a time operation.
+ * BufferedInputStream operations have synchronization making
+ * reading one byte at a time expensive.
+ *
+ * @see java.io.InputStream
+ * @see java.io.BufferedInputStream
+ */
+public final class InputStreamBuffered extends InputStream
+{
+ public static int DFT_BUFSIZE = 16*1024 ;
+ private InputStream source ;
+ private byte[] buffer ;
+ private int buffLen = 0 ;
+ private int idx = 0 ;
+ private long count = 0 ;
+
+ public InputStreamBuffered(InputStream input)
+ {
+ this(input, DFT_BUFSIZE) ;
+ }
+
+ public InputStreamBuffered(InputStream input, int bufsize)
+ {
+ super() ;
+ this.source = input ;
+ this.buffer = new byte[bufsize] ;
+ this.idx = 0 ;
+ this.buffLen = 0 ;
+ }
+
+// @Override
+// public int read(byte b[], int off, int len) throws IOException
+// {
+// }
+
+ @Override
+ public int read() throws IOException
+ {
+ return advance() ;
+ }
+
+ @Override
+ public void close() throws IOException
+ {
+ source.close() ;
+ }
+
+ public final int advance()
+ {
+ if ( idx >= buffLen )
+ // Points outside the array. Refill it
+ fillArray() ;
+
+ // Advance one character.
+ if ( buffLen >= 0 )
+ {
+ byte ch = buffer[idx] ;
+ // Advance the lookahead character
+ idx++ ;
+ count++ ;
+ return ch & 0xFF ;
+ }
+ else
+ // Buffer empty, end of stream.
+ return EOF ;
+ }
+
+ private int fillArray()
+ {
+ try
+ {
+ int x = source.read(buffer) ;
+ idx = 0 ;
+ buffLen = x ; // Maybe -1
+ return x ;
+ }
+ catch (IOException ex) { IO.exception(ex) ; return -1 ; }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/NullOutputStream.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/NullOutputStream.java b/jena-base/src/main/java/org/apache/jena/atlas/io/NullOutputStream.java
new file mode 100644
index 0000000..8986f9e
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/NullOutputStream.java
@@ -0,0 +1,40 @@
+/**
+ * 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.io;
+
+import java.io.OutputStream ;
+
+/** /dev/null */
+public class NullOutputStream extends OutputStream {
+
+ private static final NullOutputStream DEV_NULL = new NullOutputStream();
+
+ public static OutputStream sink() {
+ return DEV_NULL ;
+ }
+
+ public NullOutputStream() {}
+
+ @Override public void write(int b) {}
+
+ @Override public void write(byte b[]) {}
+
+ @Override public void write(byte b[], int off, int len) { }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/OutStreamUTF8.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/OutStreamUTF8.java b/jena-base/src/main/java/org/apache/jena/atlas/io/OutStreamUTF8.java
new file mode 100644
index 0000000..d4d15d4
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/OutStreamUTF8.java
@@ -0,0 +1,179 @@
+/*
+ * 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.io;
+
+import java.io.IOException ;
+import java.io.OutputStream ;
+import java.io.Writer ;
+
+/** Output UTF-8 encoded data.
+ * This class implements the "Modified UTF8" encoding rules (null -> C0 80)
+ * It will encode any 16 bit value.
+ * It can be used as a pure UTf-8 encoder.
+ *
+ * @see InStreamUTF8
+ */
+public final class OutStreamUTF8 extends Writer
+{
+ private OutputStream out ;
+
+ public OutStreamUTF8(OutputStream out)
+ {
+ // Buffer?
+ this.out = out ;
+ }
+
+ @Override
+ public void write(char[] cbuf, int off, int len) throws IOException
+ {
+ for ( int i = 0 ; i < len; i++ )
+ write(cbuf[off+i]) ;
+ }
+
+ @Override
+ public void write(int ch) throws IOException
+ { output(out, ch) ; }
+
+ @Override
+ public void write(char[] b) throws IOException
+ { write(b, 0, b.length) ; }
+
+ @Override
+ public void write(String str) throws IOException
+ { write(str,0, str.length()) ; }
+
+ @Override
+ public void write(String str, int idx, int len) throws IOException
+ {
+ for ( int i = 0 ; i < len; i++ )
+ write(str.charAt(idx+i)) ;
+ }
+
+ public void output(int x)
+ {
+ try {
+ output(out, x) ;
+ } catch (IOException ex) { IO.exception(ex) ; }
+ }
+
+ /*
+ * Bits
+ * 7 U+007F 1 to 127 0xxxxxxx
+ * 11 U+07FF 128 to 2,047 110xxxxx 10xxxxxx
+ * 16 U+FFFF 2,048 to 65,535 1110xxxx 10xxxxxx 10xxxxxx
+ * 21 U+1FFFFF 65,536 to 1,114,111 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ * 26 U+3FFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+ * 31 U+7FFFFFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+ */
+ public static void output(OutputStream out, int ch) throws IOException
+ {
+ if ( ch != 0 && ch <= 127 )
+ {
+ // 7 bits
+ out.write(ch) ;
+ return ;
+ }
+
+ if ( ch == 0 )
+ {
+ // Modified UTF-8.
+ out.write(0xC0) ;
+ out.write(0x80) ;
+ return ;
+ }
+
+ // Better? output(int HiMask, int byte length, int value)
+
+ if ( ch <= 0x07FF )
+ {
+ // 11 bits : 110yyyyy 10xxxxxx
+ // int x1 = ( ((ch>>(11-5))&0x7) | 0xC0 ) ; outputBytes(out, x1, 2, ch) ; return ;
+ int x1 = ( ((ch>>(11-5))&0x01F ) | 0xC0 ) ;
+ int x2 = ( (ch&0x3F) | 0x80 ) ;
+ out.write(x1) ;
+ out.write(x2) ;
+ return ;
+ }
+ if ( ch <= 0xFFFF )
+ {
+ // 16 bits : 1110aaaa 10bbbbbb 10cccccc
+ // int x1 = ( ((ch>>(16-4))&0x7) | 0xE0 ) ; outputBytes(out, x1, 3, ch) ; return ;
+ int x1 = ( ((ch>>(16-4))&0x0F) | 0xE0 ) ;
+ int x2 = ( ((ch>>6)&0x3F) | 0x80 ) ;
+ int x3 = ( (ch&0x3F) | 0x80 ) ;
+ out.write(x1) ;
+ out.write(x2) ;
+ out.write(x3) ;
+ return ;
+ }
+
+// if ( Character.isDefined(ch) )
+// throw new AtlasException("not a character") ;
+
+ //if ( true ) throw new InternalErrorException("Valid code point for Java but not encodable") ;
+
+ // Not java, where chars are 16 bit.
+ if ( ch <= 0x1FFFFF )
+ {
+ // 21 bits : 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ int x1 = ( ((ch>>(21-3))&0x7) | 0xF0 ) ;
+ outputBytes(out, x1, 4, ch) ;
+ return ;
+ }
+ if ( ch <= 0x3FFFFFF )
+ {
+ // 26 bits : 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+ int x1 = ( ((ch>>(26-2))&0x3) | 0xF8 ) ;
+ outputBytes(out, x1, 5, ch) ;
+ return ;
+ }
+
+ if ( ch <= 0x7FFFFFFF )
+ {
+ // 32 bits : 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+ int x1 = ( ((ch>>(32-1))&0x1) | 0xFC ) ;
+ outputBytes(out, x1, 6, ch) ;
+ return ;
+ }
+ }
+
+ private static void outputBytes(OutputStream out, int x1, int byteLength, int ch) throws IOException
+ {
+ // ByteLength = 3 => 2 byteLenth => shift=6 and shift=0
+ out.write(x1) ;
+ byteLength-- ; // remaining bytes
+ for ( int i = 0 ; i < byteLength ; i++ )
+ {
+ // 6 Bits, loop from high to low
+ int shift = 6*(byteLength-i-1) ;
+ int x = (ch>>shift) & 0x3F ;
+ x = x | 0x80 ; // 10xxxxxx
+ out.write(x) ;
+ }
+ }
+
+ @Override
+ public void flush() throws IOException
+ { out.flush(); }
+
+ @Override
+ public void close() throws IOException
+ { out.close() ; }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/OutputUtils.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/OutputUtils.java b/jena-base/src/main/java/org/apache/jena/atlas/io/OutputUtils.java
new file mode 100644
index 0000000..9659643
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/OutputUtils.java
@@ -0,0 +1,77 @@
+/*
+ * 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.io;
+
+import java.io.IOException ;
+import java.io.Writer ;
+
+import org.apache.jena.atlas.lib.BitsInt ;
+import org.apache.jena.atlas.lib.Chars ;
+
+
+public class OutputUtils
+{
+ /** Print the number x in width hex chars. x must fit */
+ public static void printHex(StringBuilder out, int x, int width)
+ {
+ for ( int i = width-1 ; i >= 0 ; i-- )
+ x = oneHex(out, x, i) ;
+ }
+
+ /** Print one hex digit of the number */
+ public static int oneHex(StringBuilder out, int x, int i)
+ {
+ int y = BitsInt.unpack(x, 4*i, 4*i+4) ;
+ char charHex = Chars.hexDigitsUC[y] ;
+ out.append(charHex) ;
+ return BitsInt.clear(x, 4*i, 4*i+4) ;
+ }
+
+ /** Print the number x in width hex chars. x must fit */
+ public static void printHex(Writer out, int x, int width)
+ {
+ for ( int i = width-1 ; i >= 0 ; i-- )
+ x = oneHex(out, x, i) ;
+ }
+
+ /** Print one hex digit of the number */
+ public static int oneHex(Writer out, int x, int i)
+ {
+ int y = BitsInt.unpack(x, 4*i, 4*i+4) ;
+ char charHex = Chars.hexDigitsUC[y] ;
+ try { out.write(charHex) ; } catch (IOException ex) {}
+ return BitsInt.clear(x, 4*i, 4*i+4) ;
+ }
+
+ /** Print the number x in width hex chars. x must fit */
+ public static void printHex(AWriter out, int x, int width)
+ {
+ for ( int i = width-1 ; i >= 0 ; i-- )
+ x = oneHex(out, x, i) ;
+ }
+
+ /** Print one hex digit of the number */
+ public static int oneHex(AWriter out, int x, int i)
+ {
+ int y = BitsInt.unpack(x, 4*i, 4*i+4) ;
+ char charHex = Chars.hexDigitsUC[y] ;
+ out.print(charHex) ;
+ return BitsInt.clear(x, 4*i, 4*i+4) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/PeekInputStream.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/PeekInputStream.java b/jena-base/src/main/java/org/apache/jena/atlas/io/PeekInputStream.java
new file mode 100644
index 0000000..4a6403c
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/PeekInputStream.java
@@ -0,0 +1,233 @@
+/*
+ * 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.io;
+
+import static org.apache.jena.atlas.io.IO.EOF ;
+import static org.apache.jena.atlas.io.IO.UNSET ;
+
+import java.io.FileInputStream ;
+import java.io.FileNotFoundException ;
+import java.io.IOException ;
+import java.io.InputStream ;
+
+import org.apache.jena.atlas.AtlasException ;
+import org.apache.jena.atlas.RuntimeIOException ;
+
+/** Parsing-centric input stream.
+ * @see PeekReader
+ */
+
+
+public final class PeekInputStream extends InputStream
+{
+ // Change to looking at slices of a ByteBuffer and rework TokenizerBytes
+
+ private final InputStreamBuffered source ;
+
+ private static final int PUSHBACK_SIZE = 10 ;
+ static final byte BYTE0 = (byte)0 ;
+
+ private byte[] pushbackBytes ;
+ private int idxPushback ; // Index into pushbackBytes: points to next pushBack. -1 => none.
+
+ private int currByte = UNSET ; // Next byte to return when reading forwards.
+ private long posn ;
+
+ public static final int INIT_LINE = 1 ;
+ public static final int INIT_COL = 1 ;
+
+ private long colNum ;
+ private long lineNum ;
+
+ // ---- static construction methods.
+
+ public static PeekInputStream make(InputStream inputStream)
+ {
+ return make(inputStream, InputStreamBuffered.DFT_BUFSIZE) ;
+ }
+
+ public static PeekInputStream make(InputStream inputStream, int bufferSize)
+ {
+ if ( inputStream instanceof PeekInputStream )
+ return (PeekInputStream)inputStream ;
+
+ if ( inputStream instanceof InputStreamBuffered )
+ return new PeekInputStream((InputStreamBuffered)inputStream) ;
+ InputStreamBuffered in = new InputStreamBuffered(inputStream, bufferSize) ;
+ return new PeekInputStream(in) ;
+ }
+
+ public static PeekInputStream open(String filename)
+ {
+ try {
+ InputStream in = new FileInputStream(filename) ;
+ return make(in) ;
+ } catch (FileNotFoundException ex){ throw new AtlasException("File not found: "+filename) ; }
+ }
+
+ private PeekInputStream(InputStreamBuffered input)
+ {
+ this.source = input ;
+ this.pushbackBytes = new byte[PUSHBACK_SIZE] ;
+ this.idxPushback = -1 ;
+
+ this.colNum = INIT_COL ;
+ this.lineNum = INIT_LINE ;
+ this.posn = 0 ;
+
+ // We start at byte "-1", i.e. just before the file starts.
+ // Advance always so that the peek byte is valid (is byte 0)
+ // Returns the byte before the file starts (i.e. UNSET).
+ }
+
+ public final InputStreamBuffered getInput() { return source ; }
+
+ public long getLineNum() { return lineNum; }
+
+ public long getColNum() { return colNum; }
+
+ public long getPosition() { return posn; }
+
+ //---- Do not access currByte except with peekByte/setCurrByte.
+ public final int peekByte()
+ {
+ if ( idxPushback >= 0 )
+ return pushbackBytes[idxPushback] ;
+
+ // If not started ... delayed initialization.
+ if ( currByte == UNSET )
+ init() ;
+ return currByte ;
+ }
+
+ // And the correct way to read the currByte is to call peekByte
+ private final void setCurrByte(int b)
+ {
+ currByte = b ;
+ }
+
+ public final int readByte() { return nextByte() ; }
+
+ /** push back a byte : does not alter underlying position, line or column counts*/
+ public final void pushbackByte(int b) { unreadByte(b) ; }
+
+ @Override
+ public final void close() throws IOException
+ {
+ source.close() ;
+ }
+
+ @Override
+ public final int read() throws IOException
+ {
+ if ( eof() )
+ return EOF ;
+ int x = readByte() ;
+ return x ;
+ }
+
+ @Override
+ public final int read(byte[] buf, int off, int len) throws IOException
+ {
+ if ( eof() )
+ return EOF ;
+ for ( int i = 0 ; i < len ; i++ )
+ {
+ int ch = readByte() ;
+ if ( ch == EOF )
+ return (i==0)? EOF : i ;
+ buf[i+off] = (byte)ch ;
+ }
+ return len ;
+ }
+
+ public final boolean eof() { return peekByte() == EOF ; }
+
+ // ----------------
+ // The methods below are the only ones to manipulate the byte buffers.
+ // Other methods may read the state of variables.
+
+ private final void unreadByte(int b)
+ {
+ // The push back buffer is in the order where [0] is the oldest.
+ // Does not alter the line number, column number or position count.
+
+ if ( idxPushback >= pushbackBytes.length )
+ {
+ // Enlarge pushback buffer.
+ byte[] pushbackBytes2 = new byte[pushbackBytes.length*2] ;
+ System.arraycopy(pushbackBytes, 0, pushbackBytes2, 0, pushbackBytes.length) ;
+ pushbackBytes = pushbackBytes2 ;
+ //throw new JenaException("Pushback buffer overflow") ;
+ }
+ if ( b == EOF || b == UNSET )
+ throw new RuntimeIOException("Illegal byte to push back: "+b) ;
+
+ idxPushback++ ;
+ pushbackBytes[idxPushback] = (byte)b ;
+ }
+
+ private final void init()
+ {
+ advanceAndSet() ;
+ if ( currByte == UNSET )
+ setCurrByte(EOF) ;
+ }
+
+ private final void advanceAndSet()
+ {
+ try {
+ int ch = source.read() ;
+ setCurrByte(ch) ;
+ } catch (IOException ex) { IO.exception(ex) ; }
+ }
+
+
+ // Invariants.
+ // currByte is either bytes[idx-1] or pushbackBytes[idxPushback]
+
+ /** Return the next byte, moving on one place and resetting the peek byte */
+ private final int nextByte()
+ {
+ int b = peekByte() ;
+
+ if ( b == EOF )
+ return EOF ;
+
+ if ( idxPushback >= 0 )
+ {
+ byte b2 = pushbackBytes[idxPushback] ;
+ idxPushback-- ;
+ return b2 ;
+ }
+
+ posn++ ;
+
+ if (b == '\n')
+ {
+ lineNum++;
+ colNum = INIT_COL ;
+ }
+ else
+ colNum++;
+
+ advanceAndSet() ;
+ return b ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/PeekReader.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/PeekReader.java b/jena-base/src/main/java/org/apache/jena/atlas/io/PeekReader.java
new file mode 100644
index 0000000..31076b0
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/PeekReader.java
@@ -0,0 +1,270 @@
+/*
+ * 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.io ;
+
+import static org.apache.jena.atlas.io.IO.EOF ;
+import static org.apache.jena.atlas.io.IO.UNSET ;
+
+import java.io.* ;
+
+import org.apache.jena.atlas.AtlasException ;
+import org.apache.jena.atlas.RuntimeIOException ;
+import org.apache.jena.atlas.lib.Chars ;
+
+/**
+ * Parsing-centric reader. This class is not thread safe.
+ * @see PeekInputStream
+ */
+
+public final class PeekReader extends Reader {
+ // Remember to apply fixes to PeekInputStream as well.
+
+ // Buffering is done by a CharStream - does it make adifference?
+ // Yes. A lot (Java6).
+
+ // Using a Reader here seems to have zero cost or benefit but CharStream
+ // allows fast String handling.
+ private final CharStream source ;
+
+ private static final int PUSHBACK_SIZE = 10 ;
+ static final byte CHAR0 = (char)0 ;
+
+ private char[] pushbackChars ;
+ // Index into pushbackChars: points to next pushBack.
+ // -1 => none.
+ private int idxPushback ;
+
+ // Next character to return when reading forwards.
+ private int currChar = UNSET ;
+ private long posn ;
+
+ public static final int INIT_LINE = 1 ;
+ public static final int INIT_COL = 1 ;
+
+ private long colNum ;
+ private long lineNum ;
+
+ // ---- static construction methods.
+
+ public static PeekReader make(Reader r) {
+ if ( r instanceof PeekReader )
+ return (PeekReader)r ;
+ return make(r, CharStreamBuffered.CB_SIZE) ;
+ }
+
+ public static PeekReader make(Reader r, int bufferSize) {
+ // It is worth our own buffering even if a BufferedReader
+ // because of the synchronized on one char reads in BufferedReader.
+ return new PeekReader(new CharStreamBuffered(r, bufferSize)) ;
+ }
+
+ /** Make PeekReader where the input is UTF8 : BOM is removed */
+ public static PeekReader makeUTF8(InputStream in) {
+ // This is the best route to make a PeekReader because it avoids
+ // chances of wrong charset for a Reader say.
+ PeekReader pr ;
+ if ( true ) {
+ Reader r = IO.asUTF8(in) ;
+ // This adds reader-level buffering
+ pr = make(r) ;
+ } else {
+ // This is a bit slower - reason unknown.
+ InputStreamBuffered in2 = new InputStreamBuffered(in) ;
+ CharStream r = new InStreamUTF8(in2) ;
+ pr = new PeekReader(r) ;
+ }
+ // Skip BOM.
+ int ch = pr.peekChar() ;
+ if ( ch == Chars.BOM )
+ // Skip BOM
+ pr.readChar() ;
+ return pr ;
+ }
+
+ /** Make PeekReader where the input is ASCII */
+ public static PeekReader makeASCII(InputStream in) {
+ Reader r = IO.asASCII(in) ;
+ return make(r) ;
+ }
+
+ public static PeekReader make(CharStream r) {
+ return new PeekReader(r) ;
+ }
+
+ public static PeekReader readString(String string) {
+ return new PeekReader(new CharStreamSequence(string)) ;
+ }
+
+ public static PeekReader open(String filename) {
+ try {
+ InputStream in = new FileInputStream(filename) ;
+ return makeUTF8(in) ;
+ } catch (FileNotFoundException ex) {
+ throw new AtlasException("File not found: " + filename) ;
+ }
+ }
+
+ private PeekReader(CharStream stream) {
+ this.source = stream ;
+ this.pushbackChars = new char[PUSHBACK_SIZE] ;
+ this.idxPushback = -1 ;
+
+ this.colNum = INIT_COL ;
+ this.lineNum = INIT_LINE ;
+ this.posn = 0 ;
+ }
+
+ public long getLineNum() {
+ return lineNum ;
+ }
+
+ public long getColNum() {
+ return colNum ;
+ }
+
+ public long getPosition() {
+ return posn ;
+ }
+
+ // ---- Do not access currChar except with peekChar/setCurrChar.
+ public final int peekChar() {
+ if ( idxPushback >= 0 )
+ return pushbackChars[idxPushback] ;
+
+ // If not started ... delayed initialization.
+ if ( currChar == UNSET )
+ init() ;
+ return currChar ;
+ }
+
+ // And the correct way to read the currChar is to call peekChar.
+ private final void setCurrChar(int ch) {
+ currChar = ch ;
+ }
+
+ public final int readChar() {
+ return nextChar() ;
+ }
+
+ /**
+ * push back a character : does not alter underlying position, line or
+ * column counts
+ */
+ public final void pushbackChar(int ch) {
+ unreadChar(ch) ;
+ }
+
+ // Reader operations
+ @Override
+ public final void close() throws IOException {
+ source.closeStream() ;
+ }
+
+ @Override
+ public final int read() throws IOException {
+ if ( eof() )
+ return EOF ;
+ int x = readChar() ;
+ return x ;
+ }
+
+ @Override
+ public final int read(char[] cbuf, int off, int len) throws IOException {
+ if ( eof() )
+ return EOF ;
+ // Note - we need to preserve line count
+ // Single char ops are reasonably efficient.
+ for (int i = 0; i < len; i++) {
+ int ch = readChar() ;
+ if ( ch == EOF )
+ return (i == 0) ? EOF : i ;
+ cbuf[i + off] = (char)ch ;
+ }
+ return len ;
+ }
+
+ public final boolean eof() {
+ return peekChar() == EOF ;
+ }
+
+ // ----------------
+ // The methods below are the only ones to manipulate the character buffers.
+ // Other methods may read the state of variables.
+
+ private final void unreadChar(int ch) {
+ // The push back buffer is in the order where [0] is the oldest.
+ // Does not alter the line number, column number or position count
+ // not does reading a pushback charcater.
+
+ if ( idxPushback >= pushbackChars.length ) {
+ // Enlarge pushback buffer.
+ char[] pushbackChars2 = new char[pushbackChars.length * 2] ;
+ System.arraycopy(pushbackChars, 0, pushbackChars2, 0, pushbackChars.length) ;
+ pushbackChars = pushbackChars2 ;
+ // throw new JenaException("Pushback buffer overflow") ;
+ }
+ if ( ch == EOF || ch == UNSET )
+ throw new RuntimeIOException("Illegal character to push back: " + ch) ;
+
+ idxPushback++ ;
+ pushbackChars[idxPushback] = (char)ch ;
+ }
+
+ private final void init() {
+ advanceAndSet() ;
+ if ( currChar == UNSET )
+ setCurrChar(EOF) ;
+ }
+
+ private final void advanceAndSet() {
+ int ch = source.advance() ;
+ setCurrChar(ch) ;
+ }
+
+ // Invariants.
+ // currChar is either chars[idx-1] or pushbackChars[idxPushback]
+
+ /**
+ * Return the next character, moving on one place and resetting the peek
+ * character
+ */
+ private final int nextChar() {
+ int ch = peekChar() ;
+
+ if ( ch == EOF )
+ return EOF ;
+
+ if ( idxPushback >= 0 ) {
+ char ch2 = pushbackChars[idxPushback] ;
+ idxPushback-- ;
+ return ch2 ;
+ }
+
+ posn++ ;
+
+ if ( ch == '\n' ) {
+ lineNum++ ;
+ colNum = INIT_COL ;
+ } else
+ colNum++ ;
+
+ advanceAndSet() ;
+ return ch ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/PrintUtils.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/PrintUtils.java b/jena-base/src/main/java/org/apache/jena/atlas/io/PrintUtils.java
new file mode 100644
index 0000000..14e4ed1
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/PrintUtils.java
@@ -0,0 +1,31 @@
+/*
+ * 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.io;
+
+
+public class PrintUtils
+{
+ // ---- Printable
+ public static String toString(Printable f)
+ {
+ IndentedLineBuffer buff = new IndentedLineBuffer() ;
+ f.output(buff) ;
+ return buff.toString() ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/Printable.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/Printable.java b/jena-base/src/main/java/org/apache/jena/atlas/io/Printable.java
new file mode 100644
index 0000000..69bd211
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/Printable.java
@@ -0,0 +1,24 @@
+/*
+ * 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.io;
+
+public interface Printable
+{
+ public void output(IndentedWriter out) ;
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/PrintableBase.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/PrintableBase.java b/jena-base/src/main/java/org/apache/jena/atlas/io/PrintableBase.java
new file mode 100644
index 0000000..89fbb24
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/PrintableBase.java
@@ -0,0 +1,26 @@
+/*
+ * 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.io;
+
+// Hmm - hardly worth it!
+public abstract class PrintableBase implements Printable
+{
+ @Override
+ public String toString() { return PrintUtils.toString(this) ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/StringWriterI.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/StringWriterI.java b/jena-base/src/main/java/org/apache/jena/atlas/io/StringWriterI.java
new file mode 100644
index 0000000..5fea4d3
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/StringWriterI.java
@@ -0,0 +1,30 @@
+/**
+ * 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.io;
+
+import java.io.StringWriter ;
+
+public class StringWriterI extends Writer2
+{
+ public StringWriterI()
+ {
+ super(new StringWriter()) ;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/Writer2.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/Writer2.java b/jena-base/src/main/java/org/apache/jena/atlas/io/Writer2.java
new file mode 100644
index 0000000..100ec6f
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/Writer2.java
@@ -0,0 +1,97 @@
+/**
+ * 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.io;
+
+import java.io.BufferedWriter ;
+import java.io.IOException ;
+import java.io.Writer ;
+
+import org.apache.jena.atlas.lib.Closeable ;
+
+/** A Writer, without the checked exceptions. */
+
+public class Writer2 extends AWriterBase implements AWriter, Closeable
+{
+ protected final Writer writer ;
+
+ public static Writer2 wrap(Writer writer)
+ {
+ if ( writer instanceof BufferedWriter )
+ return new Writer2(writer) ;
+ if ( writer instanceof BufferingWriter )
+ return new Writer2(writer) ;
+
+ writer = new BufferingWriter(writer) ;
+ return new Writer2(writer) ;
+ }
+
+ protected Writer2(Writer writer) { this.writer = writer ; }
+
+ @Override
+ public void print(char ch)
+ {
+ try { writer.write(ch) ; } catch (IOException ex) { IO.exception(ex) ; }
+ }
+
+ @Override
+ public void print(String string)
+ {
+ try { writer.write(string) ; } catch (IOException ex) { IO.exception(ex) ; }
+ }
+
+ @Override
+ public void print(char[] cbuf)
+ {
+ try { writer.write(cbuf) ; } catch (IOException ex) { IO.exception(ex) ; }
+ }
+
+ @Override
+ public void flush()
+ {
+ try { writer.flush() ; } catch (IOException ex) { IO.exception(ex) ; }
+ }
+
+ @Override
+ public void close()
+ {
+ try { writer.close() ; } catch (IOException ex) { IO.exception(ex) ; }
+ }
+
+ @Override
+ public void printf(String fmt, Object... args)
+ {
+ print(String.format(fmt, args)) ;
+ }
+
+ @Override
+ public void println(String obj)
+ {
+ print(obj) ; print("\n") ;
+ }
+
+ @Override
+ public void println()
+ {
+ print("\n") ;
+ }
+
+ @Override
+ public String toString() { return writer.toString() ; }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/AccString.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/AccString.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/AccString.java
new file mode 100644
index 0000000..7df3486
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/AccString.java
@@ -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.iterator;
+
+public class AccString<T> implements Accumulate<T, String>
+{
+ StringBuilder buffer = null ;
+ private String sep ;
+ private boolean first = true ;
+
+ // Fresh StringBuilder
+ public AccString(String sep) { this.sep = sep ; }
+ public AccString() { this(" ") ; }
+
+ @Override
+ public void accumulate(T item)
+ {
+ if ( ! first )
+ buffer.append(sep) ;
+ if ( item != null )
+ buffer.append(toString(item)) ;
+ else
+ buffer.append("<null>") ;
+ first = false ;
+ }
+
+ /** Make into a string */
+ protected String toString(T item)
+ {
+ return item.toString() ;
+ }
+
+ @Override
+ public String get()
+ {
+ return buffer.toString() ;
+ }
+
+ @Override
+ public void start()
+ {
+ // Resets on each use.
+ buffer = new StringBuilder() ;
+ first = true ;
+ }
+
+ @Override
+ public void finish() {}
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/Accumulate.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/Accumulate.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/Accumulate.java
new file mode 100644
index 0000000..2eef4fa
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/Accumulate.java
@@ -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.iterator;
+
+public interface Accumulate <T, R>
+{
+ public void start() ;
+ public void accumulate(T item) ;
+ public void finish();
+ public R get() ;
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/Action.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/Action.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/Action.java
new file mode 100644
index 0000000..de2630e
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/Action.java
@@ -0,0 +1,24 @@
+/*
+ * 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.iterator;
+
+public interface Action<T>
+{
+ public void apply(T item) ;
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/ActionCount.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/ActionCount.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/ActionCount.java
new file mode 100644
index 0000000..20f837c
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/ActionCount.java
@@ -0,0 +1,31 @@
+/*
+ * 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.iterator;
+
+
+public class ActionCount<T> implements Action<T>
+{
+ private long count = 0 ;
+
+ @Override
+ public void apply(T item)
+ { count++ ; }
+
+ public long getCount() { return count ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/ActionNothing.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/ActionNothing.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/ActionNothing.java
new file mode 100644
index 0000000..d05b279
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/ActionNothing.java
@@ -0,0 +1,26 @@
+/*
+ * 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.iterator;
+
+
+public class ActionNothing<T> implements Action<T>
+{
+ @Override
+ public void apply(T item) { }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/Filter.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/Filter.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/Filter.java
new file mode 100644
index 0000000..5d427c5
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/Filter.java
@@ -0,0 +1,22 @@
+/*
+ * 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.iterator;
+
+@FunctionalInterface
+public interface Filter <T> { boolean accept(T item) ; }
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/FilterDistinctAdjacent.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/FilterDistinctAdjacent.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/FilterDistinctAdjacent.java
new file mode 100644
index 0000000..3beb832
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/FilterDistinctAdjacent.java
@@ -0,0 +1,40 @@
+/*
+ * 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.iterator;
+
+import org.apache.jena.atlas.lib.Lib ;
+
+public class FilterDistinctAdjacent<T> implements Filter<T>
+{
+ private boolean isSet = false ;
+ private T last = null ;
+
+ public FilterDistinctAdjacent() { }
+
+ @Override
+ public boolean accept(T item)
+ {
+ if ( isSet && Lib.equal(last, item) )
+ return false ;
+ last = item ;
+ isSet = true ;
+ return true ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/FilterOutNulls.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/FilterOutNulls.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/FilterOutNulls.java
new file mode 100644
index 0000000..21cd471
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/FilterOutNulls.java
@@ -0,0 +1,32 @@
+/*
+ * 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.iterator;
+
+
+public class FilterOutNulls<T> implements Filter<T>
+{
+ public FilterOutNulls() { }
+
+ @Override
+ public boolean accept(T item)
+ {
+ return item != null ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/FilterStack.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/FilterStack.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/FilterStack.java
new file mode 100644
index 0000000..479d93f
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/FilterStack.java
@@ -0,0 +1,67 @@
+/*
+ * 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.iterator;
+
+/**
+ * Add a filter to a chain - the original filter is called after this new sub-filter.
+ */
+public abstract class FilterStack<T> implements Filter<T>
+{
+ private final Filter<T> other ;
+ private final boolean subFilterLast ;
+
+ public FilterStack(Filter<T> other) { this(other, false) ; }
+
+ public FilterStack(Filter<T> other, boolean callOldFilterFirst)
+ {
+ this.other = other ;
+ this.subFilterLast = callOldFilterFirst ;
+ }
+
+ @Override
+ public final boolean accept(T item)
+ {
+ if ( subFilterLast )
+ return acceptAdditionaOther(item) ;
+ else
+ return acceptOtherAdditional(item) ;
+ }
+
+ private boolean acceptAdditionaOther(T item)
+ {
+ if ( ! acceptAdditional(item) )
+ return false ;
+
+ if ( other != null && ! other.accept(item) )
+ return false ;
+
+ return true ;
+ }
+
+ private boolean acceptOtherAdditional(T item)
+ {
+ if ( other != null && ! other.accept(item) )
+ return false ;
+ return acceptAdditional(item) ;
+ }
+
+
+ /** Additional filter condition to apply */
+ public abstract boolean acceptAdditional(T item) ;
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/FilterUnique.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/FilterUnique.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/FilterUnique.java
new file mode 100644
index 0000000..2b2a957
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/FilterUnique.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.atlas.iterator;
+
+import java.util.HashSet ;
+import java.util.Set ;
+
+public class FilterUnique<T> implements Filter<T>
+{
+ private Set<T> seen = new HashSet<>() ;
+
+ public FilterUnique() { }
+
+ @Override
+ public boolean accept(T item)
+ {
+ if ( seen.contains(item) )
+ return false ;
+ seen.add(item) ;
+ return true ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/Iter.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/Iter.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/Iter.java
new file mode 100644
index 0000000..8aec2ea
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/Iter.java
@@ -0,0 +1,971 @@
+/*
+ * 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.iterator ;
+
+import java.io.PrintStream ;
+import java.util.* ;
+import java.util.stream.Stream ;
+import java.util.stream.StreamSupport ;
+
+import org.apache.jena.atlas.lib.ActionKeyValue ;
+import org.apache.jena.atlas.lib.Closeable ;
+import org.apache.jena.atlas.lib.Sink ;
+
+public class Iter<T> implements Iterator<T> {
+
+ // Most Iterable<T> operations have been removed - use streams instad.
+
+ public static <T> Stream<T> asStream(Iterator<T> iterator) {
+ // Why isn't there a JDK operation for iterator -> (sequential) stream?
+ return asStream(iterator, false);
+ }
+
+ public static <T> Stream<T> asStream(Iterator<T> iterator, boolean parallel) {
+ // Why isn't there a JDK operation for iterator -> (sequential) stream?
+ Iterable<T> iterable = () -> iterator;
+ return StreamSupport.stream(iterable.spliterator(), parallel);
+ }
+
+ // First part : the static function library.
+ // Often with both Iterator<? extends T> and Iterable<? extends T>
+
+ public static <T> Iterator<T> singleton(T item) {
+ return new SingletonIterator<>(item) ;
+ }
+
+ @SuppressWarnings("rawtypes")
+ private static final Iterator iter0 = new NullIterator() ;
+ @SuppressWarnings({"unchecked", "cast"})
+ public static <T> Iterator<T> nullIterator() { return (NullIterator<T>)iter0 ; }
+
+// public static <T> Iterator<T> nullIterator() {
+// return new NullIterator<T>() ;
+// }
+
+// public static <T> Set<T> toSet(Iterable<? extends T> stream) {
+// return toSet(stream.iterator()) ;
+// }
+
+ public static <T> Set<T> toSet(Iterator<? extends T> stream) {
+ Accumulate<T, Set<T>> action = new Accumulate<T, Set<T>>() {
+ private Set<T> acc = null ;
+
+ @Override
+ public void accumulate(T item) {
+ acc.add(item) ;
+ }
+
+ @Override
+ public Set<T> get() {
+ return acc ;
+ }
+
+ @Override
+ public void start() {
+ acc = new HashSet<>() ;
+ }
+
+ @Override
+ public void finish() {}
+ } ;
+ return reduce(stream, action) ;
+ }
+
+// public static <T> List<T> toList(Iterable<? extends T> stream) {
+// return toList(stream.iterator()) ;
+// }
+
+ public static <T> List<T> toList(Iterator<? extends T> stream) {
+ Accumulate<T, List<T>> action = new Accumulate<T, List<T>>() {
+ private List<T> acc = null ;
+
+ @Override
+ public void accumulate(T item) {
+ acc.add(item) ;
+ }
+
+ @Override
+ public List<T> get() {
+ return acc ;
+ }
+
+ @Override
+ public void start() {
+ acc = new ArrayList<>() ;
+ }
+
+ @Override
+ public void finish() {}
+ } ;
+ return reduce(stream, action) ;
+ }
+
+ /**
+ * Create another iterator without risk of concurrent modification
+ * exceptions. This materializes the input iterator.
+ */
+ public static <T> Iterator<T> iterator(Iterator<? extends T> iterator) {
+ List<T> x = Iter.toList(iterator) ;
+ return x.iterator() ;
+ }
+
+ public interface Folder<X, Y> {
+ Y eval(Y acc, X arg) ;
+ }
+
+ public static <T, R> R foldLeft(Iterable<? extends T> stream, Folder<T, R> function, R value) {
+ return foldLeft(stream.iterator(), function, value) ;
+ }
+
+ public static <T, R> R foldLeft(Iterator<? extends T> stream, Folder<T, R> function, R value) {
+ // Tail recursion, unwound
+ for (; stream.hasNext();) {
+ T item = stream.next() ;
+ value = function.eval(value, item) ;
+ }
+ return value ;
+ }
+
+ public static <T, R> R foldRight(Iterable<? extends T> stream, Folder<T, R> function, R value) {
+ return foldRight(stream.iterator(), function, value) ;
+ }
+
+ public static <T, R> R foldRight(Iterator<? extends T> stream, Folder<T, R> function, R value) {
+ // Recursive.
+ if ( !stream.hasNext() )
+ return value ;
+ T item = stream.next() ;
+ return function.eval(foldRight(stream, function, value), item) ;
+ }
+
+ // Note fold-left and fold-right
+ // http://en.wikipedia.org/wiki/Fold_%28higher-order_function%29
+
+ // This reduce is fold-left (take first element, apply to rest of list)
+ // which copes with infinite lists.
+ // Fold-left starts by combining the first element, then moves on.
+
+ public static <T, R> R reduce(Iterable<? extends T> stream, Accumulate<T, R> aggregator) {
+ return reduce(stream.iterator(), aggregator) ;
+ }
+
+ public static <T, R> R reduce(Iterator<? extends T> stream, Accumulate<T, R> aggregator) {
+ aggregator.start() ;
+ for (; stream.hasNext();) {
+ T item = stream.next() ;
+ aggregator.accumulate(item) ;
+ }
+ aggregator.finish() ;
+ return aggregator.get() ;
+ }
+
+ // map without the results - do immediately.
+ // Also, apply with call in between?
+
+// public static <T> void apply(Iterable<? extends T> stream, Action<T> action) {
+// apply(stream.iterator(), action) ;
+// }
+
+ public static <T> void apply(Iterator<? extends T> stream, Action<T> action) {
+ for (; stream.hasNext();) {
+ T item = stream.next() ;
+ action.apply(item) ;
+ }
+ }
+
+ // -- Map specific apply. No results - do immediately.
+
+ public static <K, V> void apply(Map<K, V> map, ActionKeyValue<K, V> action) {
+ for (Map.Entry<K, V> entry : map.entrySet())
+ action.apply(entry.getKey(), entry.getValue()) ;
+ }
+
+ // ---- Filter
+
+// public static <T> Iterator<T> filter(Iterable<? extends T> stream, Filter<T> filter) {
+// return filter(stream.iterator(), filter) ;
+// }
+
+ public static <T> Iterator<T> filter(final Iterator<? extends T> stream, final Filter<T> filter) {
+ final Iterator<T> iter = new Iterator<T>() {
+
+ boolean finished = false ;
+ boolean slotOccupied = false ;
+ T slot ;
+
+ @Override
+ public boolean hasNext() {
+ if ( finished )
+ return false ;
+ while (!slotOccupied) {
+ if ( !stream.hasNext() ) {
+ finished = true ;
+ break ;
+ }
+ T nextItem = stream.next() ;
+ if ( filter.accept(nextItem) ) {
+ slot = nextItem ;
+ slotOccupied = true ;
+ break ;
+ }
+ }
+ return slotOccupied ;
+ }
+
+ @Override
+ public T next() {
+ if ( hasNext() ) {
+ slotOccupied = false ;
+ return slot ;
+ }
+ throw new NoSuchElementException("filter.next") ;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("filter.remove") ;
+ }
+ } ;
+
+ return iter ;
+ }
+
+ private static class InvertedFilter<T> implements Filter<T> {
+ public static <T> Filter<T> invert(Filter<T> filter) {
+ return new InvertedFilter<>(filter) ;
+ }
+ private Filter<T> baseFilter ;
+
+ private InvertedFilter(Filter<T> baseFilter) {
+ this.baseFilter = baseFilter ;
+ }
+
+ @Override
+ public boolean accept(T item) {
+ return !baseFilter.accept(item) ;
+ }
+ }
+
+// public static <T> Iterator<T> notFilter(Iterable<? extends T> stream, Filter<T> filter) {
+// return notFilter(stream.iterator(), filter) ;
+// }
+
+ public static <T> Iterator<T> notFilter(final Iterator<? extends T> stream, final Filter<T> filter) {
+ Filter<T> flippedFilter = InvertedFilter.invert(filter) ;
+ return filter(stream, flippedFilter) ;
+ }
+
+ // Filter-related
+
+// /**
+// * Return true if every element of stream passes the filter (reads the
+// * stream)
+// */
+// public static <T> boolean every(Iterable<? extends T> stream, Filter<T> filter) {
+// for (T item : stream)
+// if ( !filter.accept(item) )
+// return false ;
+// return true ;
+// }
+
+ /**
+ * Return true if every element of stream passes the filter (reads the
+ * stream until the first element not passing the filter)
+ */
+ public static <T> boolean every(Iterator<? extends T> stream, Filter<T> filter) {
+ for (; stream.hasNext();) {
+ T item = stream.next() ;
+ if ( !filter.accept(item) )
+ return false ;
+ }
+ return true ;
+ }
+
+// /**
+// * Return true if every element of stream passes the filter (reads the
+// * stream until the first element passing the filter)
+// */
+// public static <T> boolean some(Iterable<? extends T> stream, Filter<T> filter) {
+// for (T item : stream)
+// if ( filter.accept(item) )
+// return true ;
+// return false ;
+// }
+
+ /**
+ * Return true if one or more elements of stream passes the filter (reads
+ * the stream to first element passing the filter)
+ */
+ public static <T> boolean some(Iterator<? extends T> stream, Filter<T> filter) {
+ for (; stream.hasNext();) {
+ T item = stream.next() ;
+ if ( filter.accept(item) )
+ return true ;
+ }
+ return false ;
+ }
+
+ // ---- Map
+
+// public static <T, R> Iterator<R> map(Iterable<? extends T> stream, Transform<T, R> converter) {
+// return map(stream.iterator(), converter) ;
+// }
+
+ public static <T, R> Iterator<R> map(final Iterator<? extends T> stream, final Transform<T, R> converter) {
+ final Iterator<R> iter = new Iterator<R>() {
+ @Override
+ public boolean hasNext() {
+ return stream.hasNext() ;
+ }
+
+ @Override
+ public R next() {
+ return converter.convert(stream.next()) ;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("map.remove") ;
+ }
+ } ;
+ return iter ;
+ }
+
+ public static <T, R> List<R> map(List<? extends T> list, Transform<T, R> converter) {
+ return toList(map(list.iterator(), converter)) ;
+ }
+
+ /**
+ * Projects each element of a sequence to an Iterator<R> and flattens
+ * the resulting sequences into one sequence.
+ */
+ public static <T, R> Iterator<R> mapMany(final Iterator<? extends T> stream,
+ final Transform<? super T, Iterator<R>> converter) {
+ final Iterator<R> iter = new Iterator<R>() {
+
+ private Iterator<? extends R> it = null ; // Iterator for the
+ // current element of
+ // stream.
+
+ @Override
+ public boolean hasNext() {
+ if ( it != null && it.hasNext() )
+ // Element of the current iterator.
+ return true ;
+ // Start or current iterator has ended.
+ it = null ;
+
+ // Need to move to next non-empty iterator of the stream.
+ while (stream.hasNext()) {
+ it = converter.convert(stream.next()) ;
+ if ( it.hasNext() )
+ // There is something.
+ return true ;
+ }
+ it = null ;
+ // Stream ran out.
+ return false ;
+ }
+
+ @Override
+ public R next() {
+ if ( !hasNext() )
+ throw new NoSuchElementException() ;
+ // "it" is always left with something to yield if hashNext is
+ // true.
+ return it.next() ;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("mapMany.remove") ;
+ }
+ } ;
+
+ return iter ;
+ }
+
+// public static <T, R> Iterator<R> mapMany(Iterable<? extends T> stream, Transform<T, Iterator<R>> converter) {
+// return mapMany(stream.iterator(), converter) ;
+// }
+
+ public static <T, R> List<R> mapMany(List<? extends T> list, Transform<T, Iterator<R>> converter) {
+ return toList(mapMany(list.iterator(), converter)) ;
+ }
+
+// /**
+// * Apply an action to everything in stream, yielding a stream of the same
+// * items
+// */
+// public static <T> Iterator<T> operate(Iterable<? extends T> stream, Action<T> converter) {
+// return operate(stream.iterator(), converter) ;
+// }
+
+ /**
+ * Apply an action to everything in stream, yielding a stream of the same
+ * items
+ */
+ public static <T> Iterator<T> operate(final Iterator<? extends T> stream, final Action<T> action) {
+ final Iterator<T> iter = new Iterator<T>() {
+ @Override
+ public boolean hasNext() {
+ return stream.hasNext() ;
+ }
+
+ @Override
+ public T next() {
+ T t = stream.next() ;
+ action.apply(t) ;
+ return t ;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("operate.remove") ;
+ }
+ } ;
+ return iter ;
+ }
+
+ /** Print an iterator as it gets used - this adds a printing wrapper */
+ public static <T> Iterator<T> printWrapper(final Iterator<? extends T> stream) {
+ return Iter.printWrapper(System.out, stream) ;
+ }
+
+ /** Print an iterator as it gets used - this adds a printing wrapper */
+ public static <T> Iterator<T> printWrapper(final PrintStream out, final Iterator<? extends T> stream) {
+ Action<T> action = new Action<T>() {
+ @Override
+ public void apply(T item) {
+ out.println(item) ;
+ }
+ } ;
+ return Iter.operate(stream, action) ;
+ }
+
+// /** Join two iteratables
+// * If there, potentially, going to be many iterators, it is better to
+// * create an {@link IteratorConcat} explicitly and add each iterator.
+// */
+// public static <T> Iterator<T> append(Iterable<? extends T> iter1, Iterable<? extends T> iter2) {
+// return IteratorCons.create(iterator(iter1), iterator(iter2)) ;
+// }
+
+ /** Join two iterator
+ * If there, potentially, going to be many iterators, it is better to
+ * create an {@link IteratorConcat} explicitly and add each iterator.
+ */
+ public static <T> Iterator<T> append(Iterator<? extends T> iter1, Iterator<? extends T> iter2) {
+ return IteratorCons.create(iter1, iter2) ;
+ }
+
+// private static <T> Iterator<T> iterator(Iterable<T> iter) {
+// return (iter == null) ? null : iter.iterator() ;
+// }
+
+// public static <T> Iterator<T> distinct(Iterable<T> iter) {
+// return distinct(iter.iterator()) ;
+// }
+
+ public static <T> Iterator<T> distinct(Iterator<T> iter) {
+ return filter(iter, new FilterUnique<T>()) ;
+ }
+
+// /** Remove adjacent duplicates */
+// public static <T> Iterator<T> distinctAdjacent(Iterable<T> iter) {
+// return distinctAdjacent(iter.iterator()) ;
+// }
+
+ /** Remove adjacent duplicates */
+ public static <T> Iterator<T> distinctAdjacent(Iterator<T> iter) {
+ return filter(iter, new FilterDistinctAdjacent<T>()) ;
+ }
+
+// public static <T> Iterator<T> removeNulls(Iterable<T> iter) {
+// return filter(iter, new FilterOutNulls<T>()) ;
+// }
+
+ public static <T> Iterator<T> removeNulls(Iterator<T> iter) {
+ return filter(iter, new FilterOutNulls<T>()) ;
+ }
+
+ /** Take the first N elements of an iterator - stop early if too few */
+ public static <T> List<T> take(Iterator<T> iter, int N) {
+ iter = new IteratorN<>(iter, N) ;
+ List<T> x = new ArrayList<>(N) ;
+ for (; iter.hasNext();)
+ x.add(iter.next()) ;
+ return x ;
+ }
+
+ /** Iterator that only returns upto N items */
+ static class IteratorN<T> implements Iterator<T> {
+ private final Iterator<T> iter ;
+ private final int N ;
+ private int count ;
+
+ IteratorN(Iterator<T> iter, int N) {
+ this.iter = iter ;
+ this.N = N ;
+ this.count = 0 ;
+ }
+
+ @Override
+ public boolean hasNext() {
+ if ( count >= N )
+ return false ;
+ return iter.hasNext() ;
+ }
+
+ @Override
+ public T next() {
+ if ( count >= N )
+ throw new NoSuchElementException() ;
+ T x = iter.next() ;
+ count++ ;
+ return x ;
+ }
+
+ @Override
+ public void remove() {
+ // But leave the count as-is.
+ iter.remove() ;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <T> Iterator<T> convert(Iterator<? > iterator) {
+ return (Iterator<T>)iterator ;
+ }
+
+// /**
+// * Count the iterable - many iterable objects have a .size() operation which
+// * should be used in preference to this explicit counting operation
+// */
+// public static <T> long count(Iterable<T> iterable) {
+// return count(iterable.iterator()) ;
+// }
+
+ /** Count the iterator (this is destructive on the iterator) */
+ public static <T> long count(Iterator<T> iterator) {
+ long x = 0 ;
+ while (iterator.hasNext()) {
+ iterator.next() ;
+ x++ ;
+ }
+ return x ;
+ // ActionCount<T> action = new ActionCount<T>() ;
+ // Iter.apply(iterator, action) ;
+ // return action.getCount() ;
+ }
+
+// // --- Consume the iterator.
+// /** Consume the iterable */
+// public static <T> void consume(Iterable<T> iterator) {
+// count(iterator) ;
+// }
+
+ /** Consume the iterator */
+ public static <T> void consume(Iterator<T> iterator) {
+ count(iterator) ;
+ }
+
+ // ---- String related helpers
+
+ public static <T> String asString(Iterable<T> stream) {
+ return asString(stream, new AccString<T>()) ;
+ }
+
+ public static <T> String asString(Iterator<T> stream) {
+ return asString(stream, new AccString<T>()) ;
+ }
+
+// public static <T> String asString(Iter<T> stream) {
+// return asString(stream, new AccString<T>()) ;
+// }
+//
+
+ public static <T> String asString(Iterable<T> stream, String sep) {
+ return asString(stream, new AccString<T>(sep)) ;
+ }
+
+ public static <T> String asString(Iterator<T> stream, String sep) {
+ return asString(stream, new AccString<T>(sep)) ;
+ }
+
+// public static <T> String asString(Iter<T> stream, String sep) {
+// return asString(stream.iterator(), new AccString<T>(sep)) ;
+// }
+//
+ public static <T> String asString(Iterable<T> stream, AccString<T> formatter) {
+ return asString(stream.iterator(), formatter) ;
+ }
+
+ public static <T> String asString(Iterator<T> stream, AccString<T> formatter) {
+ return reduce(stream, formatter) ;
+ }
+
+// public static <T> String asString(Iter<T> stream, AccString<T> formatter) {
+// return reduce(stream.iterator(), formatter) ;
+// }
+
+ // ----
+
+ public static <T> void close(Iterator<T> iter) {
+ if ( iter instanceof Closeable )
+ ((Closeable)iter).close() ;
+ }
+
+
+ /**
+ * Print an iterator to stdout, return a copy of the iterator. Printing
+ * occurs now. See {@link #debug} for an operation to print as the
+ * iterator is used.
+ */
+ public static <T> Iterator<T> log(Iterator<T> stream) {
+ return log(System.out, stream) ;
+ }
+
+ /**
+ * Print an iterator to stdout, return a copy of the iterator. Printing
+ * occurs when the returned iterator is used
+ */
+ public static <T> Iterator<T> log(final PrintStream out, Iterator<T> stream) {
+ Iterator<T> iter = debug(out, stream) ;
+ // And force it to run.
+ return Iter.toList(iter).iterator();
+ }
+
+ /**
+ * Print an iterator to stdout, return a copy of the iterator. Printing
+ * occurs when the iterator is used. See {@link #log} for
+ * an operation to print now.
+ */
+ public static <T> Iterator<T> debug(Iterator<T> stream) {
+ return debug(System.out, stream) ;
+ }
+
+ /**
+ * Print an iterator to stdout, return a copy of the iterator. Printing
+ * occurs when the returned iterator is used
+ */
+ public static <T> Iterator<T> debug(final PrintStream out, Iterator<T> stream) {
+ try {
+ Transform<T, T> x = new Transform<T, T>() {
+ @Override
+ public T convert(T item) {
+ out.println(item) ;
+ return item ;
+ }
+ } ;
+ return map(stream, x) ;
+ } finally { out.flush() ; }
+ }
+
+ /** Print an iterator (destructive) */
+ public static <T> void print(Iterator<T> stream) {
+ print(System.out, stream) ;
+ }
+
+ /** Print an iterator (destructive) */
+ public static <T> void print(final PrintStream out, Iterator<T> stream) {
+ Action<T> x = new Action<T>() {
+ @Override
+ public void apply(T item) {
+ out.println(item) ;
+ }
+
+ } ;
+ apply(stream, x) ;
+ }
+
+// /** Print an iterable */
+// public static <T> void print(PrintStream out, Iterable<T> iterable) {
+// print(out, iterable.iterator()) ;
+// }
+//
+// /** Print an iterable */
+// public static <T> void print(Iterable<T> iterable) {
+// print(iterable.iterator()) ;
+// }
+
+ /** Send the elements of the iterator to a sink - consumes the iterator */
+ public static <T> void sendToSink(Iterator<T> iter, Sink<T> sink) {
+ for (; iter.hasNext();) {
+ T thing = iter.next() ;
+ sink.send(thing) ;
+ }
+ sink.close() ;
+ }
+
+ /** Send the elements of the iterable to a sink */
+ public static <T> void sendToSink(Iterable<T> stream, Sink<T> sink) {
+ sendToSink(stream.iterator(), sink) ;
+ }
+
+ // ----
+ // Iter class part : factories
+
+ public static <T> Iter<T> iter(Iter<T> iter) {
+ return iter ;
+ }
+
+ // May not do what you expect. iter(int[]) is iter of one object (an int[])
+ // public static <T> Iter<T> iter(T...objects)
+ // { return Iter.iter(Arrays.asList(objects)) ; }
+
+ public static <T> Iter<T> iterSingleton(T x) {
+ return Iter.iter(SingletonIterator.create(x)) ;
+ }
+
+ public static <T> Iter<T> iter(Collection<T> collection) {
+ return Iter.iter(collection.iterator()) ;
+ }
+
+ public static <T> Iter<T> iter(Iterator<T> iterator) {
+ if ( iterator instanceof Iter<? > )
+ return (Iter<T>)iterator ;
+ return new Iter<>(iterator) ;
+ }
+
+// public static <T> Iter<T> iter(Iterable<T> iterable) {
+// if ( iterable instanceof Iter<? > )
+// return (Iter<T>)iterable ;
+// return new Iter<>(iterable.iterator()) ;
+// }
+
+ public static <T> Iter<T> singletonIter(T item) {
+ return iter(new SingletonIterator<>(item)) ;
+ }
+
+ public static <T> Iter<T> nullIter() {
+ return iter(new NullIterator<T>()) ;
+ }
+
+ /**
+ * Materialize an iterator, that is, force it to run now - useful in
+ * debugging
+ */
+ public static <T> Iterator<T> materialize(Iterator<T> iter) {
+ return Iter.toList(iter).iterator() ;
+ }
+
+ public static <T> Iter<T> concat(Iter<T> iter1, Iter<T> iter2) {
+ if ( iter1 == null )
+ return iter2 ;
+ if ( iter2 == null )
+ return iter1 ;
+ return iter1.append(iter2) ;
+ }
+
+ public static <T> Iterator<T> concat(Iterator<T> iter1, Iterator<T> iter2) {
+ if ( iter1 == null )
+ return iter2 ;
+ if ( iter2 == null )
+ return iter1 ;
+ return Iter.iter(iter1).append(Iter.iter(iter2)) ;
+ }
+
+ public static <T> T first(Iterator<T> iter, Filter<T> filter) {
+ for (int idx = 0; iter.hasNext(); idx++) {
+ T t = iter.next() ;
+ if ( filter.accept(t) )
+ return t ;
+ // return idx ;
+ }
+ return null ;
+ }
+
+ public static <T> T first(Collection<T> collection, Filter<T> filter) {
+ return first(collection.iterator(), filter) ;
+ }
+
+ public static <T> int firstIndex(Iterator<T> iter, Filter<T> filter) {
+ for (int idx = 0; iter.hasNext(); idx++) {
+ T t = iter.next() ;
+ if ( filter.accept(t) )
+ return idx ;
+ }
+ return -1 ;
+ }
+
+ public static <T> int firstIndex(Collection<T> collection, Filter<T> filter) {
+ return firstIndex(collection.iterator(), filter) ;
+ }
+
+ public static <T> T last(Iterator<T> iter, Filter<T> filter) {
+ T thing = null ;
+ for (int idx = 0; iter.hasNext(); idx++) {
+ T t = iter.next() ;
+ if ( filter.accept(t) )
+ thing = t ;
+ }
+ return thing ;
+ }
+
+ public static <T> T last(Collection<T> collection, Filter<T> filter) {
+ return last(collection.iterator(), filter) ;
+ }
+
+ public static <T> int lastIndex(Iterator<T> iter, Filter<T> filter) {
+ int location = -1 ;
+ for (int idx = 0; iter.hasNext(); idx++) {
+ T t = iter.next() ;
+ if ( filter.accept(t) )
+ location = idx ;
+ }
+ return location ;
+ }
+
+ public static <T> int lastIndex(Collection<T> collection, Filter<T> filter) {
+ return lastIndex(collection.iterator(), filter) ;
+ }
+
+ // ------------------------------------------------------
+ // The class.
+
+ private Iterator<T> iterator ;
+
+ private Iter(Iterator<T> iterator) {
+ this.iterator = iterator ;
+ }
+
+ public Set<T> toSet() {
+ return toSet(iterator) ;
+ }
+
+ public List<T> toList() {
+ return toList(iterator) ;
+ }
+
+ public void sendToSink(Sink<T> sink) {
+ sendToSink(iterator, sink) ;
+ }
+
+ public T first(Filter<T> filter) {
+ return first(iterator, filter) ;
+ }
+
+ public int firstIndex(Filter<T> filter) {
+ return firstIndex(iterator, filter) ;
+ }
+
+ public T last(Filter<T> filter) {
+ return last(iterator, filter) ;
+ }
+
+ public int lastIndex(Filter<T> filter) {
+ return lastIndex(iterator, filter) ;
+ }
+
+ public Iter<T> filter(Filter<T> filter) {
+ return iter(filter(iterator, filter)) ;
+ }
+
+ public boolean every(Filter<T> filter) {
+ return every(iterator, filter) ;
+ }
+
+ public boolean some(Filter<T> filter) {
+ return some(iterator, filter) ;
+ }
+
+ public Iter<T> removeNulls() {
+ return filter(new FilterOutNulls<T>()) ;
+ }
+
+ public <R> Iter<R> map(Transform<T, R> converter) {
+ return iter(map(iterator, converter)) ;
+ }
+
+ /**
+ * Apply an action to everything in the stream, yielding a stream of the
+ * same items
+ */
+ public Iter<T> operate(Action<T> action) {
+ return iter(operate(iterator, action)) ;
+ }
+
+ public <R> R reduce(Accumulate<T, R> aggregator) {
+ return reduce(iterator, aggregator) ;
+ }
+
+ public void apply(Action<T> action) {
+ apply(iterator, action) ;
+ }
+
+ /** Join on an iterator.
+ * If there are going to be many iterators, uit is better to create an {@link IteratorConcat}
+ * and <tt>.add</tt> each iterator. The overheads are much lower.
+ */
+ public Iter<T> append(Iterator<T> iter) {
+ return iter(IteratorCons.create(iterator, iter)) ;
+ }
+
+ /** Return an Iter that yields at most the first N items */
+ public Iter<T> take(int N) {
+ return Iter.iter(take(iterator, N)) ;
+ }
+
+ /** Count the iterator (this is destructive on the iterator) */
+ public long count() {
+ ActionCount<T> action = new ActionCount<>() ;
+ apply(action) ;
+ return action.getCount() ;
+ }
+
+ public String asString() {
+ return asString(iterator) ;
+ }
+
+ public String asString(String sep) {
+ return asString(iterator, sep) ;
+ }
+
+ public Iter<T> distinct() {
+ return iter((distinct(iterator()))) ;
+ }
+
+ public Iter<T> distinctAdjacent() {
+ return iter(distinctAdjacent(iterator())) ;
+ }
+
+ // ---- Iterable
+// @Override
+ public Iterator<T> iterator() {
+ return iterator ;
+ }
+
+ // ---- Iterator
+
+ @Override
+ public boolean hasNext() {
+ return iterator.hasNext() ;
+ }
+
+ @Override
+ public T next() {
+ return iterator.next() ;
+ }
+
+ @Override
+ public void remove() {
+ iterator.remove() ;
+ }
+}
[4/9] jena git commit: Import of lib, io,
logging and iterator packages
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/SetUtils.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/SetUtils.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/SetUtils.java
new file mode 100644
index 0000000..f4e561d
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/SetUtils.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.atlas.lib;
+
+import java.util.HashSet ;
+import java.util.Set ;
+
+public class SetUtils
+{
+ private SetUtils() {}
+
+ public static <X> Set<X> setOfOne(X element) { return DS.setOfOne(element) ; }
+
+ // Set specific operations
+
+ public static <T> Set<T> intersection(Set<? extends T> setLeft, Set<? extends T> setRight)
+ {
+ Set<T> results = new HashSet<>(setLeft) ;
+ results.retainAll(setRight) ;
+ return results ;
+ }
+
+ public static <T> boolean intersectionP(Set<? extends T> s1, Set<? extends T> s2)
+ {
+ for( T elt : s1 )
+ {
+ if ( s2.contains(elt) )
+ return true ;
+ }
+ return false ;
+ }
+
+ public static <T> Set<T> union(Set<? extends T> s1, Set<? extends T> s2)
+ {
+ Set<T> s3 = new HashSet<>(s1) ;
+ s3.addAll(s2) ;
+ return s3 ;
+ }
+
+ /** Return is s1 \ s2 */
+
+ public static <T> Set<T> difference(Set<? extends T> s1, Set<? extends T> s2)
+ {
+ Set<T> s3 = new HashSet<>(s1) ;
+ s3.removeAll(s2) ;
+ return s3 ;
+ }
+
+ /** Return true if s1 and s2 are disjoint */
+ public static <T> boolean isDisjoint(Set<? extends T> s1, Set<? extends T> s2)
+ {
+ Set<? extends T> x = s1 ;
+ Set<? extends T> y = s2 ;
+ if ( s1.size() < s2.size() )
+ {
+ x = s2 ;
+ y = s1 ;
+ }
+
+ for ( T item : x )
+ {
+ if ( y.contains(item))
+ return false ;
+ }
+ return true ;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Sink.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Sink.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Sink.java
new file mode 100644
index 0000000..01bb809
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Sink.java
@@ -0,0 +1,29 @@
+/*
+ * 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.lib;
+
+
+/** Interface for the destination of things */
+public interface Sink<T> extends Closeable
+{
+ // Can't help but think it should be "Pipe"
+ // If Sync looses Sync(boolean), then make this "extends Sync"
+ void send(T item) ;
+ void flush() ;
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkCounting.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkCounting.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkCounting.java
new file mode 100644
index 0000000..62c6e43
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkCounting.java
@@ -0,0 +1,41 @@
+/*
+ * 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.lib;
+
+
+
+public final class SinkCounting<T> extends SinkWrapper<T>
+{
+ private long count = 0 ;
+
+ public SinkCounting(Sink<T> output)
+ { super(output) ; }
+
+ public SinkCounting()
+ { super(new SinkNull<T>()) ; }
+
+ @Override
+ public void send(T thing)
+ {
+ count++ ;
+ super.send(thing) ;
+ }
+
+ public long getCount() { return count ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkLogging.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkLogging.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkLogging.java
new file mode 100644
index 0000000..e6928de
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkLogging.java
@@ -0,0 +1,41 @@
+/*
+ * 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.lib;
+
+import org.slf4j.Logger ;
+
+public class SinkLogging<T> implements Sink<T>
+{
+ private Logger log ;
+
+ public SinkLogging(Logger log) { this.log = log ; }
+
+ @Override
+ public void send(T item)
+ {
+ log.info("Sink: "+item) ;
+ }
+
+ @Override
+ public void flush() { }
+
+ @Override
+ public void close() {}
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkNull.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkNull.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkNull.java
new file mode 100644
index 0000000..9242c97
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkNull.java
@@ -0,0 +1,33 @@
+/*
+ * 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.lib;
+
+
+
+public class SinkNull<T> implements Sink<T>
+{
+ public static <X> SinkNull<X> create() { return new SinkNull<>() ; }
+
+ /*@Override*/ @Override
+ public void send(T thing) {}
+ /*@Override*/ @Override
+ public void close() {}
+ /*@Override*/ @Override
+ public void flush() { }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkPrint.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkPrint.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkPrint.java
new file mode 100644
index 0000000..4fc694d
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkPrint.java
@@ -0,0 +1,45 @@
+/*
+ * 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.lib;
+
+import java.io.PrintStream ;
+
+public class SinkPrint<T> implements Sink<T>
+{
+
+ private PrintStream out ;
+
+ public SinkPrint()
+ { this(System.out); }
+
+ public SinkPrint(PrintStream out)
+ { this.out = out ; }
+
+ @Override
+ public void send(T item)
+ {
+ out.println("Sink: "+item) ;
+ }
+
+ @Override
+ public void flush() { }
+
+ @Override
+ public void close() {}
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkSplit.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkSplit.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkSplit.java
new file mode 100644
index 0000000..8d50ee4
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkSplit.java
@@ -0,0 +1,55 @@
+/*
+ * 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.lib;
+
+/** Split a sink stream and duplicate the operations onto two sinks
+ * See also: {@link SinkWrapper}
+ */
+public class SinkSplit<T> implements Sink<T>
+{
+ private final Sink<T> sink1 ;
+ private final Sink<T> sink2 ;
+
+ public SinkSplit(Sink<T> sink1, Sink<T> sink2)
+ {
+ this.sink1 = sink1 ;
+ this.sink2 = sink2 ;
+ }
+
+ @Override
+ public void flush()
+ {
+ sink1.flush();
+ sink2.flush();
+ }
+
+ @Override
+ public void send(T item)
+ {
+ sink1.send(item) ;
+ sink2.send(item) ;
+ }
+
+ @Override
+ public void close()
+ {
+ sink1.close();
+ sink2.close();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkToCollection.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkToCollection.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkToCollection.java
new file mode 100644
index 0000000..d7e04ba
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkToCollection.java
@@ -0,0 +1,38 @@
+/**
+ * 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.lib;
+
+import java.util.Collection;
+
+/** Send items to a collection */
+public class SinkToCollection<T> implements Sink<T>
+{
+ private final Collection<T> c ;
+
+ public SinkToCollection(Collection<T> c) { this.c = c ; }
+
+ @Override
+ public void send(T item) { c.add(item); }
+
+ @Override
+ public void flush() {}
+
+ @Override
+ public void close() {}
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkToQueue.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkToQueue.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkToQueue.java
new file mode 100644
index 0000000..f7e5dff
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkToQueue.java
@@ -0,0 +1,52 @@
+/**
+ * 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.lib;
+
+import java.util.concurrent.BlockingQueue ;
+import java.util.concurrent.CancellationException ;
+
+/** Send items to a blocking queue */
+public class SinkToQueue<T> implements Sink<T>
+{
+ private final BlockingQueue<T> queue ;
+
+ public SinkToQueue(BlockingQueue<T> queue) { this.queue = queue ; }
+
+ @Override
+ public void send(T item)
+ {
+ try
+ {
+ if (Thread.interrupted()) throw new InterruptedException();
+ // Hopefully we'll never get passed null... but just in case
+ if (null == item) return;
+ queue.put(item);
+ }
+ catch (InterruptedException e)
+ {
+ throw new CancellationException();
+ }
+ }
+
+ @Override
+ public void flush() {}
+
+ @Override
+ public void close() {}
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkWrapper.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkWrapper.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkWrapper.java
new file mode 100644
index 0000000..c6632ba
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/SinkWrapper.java
@@ -0,0 +1,44 @@
+/*
+ * 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.lib;
+
+/** Wrap one sink in another - to pass on behaviour, the derived Sink must call super.operation
+ * See also: {@link SinkSplit}
+ */
+public class SinkWrapper<T> implements Sink<T>
+{
+ protected final Sink<T> sink ;
+
+ public SinkWrapper(Sink<T> sink)
+ {
+ this.sink = sink ;
+ }
+
+ @Override
+ public void flush()
+ { sink.flush(); }
+
+ @Override
+ public void send(T item)
+ { sink.send(item) ; }
+
+ @Override
+ public void close()
+ { sink.close(); }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/StrUtils.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/StrUtils.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/StrUtils.java
new file mode 100644
index 0000000..9a9be76
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/StrUtils.java
@@ -0,0 +1,292 @@
+/*
+ * 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.lib;
+
+import java.io.UnsupportedEncodingException ;
+import java.util.ArrayList ;
+import java.util.List ;
+import java.util.Map ;
+
+
+public class StrUtils //extends StringUtils
+{
+ private StrUtils() {}
+
+ /** strjoin with a newline as the separator */
+ public static String strjoinNL(String... args)
+ {
+ return join("\n", args) ;
+ }
+
+ /** strjoin with a newline as the separator */
+ public static String strjoinNL(List<String> args)
+ {
+ return join("\n", args) ;
+ }
+
+ /** Concatentate strings, using a separator */
+ public static String strjoin(String sep, String... args)
+ {
+ return join(sep, args) ;
+ }
+
+ /** Concatentate string, using a separator */
+ public static String strjoin(String sep, List<String> args)
+ {
+ return join(sep, args) ;
+ }
+
+ private static String join(String sep, List<String> a)
+ {
+ return join(sep, a.toArray(new String[0])) ;
+ }
+
+ private static String join(String sep, String...a)
+ {
+ if ( a.length == 0 )
+ return "" ;
+
+ if ( a.length == 1)
+ return a[0] ;
+
+ StringBuilder sbuff = new StringBuilder() ;
+ sbuff.append(a[0]) ;
+
+ for ( int i = 1 ; i < a.length ; i++ )
+ {
+ if ( sep != null )
+ sbuff.append(sep) ;
+ sbuff.append(a[i]) ;
+ }
+ return sbuff.toString() ;
+ }
+
+ public static final int CMP_GREATER = +1 ;
+ public static final int CMP_EQUAL = 0 ;
+ public static final int CMP_LESS = -1 ;
+
+ public static final int CMP_UNEQUAL = -9 ;
+ public static final int CMP_INDETERMINATE = 2 ;
+
+ public static int strCompare(String s1, String s2)
+ {
+ // Value is the difference of the first differing chars
+ int x = s1.compareTo(s2) ;
+ if ( x < 0 ) return CMP_LESS ;
+ if ( x > 0 ) return CMP_GREATER ;
+ if ( x == 0 ) return CMP_EQUAL ;
+ throw new InternalErrorException("String comparison failure") ;
+ }
+
+ public static int strCompareIgnoreCase(String s1, String s2)
+ {
+ // Value is the difference of the first differing chars
+ int x = s1.compareToIgnoreCase(s2) ;
+ if ( x < 0 ) return CMP_LESS ;
+ if ( x > 0 ) return CMP_GREATER ;
+ if ( x == 0 ) return CMP_EQUAL ;
+ throw new InternalErrorException("String comparison failure") ;
+ }
+
+ public static byte[] asUTF8bytes(String s)
+ {
+ try { return s.getBytes("UTF-8") ; }
+ catch (UnsupportedEncodingException ex)
+ { throw new InternalErrorException("UTF-8 not supported!") ; }
+ }
+
+ public static String fromUTF8bytes(byte[] bytes)
+ {
+ try { return new String(bytes, "UTF-8") ; }
+ catch (UnsupportedEncodingException ex)
+ { throw new InternalErrorException("UTF-8 not supported!") ; }
+ }
+
+ public static String str(Object x)
+ {
+ if ( x == null ) return "<null>" ;
+ return x.toString() ;
+ }
+
+ /** Split but also trim whiespace. */
+ public static String[] split(String s, String splitStr)
+ {
+ String[] x = s.split(splitStr) ;
+ for ( int i = 0 ; i < x.length ; i++ )
+ {
+ x[i] = x[i].trim() ;
+ }
+ return x ;
+ }
+
+ /** Does one string contain another string?
+ * @param str1
+ * @param str2
+ * @return true if str1 contains str2
+ */
+ public final static boolean contains(String str1, String str2)
+ {
+ return str1.contains(str2) ;
+ }
+
+ public final static String replace(String string, String target, String replacement)
+ {
+ return string.replace(target, replacement) ;
+ }
+
+ public static String substitute(String str, Map<String, String>subs)
+ {
+ for ( Map.Entry<String, String> e : subs.entrySet() )
+ {
+ String param = e.getKey() ;
+ if ( str.contains(param) )
+ str = str.replace(param, e.getValue()) ;
+ }
+ return str ;
+ }
+
+ public static String strform(Map<String, String>subs, String... args)
+ {
+ return substitute(strjoinNL(args),subs) ;
+ }
+
+ public static String chop(String x)
+ {
+ if ( x.length() == 0 )
+ return x ;
+ return x.substring(0, x.length()-1) ;
+ }
+
+ public static String noNewlineEnding(String x)
+ {
+ while ( x.endsWith("\n") || x.endsWith("\r") )
+ x = StrUtils.chop(x) ;
+ return x ;
+ }
+
+ public static List<Character> toCharList(String str)
+ {
+ List<Character> characters = new ArrayList<>(str.length()) ;
+ for ( Character ch : str.toCharArray() )
+ characters.add(ch) ;
+ return characters ;
+ }
+
+ // ==== Encoding and decoding strings based on a marker character (e.g. %)
+ // and then the hexadecimal representation of the character.
+ // Only characters 0-255 can be encoded.
+
+ /** Encode a string using hex values e.g. %20
+ *
+ * @param str String to encode
+ * @param marker Marker character
+ * @param escapees Characters to encode (must include the marker)
+ * @return Encoded string (returns input object if no change)
+ */
+ public static String encodeHex(String str, char marker, char[] escapees)
+ {
+ // We make a first pass to see if there is anything to do.
+ // This is assuming
+ // (1) the string is shortish (e.g. fits in L1)
+ // (2) necessary escaping is not common
+
+ int N = str.length();
+ int idx = 0 ;
+ // Scan stage.
+ for ( ; idx < N ; idx++ )
+ {
+ char ch = str.charAt(idx) ;
+ if ( Chars.charInArray(ch, escapees) )
+ break ;
+ }
+ if ( idx == N )
+ return str ;
+
+ // At least one char to convert
+ StringBuilder buff = new StringBuilder() ;
+ buff.append(str, 0, idx) ; // Insert first part.
+ for ( ; idx < N ; idx++ )
+ {
+ char ch = str.charAt(idx) ;
+ if ( Chars.charInArray(ch, escapees) )
+ {
+ Chars.encodeAsHex(buff, marker, ch) ;
+ continue ;
+ }
+ buff.append(ch) ;
+ }
+ return buff.toString();
+ }
+
+ /** Decode a string using marked hex values e.g. %20
+ *
+ * @param str String to decode
+ * @param marker The marker charcater
+ * @return Decoded string (returns input object on no change)
+ */
+ public static String decodeHex(String str, char marker)
+ {
+ int idx = str.indexOf(marker) ;
+ if ( idx == -1 )
+ return str ;
+ StringBuilder buff = new StringBuilder() ;
+
+ buff.append(str, 0, idx) ;
+ int N = str.length() ;
+
+ for ( ; idx < N ; idx++ )
+ {
+ char ch = str.charAt(idx) ;
+ // First time through this is true, always.
+ if ( ch != marker )
+ buff.append(ch) ;
+ else
+ {
+ char hi = str.charAt(idx+1) ;
+ char lo = str.charAt(idx+2) ; // exceptions.
+ char ch2 = (char)(hexDecode(hi)<<4 | hexDecode(lo)) ;
+ buff.append(ch2) ;
+ idx += 2 ;
+ }
+ }
+ return buff.toString() ;
+ }
+
+ // Encoding is table-driven but for decode, we use code.
+ static private int hexDecode(char ch) {
+ if (ch >= '0' && ch <= '9' )
+ return ch - '0' ;
+ if ( ch >= 'A' && ch <= 'F' )
+ return ch - 'A' + 10 ;
+ if ( ch >= 'a' && ch <= 'f' )
+ return ch - 'a' + 10 ;
+ return -1 ;
+ }
+
+ public static String escapeString(String x)
+ {
+ return EscapeStr.stringEsc(x) ;
+ }
+
+ public static String unescapeString(String x)
+ {
+ return EscapeStr.unescapeStr(x) ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Sync.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Sync.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Sync.java
new file mode 100644
index 0000000..c8e549b
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Sync.java
@@ -0,0 +1,24 @@
+/*
+ * 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.lib;
+
+public interface Sync
+{
+ public void sync() ;
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/SystemUtils.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/SystemUtils.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/SystemUtils.java
new file mode 100644
index 0000000..fa208f8
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/SystemUtils.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.atlas.lib;
+
+import org.apache.jena.atlas.AtlasException ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+public class SystemUtils
+{
+ private static Logger log = LoggerFactory.getLogger(SystemUtils.class.getName());
+ // Unfortunately, this tends to cause confusing logging.
+ private static boolean logging = false ;
+
+ static public ClassLoader chooseClassLoader()
+ {
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+
+ if ( logging && classLoader != null )
+ log.trace("Using thread classloader") ;
+
+// if (classLoader == null)
+// {
+// classLoader = this.getClass().getClassLoader();
+// if ( classLoader != null )
+// logger.trace("Using 'this' classloader") ;
+// }
+
+ if ( classLoader == null )
+ {
+ classLoader = ClassLoader.getSystemClassLoader() ;
+ if ( logging && classLoader != null )
+ log.trace("Using system classloader") ;
+ }
+
+ if ( classLoader == null )
+ throw new AtlasException("Failed to find a classloader") ;
+ return classLoader ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Timer.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Timer.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Timer.java
new file mode 100644
index 0000000..304e086
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Timer.java
@@ -0,0 +1,72 @@
+/*
+ * 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.lib ;
+
+import org.apache.jena.atlas.AtlasException ;
+
+/** A Timer of operations */
+public class Timer {
+
+ protected long timeFinish = -1 ;
+ protected boolean inTimer = false ;
+ protected long timeStart = 0 ;
+
+ public Timer() {}
+
+ public void startTimer() {
+ if ( inTimer )
+ throw new AtlasException("Already in timer") ;
+
+ timeStart = System.currentTimeMillis() ;
+ timeFinish = -1 ;
+ inTimer = true ;
+ }
+
+ /** Return time in millisecods */
+ public long endTimer() {
+ if ( !inTimer )
+ throw new AtlasException("Not in timer") ;
+ timeFinish = System.currentTimeMillis() ;
+ inTimer = false ;
+ return getTimeInterval() ;
+ }
+
+ public long readTimer() {
+ if ( !inTimer )
+ throw new AtlasException("Not in timer") ;
+ return System.currentTimeMillis() - timeStart ;
+ }
+
+ public long getTimeInterval() {
+ if ( inTimer )
+ throw new AtlasException("Still timing") ;
+ if ( timeFinish == -1 )
+ throw new AtlasException("No valid interval") ;
+
+ return timeFinish - timeStart ;
+ }
+
+ static public String timeStr(long timeInterval) {
+ return String.format("%.3f", timeInterval / 1000.0) ;
+ }
+
+ protected String timeStr(long timePoint, long startTimePoint) {
+ return timeStr(timePoint - startTimePoint) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Trie.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Trie.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Trie.java
new file mode 100644
index 0000000..0d823bc
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Trie.java
@@ -0,0 +1,407 @@
+/*
+ * 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.lib;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * An implementation of a classic Trie, this is a mapping from strings to some
+ * value type optimized for fast prefix search and match. If you do not need
+ * prefix search then you should typically use a standard {@link Map} instead.
+ * <p>
+ * The empty or null string may be used as a special key to refer to the root
+ * node of the trie.
+ * </p>
+ * <p>
+ * A Trie cannot store null values since null is used as an internal marker to
+ * indicate that there is no value associated with a key. This is necessary
+ * because the nature of the data structure means that adding a key potentially
+ * adds multiple keys many of which will not be associated with a value.
+ * </p>
+ *
+ * @param <T>
+ * Type of the value stored.
+ */
+public final class Trie<T> {
+
+ private TrieNode<T> root = new TrieNode<>(null);
+
+ /**
+ * Adds a value to the trie overwriting any existing value
+ * <p>
+ * Note that a null value is treated as if the key does not actually exist
+ * in the tree so trying to add a null is a no-op. If you want to remove a
+ * key use the {@link #remove(String)} method instead.
+ * </p>
+ *
+ * @param key
+ * Key
+ * @param value
+ * Value
+ */
+ public void add(String key, T value) {
+ if (value == null)
+ return;
+ TrieNode<T> n = this.moveToNode(key);
+ n.setValue(value);
+ }
+
+ /**
+ * Move to a node creating new nodes if necessary
+ *
+ * @param key
+ * Key
+ * @return Node
+ */
+ private TrieNode<T> moveToNode(String key) {
+ TrieNode<T> current = this.root;
+ if (key == null)
+ return current;
+ for (int i = 0; i < key.length(); i++) {
+ current = current.moveToChild(key.charAt(i));
+ }
+ return current;
+ }
+
+ /**
+ * Try to find a node in the trie
+ *
+ * @param key
+ * Key
+ * @return Node or null if not found
+ */
+ private TrieNode<T> find(String key) {
+ TrieNode<T> current = this.root;
+ if (key == null)
+ return current;
+ for (int i = 0; i < key.length(); i++) {
+ current = current.getChild(key.charAt(i));
+ if (current == null)
+ break;
+ }
+ return current;
+ }
+
+ /**
+ * Removes a value from the trie
+ * <p>
+ * This doesn't actually remove the key per-se rather sets the value
+ * associated with the key to null.
+ * </p>
+ *
+ * @param key
+ * Key
+ */
+ public void remove(String key) {
+ TrieNode<T> n = this.find(key);
+ if (n != null) {
+ n.setValue(null);
+ }
+ }
+
+ /**
+ * Gets whether a key exists in the trie and has a non-null value mapped to
+ * it
+ *
+ * @param key
+ * Key
+ * @return True if the key exists and has a non-null value mapped to it
+ */
+ public boolean contains(String key) {
+ return this.contains(key, true);
+ }
+
+ /**
+ * Gets whether a key exists in the trie and meets the given value criteria
+ *
+ * @param key
+ * Key
+ * @param requireValue
+ * If true a key must have a non-null value associated with it to
+ * be considered to be contained in the tree, if false then the
+ * key must merely map to a node in the trie
+ * @return True if the key exists and the value criteria is met, false
+ * otherwise
+ */
+ public boolean contains(String key, boolean requireValue) {
+ TrieNode<T> n = this.find(key);
+ if (n == null)
+ return false;
+ if (requireValue) {
+ return n.hasValue();
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Gets whether a key value pair are present in the trie
+ *
+ * @param key
+ * Key
+ * @param value
+ * Value
+ * @return True if the key value pair exists in the trie, false otherwise
+ */
+ public boolean contains(String key, T value) {
+ TrieNode<T> n = this.find(key);
+ if (n == null)
+ return false;
+ if (value == null && !n.hasValue())
+ return true;
+ return value.equals(n.getValue());
+ }
+
+ /**
+ * Gets the value associated with a key
+ *
+ * @param key
+ * Key
+ * @return Value
+ */
+ public T get(String key) {
+ TrieNode<T> n = this.find(key);
+ if (n == null)
+ return null;
+ return n.getValue();
+ }
+
+ /**
+ * Performs a prefix search and returns all values mapped under the given
+ * prefix. The entirety of the prefix must be matches, if you only want part
+ * of the prefix to be matched use the {@link #partialSearch(String)} method
+ * instead.
+ *
+ * @param prefix
+ * Prefix
+ * @return List of values associated with the given key
+ */
+ public List<T> prefixSearch(String prefix) {
+ TrieNode<T> n = this.find(prefix);
+ if (n == null)
+ return new ArrayList<>();
+ return Collections.unmodifiableList(n.getValues());
+ }
+
+ /**
+ * Performs a search and returns any value associated with any partial or
+ * whole prefix of the key
+ *
+ * @param key
+ * Key
+ * @return List of values associated with any partial prefix of the key
+ */
+ public List<T> partialSearch(String key) {
+ List<T> values = new ArrayList<>();
+ TrieNode<T> current = this.root;
+ if (key == null) {
+ if (current.hasValue())
+ values.add(current.getValue());
+ } else {
+ for (int i = 0; i < key.length(); i++) {
+ if (current.hasValue())
+ values.add(current.getValue());
+ current = current.getChild(key.charAt(i));
+ if (current == null)
+ return Collections.unmodifiableList(values);
+ }
+
+ // If we reach here current is the complete key match
+ // so make sure to include it in the values list
+ if (current.hasValue()) {
+ values.add(current.getValue());
+ }
+
+ }
+ return Collections.unmodifiableList(values);
+ }
+
+ /**
+ * Finds the shortest match for a given key i.e. returns the value
+ * associated with the shortest prefix of the key that has a value
+ *
+ * @param key
+ * Key
+ * @return Shortest Match or null if no possible matches
+ */
+ public T shortestMatch(String key) {
+ TrieNode<T> current = this.root;
+ if (key == null)
+ return current.getValue();
+ for (int i = 0; i < key.length(); i++) {
+ if (current.hasValue())
+ break;
+ current = current.getChild(key.charAt(i));
+ if (current == null)
+ return null;
+ }
+ return current.getValue();
+ }
+
+ /**
+ * Finds the longest match for a given key i.e. returns the value associated
+ * with the longest prefix of the key that has a value
+ *
+ * @param key
+ * Key
+ * @return Longest Match or null if no possible matches
+ */
+ public T longestMatch(String key) {
+ T value = null;
+ TrieNode<T> current = this.root;
+ if (key == null) {
+ return current.getValue();
+ } else {
+ for (int i = 0; i < key.length(); i++) {
+ if (current.hasValue())
+ value = current.getValue();
+ current = current.getChild(key.charAt(i));
+ if (current == null)
+ return value;
+ }
+ // If we reach here current is the complete key match
+ // so return its value if it has one
+ if (current.hasValue()) {
+ return current.getValue();
+ }
+ }
+ return value;
+ }
+
+ /**
+ * Represents a node in the Trie
+ * <p>
+ * The implementation is designed to be sparse such that we delay creation
+ * of things at both leafs and interior nodes until they are actually needed
+ * </p>
+ *
+ */
+ private static class TrieNode<T> {
+ private Map<Character, TrieNode<T>> children = null;
+ private Character singletonChildChar = null;
+ private TrieNode<T> singletonChild = null;
+ private T value;
+
+ /**
+ * Creates a Trie Node
+ *
+ * @param value
+ * Value
+ */
+ public TrieNode(T value) {
+ this.value = value;
+ }
+
+ /**
+ * Gets the value
+ *
+ * @return Value
+ */
+ public T getValue() {
+ return this.value;
+ }
+
+ /**
+ * Sets the value
+ *
+ * @param value
+ * Value
+ */
+ public void setValue(T value) {
+ this.value = value;
+ }
+
+ /**
+ * Returns whether a non-null value is associated with this node
+ *
+ * @return True if there is a non-null value, false otherwise
+ */
+ public boolean hasValue() {
+ return this.value != null;
+ }
+
+ /**
+ * Gets the child (if it exists)
+ *
+ * @param c
+ * Character to move to
+ * @return Child
+ */
+ public TrieNode<T> getChild(Character c) {
+ if (this.children != null) {
+ return this.children.get(c);
+ } else if (c.equals(this.singletonChildChar)) {
+ return this.singletonChild;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Moves to a child (creating a new node if necessary)
+ *
+ * @param c
+ * Character to move to
+ * @return Child
+ */
+ public TrieNode<T> moveToChild(Character c) {
+ TrieNode<T> n = this.getChild(c);
+ if (n == null) {
+ n = new TrieNode<>(null);
+ if (this.children != null) {
+ // Add to existing map
+ this.children.put(c, n);
+ } else if (this.singletonChildChar != null) {
+ // Need to lazily create map
+ this.children = new HashMap<>();
+ this.children.put(this.singletonChildChar, this.singletonChild);
+ this.children.put(c, n);
+ } else {
+ // Singleton child
+ this.singletonChildChar = c;
+ this.singletonChild = n;
+ }
+ }
+ return n;
+ }
+
+ /**
+ * Gets all values from a given node and its descendants
+ *
+ * @return Values
+ */
+ public List<T> getValues() {
+ List<T> values = new ArrayList<>();
+ if (this.hasValue()) {
+ values.add(this.value);
+ }
+ if (this.children != null) {
+ for (TrieNode<T> child : this.children.values()) {
+ values.addAll(child.getValues());
+ }
+ } else if (this.singletonChild != null) {
+ values.addAll(this.singletonChild.getValues());
+ }
+ return values;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Tuple.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Tuple.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Tuple.java
new file mode 100644
index 0000000..ae944a7
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Tuple.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.atlas.lib ;
+
+import java.util.Arrays ;
+import java.util.Iterator ;
+import java.util.List ;
+
+import org.apache.jena.atlas.iterator.Iter ;
+import org.apache.jena.atlas.iterator.IteratorArray ;
+import org.apache.jena.atlas.iterator.Transform ;
+
+/** Tuple class - tuples are immutable and must be created initialized */
+public class Tuple<T> implements Iterable<T> {
+ // Interface this?
+ // Classes: TupleImpl, TupleSlice
+ public static <X> Tuple<X> createTuple(@SuppressWarnings("unchecked") X... elements) {
+ X[] els = elements ; // ArrayUtils.copy(elements) ;
+ return create(els) ;
+ }
+
+ /**
+ * Create a tuple from an array of elements. The array is not copied and
+ * should not be modified after this call.
+ * <p>
+ * There is also a {@link TupleBuilder} which does create an idendent
+ * copy, in case that style is preferrable for creating tuples.
+ */
+ public static <X> Tuple<X> create(X[] elements) {
+ return new Tuple<>(elements) ;
+ }
+
+ // TupleLib??
+ public static <T> Iterator<T> project(final int slot, Iterator<Tuple<T>> iter) {
+ Transform<Tuple<T>, T> projection = new Transform<Tuple<T>, T>() {
+ @Override
+ public T convert(Tuple<T> tuple) {
+ return tuple.get(slot) ;
+ }
+ } ;
+ return Iter.map(iter, projection) ;
+ }
+
+ public static <T> Iterator<Tuple<T>> prefix(final int prefixLength, Iterator<Tuple<T>> iter) {
+ Transform<Tuple<T>, Tuple<T>> sub = new Transform<Tuple<T>, Tuple<T>>() {
+ @Override
+ public Tuple<T> convert(Tuple<T> tuple) {
+ T[] x = ArrayUtils.copy(tuple.tuple, 0, prefixLength) ;
+ return Tuple.create(x) ;
+ }
+ } ;
+ return Iter.map(iter, sub) ;
+ }
+
+ protected final T[] tuple ;
+
+ protected Tuple(@SuppressWarnings("unchecked") T... tuple) {
+ this.tuple = tuple ;
+ }
+
+ public T get(int idx) {
+ return tuple[idx] ;
+ }
+
+ public int countNotNull() {
+ int x = 0 ;
+ for ( T item : tuple )
+ if ( item != null )
+ x++ ;
+ return x ;
+ }
+
+ public List<T> asList() {
+ return Arrays.asList(tuple) ;
+ }
+
+ public T[] tuple() {
+ return tuple ;
+ }
+
+ public T[] tupleCopy() {
+ return ArrayUtils.copy(tuple) ;
+ }
+
+ @Override
+ public Iterator<T> iterator() {
+ return IteratorArray.create(tuple) ;
+ }
+
+ /** Return a tuple with the column mapping applied */
+ public Tuple<T> map(ColumnMap colMap) {
+ return colMap.map(this) ;
+ }
+
+ /** Return a tuple with the column mapping reversed */
+ public Tuple<T> unmap(ColumnMap colMap) {
+ return colMap.unmap(this) ;
+ }
+
+ public int size() {
+ return tuple.length ;
+ }
+
+ @Override
+ public int hashCode() {
+ int x = 99 ;
+ for ( T n : tuple ) {
+ if ( n != null )
+ x = x << 1 ^ n.hashCode() ;
+ }
+ return x ;
+ }
+
+ /** Equality of tuples is based on equality of the elements in the tuple */
+ @Override
+ public boolean equals(Object other) {
+ if ( this == other )
+ return true ;
+ if ( !(other instanceof Tuple<? >) )
+ return false ;
+ Tuple<? > x = (Tuple<? >)other ;
+ if ( x.size() != this.size() )
+ return false ;
+ for ( int i = 0 ; i < tuple.length ; i++ ) {
+ Object obj1 = tuple[i] ;
+ Object obj2 = x.tuple[i] ;
+ if ( !Lib.equal(obj1, obj2) )
+ return false ;
+ }
+ return true ;
+ }
+
+ @Override
+ public String toString() {
+ return "[" + Iter.asString(iterator(), ", ") + "]" ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/TupleBuilder.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/TupleBuilder.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/TupleBuilder.java
new file mode 100644
index 0000000..278334d
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/TupleBuilder.java
@@ -0,0 +1,50 @@
+/*
+ * 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.lib;
+
+
+import java.util.ArrayList ;
+import java.util.List ;
+
+/** Tuple builder class - tuples are immutable, this is how to create them in the builder style */
+public class TupleBuilder<T>
+{
+ private List<T> x = new ArrayList<>() ;
+
+ public TupleBuilder() { }
+
+ public TupleBuilder<T> add(T element) {
+ x.add(element) ;
+ return this ;
+ }
+
+ public TupleBuilder<T> reset() {
+ x.clear() ;
+ return this ;
+ }
+
+ public Tuple<T> build() {
+ @SuppressWarnings("unchecked")
+ T[] elts = (T[])new Object[x.size()] ;
+ // Copy contents, should not create a new array because elts
+ // is created with the right size so elts == elts2
+ T[] elts2 = x.toArray(elts) ;
+ return new Tuple<>(elts2) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/XMLLib.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/XMLLib.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/XMLLib.java
new file mode 100644
index 0000000..e8640df
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/XMLLib.java
@@ -0,0 +1,62 @@
+/*
+ * 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.lib;
+
+/** Operations in someway related to XML */
+public class XMLLib
+{
+ /** Trim the XML whitespace characters strictly needed for whitespace facet collapse.
+ * This <b>not</b> full whitespace facet collapse, which also requires processing of
+ * internal spaces. Because none of the datatypes that have whitespace facet
+ * collapse and have values we extract can legally contain internal whitespace,
+ * we just need to trim the string.
+ *
+ * Java String.trim removes any characters less than 0x20.
+ */
+ static String WScollapse(String string)
+ {
+ int len = string.length();
+ if ( len == 0 )
+ return string ;
+
+ if ( (string.charAt(0) > 0x20) && (string.charAt(len-1) > 0x20) )
+ return string ;
+
+ int idx1 = 0 ;
+ for ( ; idx1 < len ; idx1++ )
+ {
+ char ch = string.charAt(idx1) ;
+ if ( ! testForWS(ch) )
+ break ;
+ }
+ int idx2 = len-1 ;
+ for ( ; idx2 > idx1 ; idx2-- )
+ {
+ char ch = string.charAt(idx2) ;
+ if ( ! testForWS(ch) )
+ break ;
+ }
+ return string.substring(idx1, idx2+1) ;
+ }
+
+ private static boolean testForWS(char ch)
+ {
+ return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/Cache0.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/Cache0.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/Cache0.java
new file mode 100644
index 0000000..00befa0
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/Cache0.java
@@ -0,0 +1,72 @@
+/*
+ * 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.lib.cache ;
+
+import java.util.Iterator ;
+import java.util.concurrent.Callable ;
+
+import org.apache.jena.atlas.iterator.Iter ;
+import org.apache.jena.atlas.lib.ActionKeyValue ;
+import org.apache.jena.atlas.lib.Cache ;
+
+/** A cache that keeps nothing */
+public final class Cache0<K, V> implements Cache<K, V> {
+ @Override
+ public boolean containsKey(K key) {
+ return false ;
+ }
+
+ @Override
+ public V getIfPresent(K key) {
+ return null ;
+ }
+
+ @Override
+ public V getOrFill(K key, Callable<V> callable) {
+ return null ;
+ }
+
+ @Override
+ public void put(K key, V thing) {}
+
+ @Override
+ public void remove(K key) {}
+
+ @Override
+ public Iterator<K> keys() {
+ return Iter.nullIterator() ;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return true ;
+ }
+
+ @Override
+ public void clear() {}
+
+ @Override
+ public long size() {
+ return 0 ;
+ }
+
+ @Override
+ public void setDropHandler(ActionKeyValue<K, V> dropHandler) {}
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/Cache1.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/Cache1.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/Cache1.java
new file mode 100644
index 0000000..38ab5c6
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/Cache1.java
@@ -0,0 +1,127 @@
+/*
+ * 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.lib.cache;
+
+import java.util.Iterator ;
+import java.util.concurrent.Callable ;
+
+import org.apache.jena.atlas.iterator.SingletonIterator ;
+import org.apache.jena.atlas.lib.ActionKeyValue ;
+import org.apache.jena.atlas.lib.Cache ;
+import org.apache.jena.atlas.lib.Lib ;
+
+/** A one-slot cache.*/
+public class Cache1<K, V> implements Cache<K,V>
+{
+ private ActionKeyValue<K, V> dropHandler = null ;
+ private K cacheKey ;
+ private V cacheValue ;
+
+ public Cache1() { clear() ; }
+
+ @Override
+ public boolean containsKey(K key)
+ {
+ if ( cacheKey == null )
+ return false ;
+ return cacheKey.equals(key) ;
+ }
+
+ @Override
+ public V getIfPresent(K key)
+ {
+ if ( cacheKey == null ) return null ;
+ if ( cacheKey.equals(key) ) return cacheValue ;
+ return null ;
+ }
+
+ @Override
+ public V getOrFill(K key, Callable<V> callable) {
+ return CacheOps.getOrFillSync(this, key, callable) ;
+ }
+
+ @Override
+ public void clear()
+ {
+ if ( cacheKey == null )
+ return ;
+
+ K k = cacheKey ;
+ V v = cacheValue ;
+ cacheKey = null ;
+ cacheValue = null ;
+
+ notifyDrop(k, v) ;
+ }
+
+ @Override
+ public boolean isEmpty()
+ {
+ return cacheKey == null ;
+ }
+
+ @Override
+ public Iterator<K> keys()
+ {
+ return new SingletonIterator<>(cacheKey) ;
+ }
+
+ @Override
+ public void put(K key, V thing)
+ {
+ if ( Lib.equal(cacheKey, key) && Lib.equal(cacheValue, thing) )
+ // No change.
+ return ;
+
+ // Change
+ K k = cacheKey ;
+ V v = cacheValue ;
+ // Displaces any existing cached key/value pair
+ cacheKey = key ;
+ cacheValue = thing ;
+ notifyDrop(k, v) ;
+ }
+
+ @Override
+ public void remove(K key)
+ {
+ if ( cacheKey == null ) return ;
+ if ( cacheKey.equals(key) )
+ clear() ; // Will notify
+ }
+
+ @Override
+ public void setDropHandler(ActionKeyValue<K, V> dropHandler)
+ {
+ this.dropHandler = dropHandler ;
+ }
+
+ private void notifyDrop(K key, V thing)
+ {
+ if ( dropHandler != null && key != null )
+ dropHandler.apply(key, thing) ;
+ }
+
+ @Override
+ public long size()
+ {
+ return (cacheKey == null) ? 0 : 1 ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheGuava.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheGuava.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheGuava.java
new file mode 100644
index 0000000..fd5959c
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheGuava.java
@@ -0,0 +1,119 @@
+/**
+ * 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.lib.cache;
+
+import java.util.Iterator ;
+import java.util.concurrent.Callable ;
+import java.util.concurrent.ExecutionException ;
+
+import org.apache.jena.atlas.lib.ActionKeyValue ;
+import org.apache.jena.atlas.lib.Cache ;
+import org.apache.jena.atlas.logging.Log ;
+
+import org.apache.jena.ext.com.google.common.cache.CacheBuilder ;
+import org.apache.jena.ext.com.google.common.cache.RemovalListener ;
+import org.apache.jena.ext.com.google.common.cache.RemovalNotification ;
+
+/** Wrapper around com.google.common.cache */
+final
+public class CacheGuava<K,V> implements Cache<K, V>
+{
+ private ActionKeyValue<K, V> dropHandler = null ;
+ /*private*/ org.apache.jena.ext.com.google.common.cache.Cache<K,V> cache ;
+
+ public CacheGuava(int size)
+ {
+ RemovalListener<K,V> drop = new RemovalListener<K, V>() {
+ @Override
+ public void onRemoval(RemovalNotification<K, V> notification) {
+ if ( dropHandler != null )
+ dropHandler.apply(notification.getKey(),
+ notification.getValue()) ;
+ }
+ } ;
+ cache = CacheBuilder.newBuilder()
+ .maximumSize(size)
+ .removalListener(drop)
+ .recordStats()
+ .concurrencyLevel(8)
+ .build() ;
+ }
+
+ // Change the interface to be ...
+ @Override
+ public V getOrFill(K key, Callable<V> filler) {
+ try {
+ return cache.get(key, filler) ;
+ }
+ catch (ExecutionException e) {
+ Log.warn(CacheGuava.class, "Execution exception filling cache", e) ;
+ return null ;
+ }
+ }
+
+ @Override
+ public V getIfPresent(K key) {
+ return cache.getIfPresent(key) ;
+ }
+
+ @Override
+ public void put(K key, V thing) {
+ if ( thing == null ) {
+ cache.invalidate(key);
+ return ;
+ }
+ cache.put(key, thing) ;
+ }
+
+ @Override
+ public boolean containsKey(K key) {
+ return cache.getIfPresent(key) != null ;
+ }
+
+ @Override
+ public void remove(K key) {
+ cache.invalidate(key) ;
+ }
+
+ @Override
+ public Iterator<K> keys() {
+ return cache.asMap().keySet().iterator() ;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return cache.size() == 0 ;
+ }
+
+ @Override
+ public void clear() {
+ cache.invalidateAll() ;
+ }
+
+ @Override
+ public long size() {
+ return cache.size() ;
+ }
+
+ @Override
+ public void setDropHandler(ActionKeyValue<K, V> dropHandler) {
+ this.dropHandler = dropHandler ;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheOps.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheOps.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheOps.java
new file mode 100644
index 0000000..c8560bb
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheOps.java
@@ -0,0 +1,50 @@
+/**
+ * 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.lib.cache;
+
+import java.util.concurrent.Callable ;
+
+import org.apache.jena.atlas.AtlasException ;
+import org.apache.jena.atlas.lib.Cache ;
+
+/** Support operations for Cache functions */
+class CacheOps {
+
+ /** Implementation of getOrFill based on Cache.get and Cache.put */
+ public static <K,V> V getOrFill(Cache<K,V> cache, K key, Callable<V> callable) {
+ V value = cache.getIfPresent(key) ;
+ if ( value == null ) {
+ try { value = callable.call() ; }
+ catch (Exception e) {
+ throw new AtlasException("Exception on cache fill", e) ;
+ }
+ if ( value != null )
+ cache.put(key, value) ;
+ }
+ return value ;
+ }
+
+ /** Thread safe implementation of getOrFill based on Cache.get and Cache.put */
+ public static <K,V> V getOrFillSync(Cache<K,V> cache, K key, Callable<V> callable) {
+ synchronized(cache) {
+ return getOrFill(cache, key, callable) ;
+ }
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheSetImpl.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheSetImpl.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheSetImpl.java
new file mode 100644
index 0000000..b3bf048
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheSetImpl.java
@@ -0,0 +1,93 @@
+/*
+ * 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.lib.cache ;
+
+import java.util.Iterator ;
+
+import org.apache.jena.atlas.iterator.Action ;
+import org.apache.jena.atlas.lib.ActionKeyValue ;
+import org.apache.jena.atlas.lib.Cache ;
+import org.apache.jena.atlas.lib.CacheSet ;
+
+/** Cache set */
+public class CacheSetImpl<T> implements CacheSet<T> {
+ // LinkHashSet does not have LRU support.
+ static Object theOnlyValue = new Object() ;
+ Cache<T, Object> cacheMap = null ;
+
+ public CacheSetImpl(Cache<T, Object> cache) {
+ cacheMap = cache ;
+ }
+
+ /** Callback for entries when dropped from the cache */
+ @Override
+ public void setDropHandler(Action<T> dropHandler) {
+ cacheMap.setDropHandler(new Wrapper<T>(dropHandler)) ;
+ }
+
+ // From map action to set action.
+ static class Wrapper<T> implements ActionKeyValue<T, Object> {
+ Action<T> dropHandler ;
+
+ public Wrapper(Action<T> dropHandler) {
+ this.dropHandler = dropHandler ;
+ }
+
+ @Override
+ public void apply(T key, Object value) {
+ dropHandler.apply(key) ;
+ }
+
+ }
+
+ @Override
+ public void add(T e) {
+ cacheMap.put(e, theOnlyValue) ;
+ }
+
+ @Override
+ public void clear() {
+ cacheMap.clear() ;
+ }
+
+ @Override
+ public boolean contains(T obj) {
+ return cacheMap.containsKey(obj) ;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return cacheMap.isEmpty() ;
+ }
+
+ public Iterator<T> iterator() {
+ return cacheMap.keys() ;
+ }
+
+ @Override
+ public void remove(T obj) {
+ cacheMap.remove(obj) ;
+ }
+
+ @Override
+ public long size() {
+ return cacheMap.size() ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheSetSync.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheSetSync.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheSetSync.java
new file mode 100644
index 0000000..fc3a3bd
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheSetSync.java
@@ -0,0 +1,65 @@
+/*
+ * 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.lib.cache ;
+
+import org.apache.jena.atlas.iterator.Action ;
+import org.apache.jena.atlas.lib.CacheSet ;
+
+public class CacheSetSync<T> implements CacheSet<T> {
+ private CacheSet<T> cache ;
+
+ public CacheSetSync(CacheSet<T> cache) {
+ this.cache = cache ;
+ }
+
+ @Override
+ synchronized public void add(T e) {
+ cache.add(e) ;
+ }
+
+ @Override
+ synchronized public void clear() {
+ cache.clear() ;
+ }
+
+ @Override
+ synchronized public boolean contains(T obj) {
+ return cache.contains(obj) ;
+ }
+
+ @Override
+ synchronized public boolean isEmpty() {
+ return cache.isEmpty() ;
+ }
+
+ @Override
+ synchronized public void remove(T obj) {
+ cache.remove(obj) ;
+ }
+
+ @Override
+ synchronized public long size() {
+ return cache.size() ;
+ }
+
+ @Override
+ synchronized public void setDropHandler(Action<T> dropHandler) {
+ cache.setDropHandler(dropHandler) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheSetWrapper.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheSetWrapper.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheSetWrapper.java
new file mode 100644
index 0000000..c11ffb0
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheSetWrapper.java
@@ -0,0 +1,65 @@
+/*
+ * 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.lib.cache ;
+
+import org.apache.jena.atlas.iterator.Action ;
+import org.apache.jena.atlas.lib.CacheSet ;
+
+public class CacheSetWrapper<T> implements CacheSet<T> {
+ private CacheSet<T> cache ;
+
+ public CacheSetWrapper(CacheSet<T> cache) {
+ this.cache = cache ;
+ }
+
+ @Override
+ public void add(T e) {
+ cache.add(e) ;
+ }
+
+ @Override
+ public void clear() {
+ cache.clear() ;
+ }
+
+ @Override
+ public boolean contains(T obj) {
+ return cache.contains(obj) ;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return cache.isEmpty() ;
+ }
+
+ @Override
+ public void remove(T obj) {
+ cache.remove(obj) ;
+ }
+
+ @Override
+ public long size() {
+ return cache.size() ;
+ }
+
+ @Override
+ public void setDropHandler(Action<T> dropHandler) {
+ cache.setDropHandler(dropHandler) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheSimple.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheSimple.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheSimple.java
new file mode 100644
index 0000000..a33d8e2
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheSimple.java
@@ -0,0 +1,161 @@
+/*
+ * 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.lib.cache;
+
+import java.util.Arrays ;
+import java.util.Iterator ;
+import java.util.concurrent.Callable ;
+
+import org.apache.jena.atlas.iterator.Iter ;
+import org.apache.jena.atlas.iterator.IteratorArray ;
+import org.apache.jena.atlas.lib.ActionKeyValue ;
+import org.apache.jena.atlas.lib.Cache ;
+
+
+/**
+ * A simple fixed size cache that uses the hash code to address a slot.
+ * Clash policy is to overwrite.
+ * No object creation during lookup or insert.
+ */
+
+public class CacheSimple<K,V> implements Cache<K,V>
+{
+ private final V[] values ;
+ private final K[] keys ;
+ private final int size ;
+ private int currentSize = 0 ;
+ private ActionKeyValue<K,V> dropHandler = null ;
+
+ public CacheSimple(int size)
+ {
+ @SuppressWarnings("unchecked")
+ V[] x = (V[])new Object[size] ;
+ values = x ;
+
+ @SuppressWarnings("unchecked")
+ K[] z = (K[])new Object[size] ;
+ keys = z ;
+
+ this.size = size ;
+ }
+
+
+ @Override
+ public void clear()
+ {
+ Arrays.fill(values, null) ;
+ Arrays.fill(keys, null) ;
+ // drop handler
+ currentSize = 0 ;
+ }
+
+ @Override
+ public boolean containsKey(K key)
+ {
+ return getIfPresent(key) != null ;
+ }
+
+ // Return key index : -(index+1) if the key does not match
+ private final int index(K key)
+ {
+ int x = (key.hashCode()&0x7fffffff) % size ;
+ if ( keys[x] != null && keys[x].equals(key) )
+ return x ;
+ return -x-1 ;
+ }
+
+ private final int decode(int x)
+ {
+ if ( x >= 0 ) return x ;
+ return -x-1 ;
+ }
+
+ @Override
+ public V getIfPresent(K key)
+ {
+ int x = index(key) ;
+ if ( x < 0 )
+ return null ;
+ return values[x] ;
+ }
+
+ @Override
+ public V getOrFill(K key, Callable<V> callable) {
+ return CacheOps.getOrFill(this, key, callable) ;
+ }
+
+ @Override
+ public void put(K key, V thing)
+ {
+ int x = index(key) ;
+ V old = null ;
+ if ( x < 0 )
+ // New.
+ x = decode(x) ;
+ else
+ {
+ // Drop the old K->V
+ old = values[x] ;
+ if ( dropHandler != null )
+ dropHandler.apply(keys[x], old) ;
+ currentSize-- ;
+ }
+
+ values[x] = thing ;
+ if ( thing == null )
+ //put(,null) is a remove.
+ keys[x] = null ;
+ else {
+ keys[x] = key ;
+ currentSize++ ;
+ }
+ }
+
+ @Override
+ public void remove(K key)
+ {
+ put(key, null) ;
+ }
+
+ @Override
+ public long size()
+ {
+ return currentSize ;
+ }
+
+ @Override
+ public Iterator<K> keys()
+ {
+ Iterator<K> iter = IteratorArray.create(keys) ;
+ return Iter.removeNulls(iter) ;
+ }
+
+ @Override
+ public boolean isEmpty()
+ {
+ return currentSize == 0 ;
+ }
+
+ /** Callback for entries when dropped from the cache */
+ @Override
+ public void setDropHandler(ActionKeyValue<K,V> dropHandler)
+ {
+ this.dropHandler = dropHandler ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheWrapper.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheWrapper.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheWrapper.java
new file mode 100644
index 0000000..e655749
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/CacheWrapper.java
@@ -0,0 +1,65 @@
+/*
+ * 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.lib.cache;
+import java.util.Iterator ;
+import java.util.concurrent.Callable ;
+
+import org.apache.jena.atlas.lib.ActionKeyValue ;
+import org.apache.jena.atlas.lib.Cache ;
+
+
+
+public class CacheWrapper<Key,T> implements Cache<Key,T>
+{
+ protected Cache<Key,T> cache ;
+
+ public CacheWrapper(Cache<Key,T> cache) { this.cache = cache ; }
+
+ @Override
+ public void clear() { cache.clear(); }
+
+ @Override
+ public boolean containsKey(Key key) { return cache.containsKey(key) ; }
+
+ @Override
+ public T getIfPresent(Key key) { return cache.getIfPresent(key) ; }
+
+ @Override
+ public T getOrFill(Key key, Callable<T> callable) { return cache.getOrFill(key, callable) ; }
+
+ @Override
+ public boolean isEmpty() { return cache.isEmpty() ; }
+
+ @Override
+ public Iterator<Key> keys() { return cache.keys(); }
+
+ @Override
+ public void put(Key key, T thing) { cache.put(key, thing) ; }
+
+ @Override
+ public void remove(Key key) { cache.remove(key) ; }
+
+ @Override
+ public void setDropHandler(ActionKeyValue<Key, T> dropHandler)
+ { cache.setDropHandler(dropHandler) ; }
+
+ @Override
+ public long size() { return cache.size() ; }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/Getter.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/Getter.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/Getter.java
new file mode 100644
index 0000000..c9f879c
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/cache/Getter.java
@@ -0,0 +1,25 @@
+/*
+ * 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.lib.cache;
+
+/** A get interface */
+public interface Getter<K, V>
+{
+ public V get(K key) ;
+}
[9/9] jena git commit: Import of lib, io,
logging and iterator packages
Posted by an...@apache.org.
Import of lib, io, logging and iterator packages
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/1320f8db
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/1320f8db
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/1320f8db
Branch: refs/heads/master
Commit: 1320f8dbe2ed08f10fda6e48aac9177557b1ed03
Parents: 692118f
Author: Andy Seaborne <an...@apache.org>
Authored: Tue Apr 28 22:03:14 2015 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Tue Apr 28 22:03:14 2015 +0100
----------------------------------------------------------------------
jena-base/pom.xml | 2 +-
.../org/apache/jena/atlas/AtlasException.java | 27 +
.../apache/jena/atlas/RuntimeIOException.java | 34 +
.../java/org/apache/jena/atlas/io/AWriter.java | 43 +
.../org/apache/jena/atlas/io/AWriterBase.java | 33 +
.../org/apache/jena/atlas/io/BlockUTF8.java | 281 ++++++
.../apache/jena/atlas/io/BufferingWriter.java | 180 ++++
.../org/apache/jena/atlas/io/CharStream.java | 31 +
.../apache/jena/atlas/io/CharStreamBasic.java | 58 ++
.../jena/atlas/io/CharStreamBuffered.java | 166 ++++
.../apache/jena/atlas/io/CharStreamReader.java | 56 ++
.../jena/atlas/io/CharStreamSequence.java | 47 +
.../main/java/org/apache/jena/atlas/io/IO.java | 325 +++++++
.../org/apache/jena/atlas/io/InStreamASCII.java | 89 ++
.../org/apache/jena/atlas/io/InStreamUTF8.java | 254 +++++
.../jena/atlas/io/IndentedLineBuffer.java | 50 +
.../apache/jena/atlas/io/IndentedWriter.java | 366 +++++++
.../jena/atlas/io/InputStreamBuffered.java | 104 ++
.../apache/jena/atlas/io/NullOutputStream.java | 40 +
.../org/apache/jena/atlas/io/OutStreamUTF8.java | 179 ++++
.../org/apache/jena/atlas/io/OutputUtils.java | 77 ++
.../apache/jena/atlas/io/PeekInputStream.java | 233 +++++
.../org/apache/jena/atlas/io/PeekReader.java | 270 ++++++
.../org/apache/jena/atlas/io/PrintUtils.java | 31 +
.../org/apache/jena/atlas/io/Printable.java | 24 +
.../org/apache/jena/atlas/io/PrintableBase.java | 26 +
.../org/apache/jena/atlas/io/StringWriterI.java | 30 +
.../java/org/apache/jena/atlas/io/Writer2.java | 97 ++
.../apache/jena/atlas/iterator/AccString.java | 66 ++
.../apache/jena/atlas/iterator/Accumulate.java | 27 +
.../org/apache/jena/atlas/iterator/Action.java | 24 +
.../apache/jena/atlas/iterator/ActionCount.java | 31 +
.../jena/atlas/iterator/ActionNothing.java | 26 +
.../org/apache/jena/atlas/iterator/Filter.java | 22 +
.../atlas/iterator/FilterDistinctAdjacent.java | 40 +
.../jena/atlas/iterator/FilterOutNulls.java | 32 +
.../apache/jena/atlas/iterator/FilterStack.java | 67 ++
.../jena/atlas/iterator/FilterUnique.java | 39 +
.../org/apache/jena/atlas/iterator/Iter.java | 971 +++++++++++++++++++
.../jena/atlas/iterator/IteratorArray.java | 92 ++
.../atlas/iterator/IteratorBlockingQueue.java | 73 ++
.../jena/atlas/iterator/IteratorConcat.java | 104 ++
.../jena/atlas/iterator/IteratorCons.java | 122 +++
.../iterator/IteratorDelayedInitialization.java | 78 ++
.../jena/atlas/iterator/IteratorInteger.java | 61 ++
.../atlas/iterator/IteratorResourceClosing.java | 107 ++
.../jena/atlas/iterator/IteratorSlotted.java | 117 +++
.../jena/atlas/iterator/IteratorTruncate.java | 79 ++
.../jena/atlas/iterator/IteratorWithBuffer.java | 132 +++
.../atlas/iterator/IteratorWithHistory.java | 109 +++
.../jena/atlas/iterator/IteratorWrapper.java | 41 +
.../apache/jena/atlas/iterator/MapUtils.java | 36 +
.../jena/atlas/iterator/NullIterator.java | 49 +
.../jena/atlas/iterator/PeekIterator.java | 100 ++
.../jena/atlas/iterator/PushbackIterator.java | 62 ++
.../atlas/iterator/RepeatApplyIterator.java | 86 ++
.../jena/atlas/iterator/SingletonIterator.java | 51 +
.../apache/jena/atlas/iterator/Transform.java | 21 +
.../jena/atlas/iterator/WrapperIterator.java | 45 +
.../apache/jena/atlas/lib/ActionKeyValue.java | 24 +
.../org/apache/jena/atlas/lib/AlarmClock.java | 69 ++
.../java/org/apache/jena/atlas/lib/Alg.java | 239 +++++
.../org/apache/jena/atlas/lib/Allocator.java | 28 +
.../org/apache/jena/atlas/lib/ArrayUtils.java | 64 ++
.../java/org/apache/jena/atlas/lib/BitsInt.java | 309 ++++++
.../org/apache/jena/atlas/lib/BitsLong.java | 311 ++++++
.../apache/jena/atlas/lib/ByteBufferLib.java | 211 ++++
.../java/org/apache/jena/atlas/lib/Bytes.java | 357 +++++++
.../java/org/apache/jena/atlas/lib/Cache.java | 56 ++
.../org/apache/jena/atlas/lib/CacheFactory.java | 67 ++
.../org/apache/jena/atlas/lib/CacheSet.java | 34 +
.../org/apache/jena/atlas/lib/CacheStats.java | 28 +
.../org/apache/jena/atlas/lib/Callback.java | 24 +
.../java/org/apache/jena/atlas/lib/Cell.java | 99 ++
.../java/org/apache/jena/atlas/lib/Chars.java | 271 ++++++
.../org/apache/jena/atlas/lib/Closeable.java | 27 +
.../apache/jena/atlas/lib/CollectionUtils.java | 52 +
.../org/apache/jena/atlas/lib/ColumnMap.java | 254 +++++
.../main/java/org/apache/jena/atlas/lib/DS.java | 45 +
.../apache/jena/atlas/lib/DateTimeUtils.java | 127 +++
.../org/apache/jena/atlas/lib/EscapeStr.java | 235 +++++
.../java/org/apache/jena/atlas/lib/FileOps.java | 239 +++++
.../java/org/apache/jena/atlas/lib/Hex.java | 97 ++
.../java/org/apache/jena/atlas/lib/IRILib.java | 243 +++++
.../jena/atlas/lib/InternalErrorException.java | 27 +
.../java/org/apache/jena/atlas/lib/Lib.java | 126 +++
.../org/apache/jena/atlas/lib/ListUtils.java | 150 +++
.../java/org/apache/jena/atlas/lib/Map2.java | 104 ++
.../org/apache/jena/atlas/lib/MapUtils.java | 45 +
.../org/apache/jena/atlas/lib/MultiMap.java | 146 +++
.../apache/jena/atlas/lib/MultiMapToList.java | 43 +
.../apache/jena/atlas/lib/MultiMapToSet.java | 47 +
.../org/apache/jena/atlas/lib/MultiSet.java | 218 +++++
.../apache/jena/atlas/lib/NotImplemented.java | 27 +
.../org/apache/jena/atlas/lib/NumberUtils.java | 133 +++
.../java/org/apache/jena/atlas/lib/Pair.java | 62 ++
.../java/org/apache/jena/atlas/lib/Pool.java | 30 +
.../org/apache/jena/atlas/lib/PoolBase.java | 57 ++
.../org/apache/jena/atlas/lib/PoolSync.java | 53 +
.../java/org/apache/jena/atlas/lib/Problem.java | 25 +
.../apache/jena/atlas/lib/PropertiesSorted.java | 87 ++
.../apache/jena/atlas/lib/PropertyUtils.java | 143 +++
.../org/apache/jena/atlas/lib/RandomLib.java | 41 +
.../java/org/apache/jena/atlas/lib/Ref.java | 54 ++
.../java/org/apache/jena/atlas/lib/RefLong.java | 38 +
.../org/apache/jena/atlas/lib/Registry.java | 39 +
.../jena/atlas/lib/ReverseComparator.java | 38 +
.../org/apache/jena/atlas/lib/SetUtils.java | 84 ++
.../java/org/apache/jena/atlas/lib/Sink.java | 29 +
.../org/apache/jena/atlas/lib/SinkCounting.java | 41 +
.../org/apache/jena/atlas/lib/SinkLogging.java | 41 +
.../org/apache/jena/atlas/lib/SinkNull.java | 33 +
.../org/apache/jena/atlas/lib/SinkPrint.java | 45 +
.../org/apache/jena/atlas/lib/SinkSplit.java | 55 ++
.../apache/jena/atlas/lib/SinkToCollection.java | 38 +
.../org/apache/jena/atlas/lib/SinkToQueue.java | 52 +
.../org/apache/jena/atlas/lib/SinkWrapper.java | 44 +
.../org/apache/jena/atlas/lib/StrUtils.java | 292 ++++++
.../java/org/apache/jena/atlas/lib/Sync.java | 24 +
.../org/apache/jena/atlas/lib/SystemUtils.java | 57 ++
.../java/org/apache/jena/atlas/lib/Timer.java | 72 ++
.../java/org/apache/jena/atlas/lib/Trie.java | 407 ++++++++
.../java/org/apache/jena/atlas/lib/Tuple.java | 153 +++
.../org/apache/jena/atlas/lib/TupleBuilder.java | 50 +
.../java/org/apache/jena/atlas/lib/XMLLib.java | 62 ++
.../org/apache/jena/atlas/lib/cache/Cache0.java | 72 ++
.../org/apache/jena/atlas/lib/cache/Cache1.java | 127 +++
.../apache/jena/atlas/lib/cache/CacheGuava.java | 119 +++
.../apache/jena/atlas/lib/cache/CacheOps.java | 50 +
.../jena/atlas/lib/cache/CacheSetImpl.java | 93 ++
.../jena/atlas/lib/cache/CacheSetSync.java | 65 ++
.../jena/atlas/lib/cache/CacheSetWrapper.java | 65 ++
.../jena/atlas/lib/cache/CacheSimple.java | 161 +++
.../jena/atlas/lib/cache/CacheWrapper.java | 65 ++
.../org/apache/jena/atlas/lib/cache/Getter.java | 25 +
.../org/apache/jena/atlas/logging/FmtLog.java | 162 ++++
.../java/org/apache/jena/atlas/logging/Log.java | 116 +++
.../org/apache/jena/atlas/logging/LogCtl.java | 282 ++++++
.../jena/atlas/logging/ProgressLogger.java | 133 +++
.../logging/java/ConsoleHandlerStdout.java | 75 ++
.../jena/atlas/logging/java/TextFormatter.java | 53 +
.../java/org/apache/jena/base/Closeable.java | 27 +
.../src/main/java/org/apache/jena/base/Sys.java | 27 +
.../java/org/apache/jena/atlas/TC_Atlas.java | 41 +
.../atlas/io/AbstractTestPeekInputStream.java | 243 +++++
.../jena/atlas/io/AbstractTestPeekReader.java | 243 +++++
.../java/org/apache/jena/atlas/io/TS_IO.java | 45 +
.../org/apache/jena/atlas/io/TestBlockUTF8.java | 254 +++++
.../jena/atlas/io/TestBufferingWriter.java | 97 ++
.../jena/atlas/io/TestIndentedWriter.java | 58 ++
.../jena/atlas/io/TestInputStreamBuffered.java | 109 +++
.../atlas/io/TestPeekInputStreamSource.java | 44 +
.../atlas/io/TestPeekReaderCharSequence.java | 32 +
.../jena/atlas/io/TestPeekReaderSource.java | 34 +
.../apache/jena/atlas/io/TestPrintUtils.java | 59 ++
.../apache/jena/atlas/io/TestStreamUTF8.java | 118 +++
.../apache/jena/atlas/iterator/TS_Iterator.java | 38 +
.../apache/jena/atlas/iterator/TestIter.java | 539 ++++++++++
.../jena/atlas/iterator/TestIteratorArray.java | 104 ++
.../jena/atlas/iterator/TestIteratorPeek.java | 107 ++
.../atlas/iterator/TestIteratorPushback.java | 93 ++
.../atlas/iterator/TestIteratorSlotted.java | 136 +++
.../atlas/iterator/TestIteratorWithBuffer.java | 97 ++
.../atlas/iterator/TestIteratorWithHistory.java | 87 ++
.../org/apache/jena/atlas/junit/BaseTest.java | 45 +
.../java/org/apache/jena/atlas/lib/TS_Lib.java | 57 ++
.../apache/jena/atlas/lib/TestAlarmClock.java | 92 ++
.../java/org/apache/jena/atlas/lib/TestAlg.java | 226 +++++
.../org/apache/jena/atlas/lib/TestBitsInt.java | 468 +++++++++
.../org/apache/jena/atlas/lib/TestBitsLong.java | 468 +++++++++
.../org/apache/jena/atlas/lib/TestBytes.java | 198 ++++
.../org/apache/jena/atlas/lib/TestCache.java | 149 +++
.../org/apache/jena/atlas/lib/TestCache2.java | 88 ++
.../apache/jena/atlas/lib/TestColumnMap.java | 107 ++
.../jena/atlas/lib/TestDateTimeUtils.java | 82 ++
.../org/apache/jena/atlas/lib/TestFileOps.java | 78 ++
.../jena/atlas/lib/TestFilenameProcessing.java | 136 +++
.../java/org/apache/jena/atlas/lib/TestHex.java | 81 ++
.../apache/jena/atlas/lib/TestListUtils.java | 79 ++
.../org/apache/jena/atlas/lib/TestMultiSet.java | 143 +++
.../apache/jena/atlas/lib/TestNumberUtils.java | 106 ++
.../org/apache/jena/atlas/lib/TestRefLong.java | 70 ++
.../jena/atlas/lib/TestReverseComparator.java | 91 ++
.../org/apache/jena/atlas/lib/TestSetUtils.java | 146 +++
.../org/apache/jena/atlas/lib/TestStrUtils.java | 59 ++
.../org/apache/jena/atlas/lib/TestTrie.java | 346 +++++++
.../org/apache/jena/atlas/lib/TestXMLLib.java | 47 +
187 files changed, 20541 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/pom.xml
----------------------------------------------------------------------
diff --git a/jena-base/pom.xml b/jena-base/pom.xml
index a8c05e5..0acf545 100644
--- a/jena-base/pom.xml
+++ b/jena-base/pom.xml
@@ -74,7 +74,7 @@
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
- <include>org/apache/jena/iri/test/TestPackage.java</include>
+ <include>**/TS_*.java</include>
</includes>
</configuration>
</plugin>
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/AtlasException.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/AtlasException.java b/jena-base/src/main/java/org/apache/jena/atlas/AtlasException.java
new file mode 100644
index 0000000..2754060
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/AtlasException.java
@@ -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;
+
+public class AtlasException extends RuntimeException
+{
+ public AtlasException() { super() ; }
+ public AtlasException(String msg) { super(msg) ; }
+ public AtlasException(Throwable th) { super(th) ; }
+ public AtlasException(String msg, Throwable th) { super(msg, th) ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/RuntimeIOException.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/RuntimeIOException.java b/jena-base/src/main/java/org/apache/jena/atlas/RuntimeIOException.java
new file mode 100644
index 0000000..1d9938b
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/RuntimeIOException.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.atlas;
+
+/** Runtime eception used to wrap IOExceptions */
+public class RuntimeIOException extends AtlasException
+{
+ public RuntimeIOException() { super() ; }
+ public RuntimeIOException(String msg) { super(msg) ; }
+ /**
+ * Wrap a Throwable - this is usually an IOException.
+ */
+ public RuntimeIOException(Throwable th) { super(th) ; }
+ /**
+ * Wrap a Throwable - this is usually an IOException.
+ */
+ public RuntimeIOException(String msg, Throwable th) { super(msg, th) ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/AWriter.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/AWriter.java b/jena-base/src/main/java/org/apache/jena/atlas/io/AWriter.java
new file mode 100644
index 0000000..c046544
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/AWriter.java
@@ -0,0 +1,43 @@
+/**
+ * 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.io;
+
+import org.apache.jena.atlas.lib.Closeable ;
+
+
+/** Simple abstraction of a string/character output stream */
+
+public interface AWriter extends Closeable, AutoCloseable
+{
+ public void write(char ch) ;
+ public void write(char[] cbuf) ;
+ public void write(String string) ;
+
+ public void print(char ch) ;
+ public void print(char[] cbuf) ;
+ public void print(String string) ;
+ public void printf(String fmt, Object ...arg) ;
+ public void println(String object) ;
+ public void println() ;
+
+ public void flush() ;
+ @Override
+ public void close() ;
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/AWriterBase.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/AWriterBase.java b/jena-base/src/main/java/org/apache/jena/atlas/io/AWriterBase.java
new file mode 100644
index 0000000..bc80fc2
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/AWriterBase.java
@@ -0,0 +1,33 @@
+/**
+ * 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.io;
+
+
+/** Simple abstraction of a string/character output stream */
+
+public abstract class AWriterBase implements AWriter
+{
+ @Override
+ public final void write(char ch) { print(ch) ; }
+ @Override
+ public final void write(char[] cbuf) { print(cbuf) ; }
+ @Override
+ public final void write(String string) { print(string) ; }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/BlockUTF8.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/BlockUTF8.java b/jena-base/src/main/java/org/apache/jena/atlas/io/BlockUTF8.java
new file mode 100644
index 0000000..2d5560b
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/BlockUTF8.java
@@ -0,0 +1,281 @@
+/**
+ * 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.io ;
+
+import java.io.IOException ;
+import java.nio.ByteBuffer ;
+import java.nio.CharBuffer ;
+
+import org.apache.jena.atlas.lib.NotImplemented ;
+
+/**
+ * Convert between bytes and chars, UTF-8 only.
+ *
+ * This code is just the UTF-8 encoding rules - it does not check for legality
+ * of the Unicode data. The standard codec do, so do not round-trip with binary
+ * compatibility. (Example: a single element of a surrogate pair will
+ * be encoded/decoded without lost.
+ *
+ *
+ * The usual Charset encoders/decoders can be expensive to start up - they are also
+ * not thread safe. Sometimes we want to convert 10's of chars and UTF-8 can be
+ * done in code with no lookup tables (which, if used, are cache-unfriendly).
+ *
+ * This code is thread safe. It uses code in the hope that JITting will
+ * make it fast if used heavily.
+ */
+
+public class BlockUTF8
+{
+ // Looking in java.lang.StringCoding (Sun RT) is illuminating.
+ // The actual encode/decode code is in sun.nio.cs.UTF_8.(Decoder|Encoder)
+ // which has special cases for ByteBuffer, ByteBuffer with array (needs offsets)
+ // and byte[] <-> char[]
+
+ // It seems that chars -> bytes (on <100char strings) is faster with BlockUTF8
+ // but the conversion from bytes to string is faster with Java decoders (not by much though).
+
+ /*
+ * Bits
+ * 7 U+007F 1 to 127 0xxxxxxx
+ * 11 U+07FF 128 to 2,047 110xxxxx 10xxxxxx
+ * 16 U+FFFF 2,048 to 65,535 1110xxxx 10xxxxxx 10xxxxxx
+ * 21 U+1FFFFF 65,536 to 1,114,111 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ * 26 U+3FFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+ * 31 U+7FFFFFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+ */
+
+
+ /** Convert the bytes in the ByteBuffer to characters in the CharBuffer.
+ * The CharBuffer must be large enough.
+ */
+ public static void toChars(ByteBuffer bb, CharBuffer cb)
+ {
+// if ( bb.hasArray() && cb.hasArray() )
+// {
+// toCharsArray(bb.array(), cb.array()) ;
+// return ;
+// }
+ toCharsBuffer(bb, cb) ;
+ }
+
+ /** Convert characters to UTF-8 bytes in the ByteBuffer.
+ * The ByteBuffer must be large enough.
+ */
+ public static void fromChars(CharBuffer cb, ByteBuffer bb)
+ {
+// if ( bb.hasArray() && cb.hasArray() )
+// {
+// fromCharsArray(cb.array(), bb.array()) ;
+// return ;
+// }
+ fromCharsBuffer(cb, bb) ;
+ }
+
+ /** Make a string from UTF-8 bytes in a ByteBuffer */
+ public static String toString(ByteBuffer bb)
+ {
+ // I think that the copy from some mutable collector to immutable string is inevitable in java.
+ int len = bb.remaining() ;
+ CharBuffer cb = CharBuffer.allocate(len) ;
+ toChars(bb, cb) ;
+ return new String(cb.array(), 0, cb.position()) ;
+ }
+
+ // Using buffer access.
+ private static void toCharsBuffer(ByteBuffer bb, CharBuffer cb)
+ {
+ int idx = bb.position();
+ int limit = bb.limit() ;
+
+ for ( ; idx < limit ; )
+ {
+ int x = bb.get() ;
+ if ( x > 0 && x <= 127 )
+ {
+ cb.put((char)x) ;
+ idx += 1 ;
+ } else if ( x == 0 )
+ {
+ // Pass through a null byte as the null character (illegal Unicode, Java compatible).
+ cb.put((char)x) ;
+ idx += 1 ;
+ }
+ else if ( (x & 0xE0) == 0xC0 )
+ {
+ // 10 => extension byte
+ // 110..... => 2 bytes
+ // Unroll common path
+ //int ch = readMultiBytes(bb, x & 0x1F, 2) ;
+ int x2 = bb.get() ;
+ if ( (x2 & 0xC0) != 0x80 )
+ exception("Illegal UTF-8 processing character: 0x%04X",x2) ;
+ // 6 bits of x2
+ int ch = ( (x&0x1F) << 6) | (x2 & 0x3F);
+ cb.put((char)ch) ;
+ idx += 2 ;
+ }
+ else if ( (x & 0xF0) == 0xE0 )
+ {
+ // 1110.... => 3 bytes : 16 bits : not outside 16bit chars
+ int ch = readMultiBytes(bb, x & 0x0F, 3) ;
+ cb.put((char)ch) ;
+ idx += 3 ;
+ }
+ else if ( (x & 0xF8) == 0xF0 )
+ {
+ // Looking like 4 byte charcater.
+ // 11110zzz => 4 bytes.
+ int ch = readMultiBytes(bb, x & 0x08, 4) ;
+ char chars[] = Character.toChars(ch) ;
+ cb.put(chars) ;
+ idx += 4 ;
+ }
+ else
+ {
+ exception("Illegal UTF-8: 0x%04X",x) ;
+ return ;
+ }
+ }
+ }
+
+ private static void toCharsArray(byte[] bytes, char[] chars)
+ {
+ throw new NotImplemented() ;
+ }
+
+ private static void fromCharsBuffer(CharBuffer cb, ByteBuffer bb)
+ {
+ // CharBuffers are CharSequences but charAt(i) adds a layer of work.
+ //int bytesStart = bb.position() ;
+ int idx = cb.position() ;
+ int limit = cb.limit() ;
+ for ( ; idx < limit ; idx ++ )
+ {
+ char ch = cb.get() ;
+ if ( ch != 0 && ch <= 127 )
+ {
+ // 7 bits
+ bb.put((byte)ch) ;
+ }
+ else if ( ch == 0 )
+ {
+ // Java.
+ bb.put((byte)0x00) ;
+ // Modified UTF-8.
+ //bb.put((byte)0xC0) ;
+ //bb.put((byte)0x80) ;
+ }
+ else if ( ch <= 0x07FF )
+ {
+ // 11 bits : 110yyyyy 10xxxxxx
+ // int x1 = ( ((ch>>(11-5))&0x7) | 0xC0 ) ; outputBytes(out, x1, 2, ch) ; return ;
+ int x1 = ( ((ch>>(11-5))&0x01F ) | 0xC0 ) ;
+ int x2 = ( (ch&0x3F) | 0x80 ) ;
+ bb.put((byte)x1) ;
+ bb.put((byte)x2) ;
+ }
+ else if ( ch <= 0xFFFF )
+ {
+ // 16 bits : 1110aaaa 10bbbbbb 10cccccc
+ // int x1 = ( ((ch>>(16-4))&0x7) | 0xE0 ) ; outputBytes(out, x1, 3, ch) ; return ;
+ int x1 = ( ((ch>>(16-4))&0x0F) | 0xE0 ) ;
+ int x2 = ( ((ch>>6)&0x3F) | 0x80 ) ;
+ int x3 = ( (ch&0x3F) | 0x80 ) ;
+ bb.put((byte)x1) ;
+ bb.put((byte)x2) ;
+ bb.put((byte)x3) ;
+ }
+ // if ( Character.isDefined(ch) )
+ // throw new AtlasException("not a character") ;
+ //if ( true ) throw new InternalErrorException("Valid code point for Java but not encodable") ;
+ // Not java, where chars are 16 bit.
+ else if ( ch <= 0x1FFFFF )
+ {
+ // 21 bits : 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ int x1 = ( ((ch>>(21-3))&0x7) | 0xF0 ) ;
+ outputBytes(bb, x1, 4, ch) ;
+ }
+ else if ( ch <= 0x3FFFFFF )
+ {
+ // 26 bits : 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+ int x1 = ( ((ch>>(26-2))&0x3) | 0xF8 ) ;
+ outputBytes(bb, x1, 5, ch) ;
+ }
+ else if ( ch <= 0x7FFFFFFF )
+ {
+ // 32 bits : 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+ int x1 = ( ((ch>>(32-1))&0x1) | 0xFC ) ;
+ outputBytes(bb, x1, 6, ch) ;
+ }
+ }
+ //int bytesFinish = bb.position() ;
+ }
+
+ private static void fromCharsArray(char[] array, byte[] array2)
+ {
+ throw new NotImplemented() ;
+ }
+
+ public static void fromChars(CharSequence cs, ByteBuffer bb)
+ {
+ fromChars(CharBuffer.wrap(cs), bb) ;
+ }
+
+ private static int readMultiBytes(ByteBuffer input, int start, int len)
+ {
+ // We have already read one byte.
+ if ( input.remaining() < (len-1) )
+ exception("Premature end to UTF-8 sequence at end of input") ;
+ int x = start ;
+ for ( int i = 0 ; i < len-1 ; i++ )
+ {
+ int x2 = input.get() ;
+ if ( (x2 & 0xC0) != 0x80 )
+ exception("Illegal UTF-8 processing character: 0x%04X",x2) ;
+ // 6 bits of x2
+ x = (x << 6) | (x2 & 0x3F);
+ }
+ return x ;
+ }
+
+ /** Put bytes to the output ByteBuffer for charcater ch.
+ * The first byte is in x1 and already has the needed bits set.
+ */
+ private static void outputBytes(ByteBuffer bb, int x1, int byteLength, int ch)
+ {
+ bb.put((byte)x1) ;
+ byteLength-- ; // remaining bytes
+ for ( int i = 0 ; i < byteLength ; i++ )
+ {
+ // 6 Bits, loop from high to low
+ int shift = 6*(byteLength-i-1) ;
+ int x = (ch>>shift) & 0x3F ;
+ x = x | 0x80 ; // 10xxxxxx
+ bb.put((byte)x) ;
+ }
+ }
+
+ // Does not return
+ private static void exception(String fmt, Object ...args)
+ {
+ String str = String.format(fmt,args) ;
+ IO.exception(new IOException(str)) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/BufferingWriter.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/BufferingWriter.java b/jena-base/src/main/java/org/apache/jena/atlas/io/BufferingWriter.java
new file mode 100644
index 0000000..b17e930
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/BufferingWriter.java
@@ -0,0 +1,180 @@
+/*
+ * 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.io ;
+
+import java.io.IOException ;
+import java.io.Writer ;
+
+import org.apache.jena.atlas.io.IO ;
+
+/**
+ * A buffering writer. Like BufferedWriter but with no synchronization. A
+ * "synchronized" per character can be expensive.
+ * <p>
+ * The standard java.io classes have hidden synchronization so in some very
+ * critical situations, this can be expensive.
+ * </p>
+ * This class is not thread safe.
+ */
+
+public final class BufferingWriter extends Writer {
+ // Default sizes
+ private static final int SIZE = 8 * 1024 ; // Unit size in bytes.
+ private static final int BLOB_SIZE = SIZE / 2 ; // Large object size,
+ // worse case, bytes
+ // Sizes for this instance
+ private final int blockSize ;
+ private final int blobSize ;
+
+ private char[] buffer = new char[SIZE] ;
+ private int idx = 0 ;
+ private Writer out ;
+
+ /** Create a buffering writer */
+ public BufferingWriter(Writer dest) {
+ this(dest, SIZE, BLOB_SIZE) ;
+ }
+
+ /** Create a buffering writer */
+ public BufferingWriter(Writer dest, int size) {
+ this(dest, size, size/2) ;
+ }
+
+ /** Create a buffering writer */
+ public BufferingWriter(Writer dest, int size, int blobSize) {
+ this.out = dest ;
+ this.blockSize = size ;
+ this.blobSize = blobSize ;
+ }
+
+ /**
+ * Output a string
+ * @param string Characters
+ */
+ public void output(String string) {
+ output(string, 0, string.length()) ;
+ }
+
+ /**
+ * Output a string
+ *
+ * @param string Characters
+ * @param off Starting point in the string
+ * @param length Length
+ */
+ public void output(String string, int off, int length) {
+ boolean largeBlob = (length > blobSize) ;
+
+ // There is no space or too big
+ if ( largeBlob || (blockSize - idx) < length )
+ flushBuffer() ;
+ // If too big, do directly.
+ if ( largeBlob /* too big */) {
+ try { out.write(string, off, length) ; }
+ catch (IOException ex) { IO.exception(ex) ; }
+ return ;
+ }
+ int n = string.length() ;
+ string.getChars(off, (n + off), buffer, idx) ;
+ idx += n ;
+ }
+
+ /** Output an array of characters */
+ public void output(char chars[]) {
+ output(chars, 0, chars.length) ;
+ }
+
+ /**
+ * Output an array of characters
+ *
+ * @param chars Characters
+ * @param start Start
+ * @param length Length
+ */
+ public void output(char chars[], int start, int length) {
+ boolean largeBlob = (length > blobSize) ;
+
+ // There is no space or too big
+ if ( largeBlob || (blockSize - idx) < length )
+ flushBuffer() ;
+ // If too big, do directly.
+ if ( largeBlob /* too big */) {
+ try { out.write(chars) ; }
+ catch (IOException ex) { IO.exception(ex) ; }
+ return ;
+ }
+ System.arraycopy(chars, start, buffer, idx, length) ;
+ idx += length ;
+ }
+
+ /** Output a single character */
+ public void output(char ch) {
+ if ( blockSize == idx )
+ flushBuffer() ;
+ buffer[idx++] = ch ;
+ }
+
+ private void flushBuffer() {
+ if ( idx > 0 ) {
+ try { out.write(buffer, 0, idx) ; }
+ catch (IOException ex) { IO.exception(ex) ; }
+ idx = 0 ;
+ }
+
+ }
+
+ // ---- Writer
+
+ @Override
+ public void close() {
+ flushBuffer() ;
+ IO.close(out) ;
+ }
+
+ @Override
+ public void flush() {
+ flushBuffer() ;
+ IO.flush(out) ;
+ }
+
+ @Override
+ public void write(char[] cbuf, int off, int len) throws IOException {
+ output(cbuf, off, len) ;
+ }
+
+ @Override
+ public void write(char[] cbuf) throws IOException {
+ write(cbuf, 0, cbuf.length) ;
+ }
+
+ @Override
+ public void write(String string, int off, int len) throws IOException {
+ output(string, off, len) ;
+ }
+
+ @Override
+ public void write(String string) throws IOException {
+ output(string, 0, string.length()) ;
+ }
+
+ @Override
+ public void write(int ch) throws IOException {
+ output((char)ch) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/CharStream.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/CharStream.java b/jena-base/src/main/java/org/apache/jena/atlas/io/CharStream.java
new file mode 100644
index 0000000..f066843
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/CharStream.java
@@ -0,0 +1,31 @@
+/*
+ * 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.io;
+
+
+/** A simplifed reader interface without IOExceptions.
+ * And it's an interface, not an abstract class
+ */
+public interface CharStream
+{
+ public int advance() ;
+
+ /** Close the stream - different name from java.io.Reader.close */
+ public void closeStream() ;
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamBasic.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamBasic.java b/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamBasic.java
new file mode 100644
index 0000000..27416d9
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamBasic.java
@@ -0,0 +1,58 @@
+/*
+ * 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.io;
+
+import java.io.IOException ;
+import java.io.Reader ;
+
+/** A PeekReaderSource that does no buffering - just wraps a reader. */
+public final class CharStreamBasic extends CharStreamReader
+{
+ private Reader reader ;
+
+ CharStreamBasic(Reader reader)
+ {
+ this.reader = reader ;
+ }
+
+ @Override
+ public int advance()
+ {
+ try
+ {
+ return reader.read() ;
+ } catch (IOException ex)
+ {
+ ex.printStackTrace();
+ return -1 ;
+ }
+ }
+
+ @Override
+ public void closeStream()
+ {
+ try
+ {
+ reader.close() ;
+ } catch (IOException ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamBuffered.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamBuffered.java b/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamBuffered.java
new file mode 100644
index 0000000..519dc36
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamBuffered.java
@@ -0,0 +1,166 @@
+/*
+ * 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.io;
+
+import static org.apache.jena.atlas.io.IO.EOF ;
+
+import java.io.IOException ;
+import java.io.Reader ;
+
+/** Buffering reader without the (hidden) sync overhead in BufferedReader
+ *
+ * @see java.io.BufferedReader
+ */
+
+
+public final class CharStreamBuffered extends CharStreamReader
+{
+ /*package*/ static final int CB_SIZE = 128 * 1024 ;
+
+ private final char[] chars ; // CharBuffer?
+ private int buffLen = 0 ;
+ private int idx = 0 ;
+
+ private final Source source;
+
+ public CharStreamBuffered(Reader r)
+ { this(r, CB_SIZE) ; }
+
+ /**
+ * @param r
+ * @param buffSize
+ */
+ public CharStreamBuffered(Reader r, int buffSize)
+ {
+ super() ;
+ source = new SourceReader(r) ;
+ chars = new char[buffSize] ;
+ }
+
+ // Local adapter/encapsulation
+ private interface Source
+ {
+ int fill(char[] array) ;
+ void close() ;
+ }
+
+ static final class SourceReader implements Source
+ {
+ final Reader reader ;
+ SourceReader(Reader r) { reader = r ; }
+
+ @Override
+ public void close()
+ {
+ try { reader.close() ; } catch (IOException ex) { IO.exception(ex) ; }
+ }
+
+ @Override
+ public int fill(char[] array)
+ {
+ try { return reader.read(array) ; } catch (IOException ex) { IO.exception(ex) ; return -1 ; }
+ }
+ }
+
+// /** Faster?? for ASCII */
+// static final class SourceASCII implements Source
+// {
+// final InputStream input ;
+// SourceASCII(InputStream r) { input = r ; }
+// public void close()
+// { try { input.close() ; } catch (IOException ex) { exception(ex) ; } }
+//
+// public final int fill(char[] array)
+// {
+// try {
+// // Recycle.
+// byte[] buff = new byte[array.length] ;
+// int len = input.read(buff) ;
+// for ( int i = 0 ; i < len ; i++ )
+// {
+// byte b = buff[i] ;
+// if ( b < 0 )
+// throw new AtlasException("Illegal ASCII charcater: "+b) ;
+// array[i] = (char)b ;
+// }
+// return len ;
+// } catch (IOException ex) { exception(ex) ; return -1 ; }
+// }
+// }
+//
+// static final class SourceChannel implements Source
+// {
+// final ReadableByteChannel channel ;
+// CharsetDecoder decoder = Chars.createDecoder() ;
+// SourceChannel(ReadableByteChannel r) { channel = r ; }
+//
+// @Override
+// public void close()
+// {
+// try { channel.close() ; } catch (IOException ex) { exception(ex) ; }
+// }
+//
+// @Override
+// public int fill(char[] array)
+// {
+// // Encoding foo.
+//// Bytes
+////
+//// ByteBuffer b = ByteBuffer.wrap(null) ;
+////
+//// try { return channel.read(null).read(array) ; } catch (IOException ex) { exception(ex) ; return -1 ; }
+// return -1 ;
+// }
+// }
+
+ @Override
+ public final int advance()
+ {
+ if ( idx >= buffLen )
+ // Points outside the array. Refill it
+ fillArray() ;
+
+ // Advance one character.
+ if ( buffLen >= 0 )
+ {
+ char ch = chars[idx] ;
+ // Advance the lookahead character
+ idx++ ;
+ return ch ;
+ }
+ else
+ // Buffer empty, end of stream.
+ return EOF ;
+ }
+
+ private int fillArray()
+ {
+ int x = source.fill(chars) ;
+ idx = 0 ;
+ buffLen = x ; // Maybe -1
+ return x ;
+ }
+
+
+ @Override
+ public void closeStream()
+ {
+ source.close() ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamReader.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamReader.java b/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamReader.java
new file mode 100644
index 0000000..d7dce11
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamReader.java
@@ -0,0 +1,56 @@
+/*
+ * 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.io;
+
+import java.io.IOException ;
+import java.io.Reader ;
+
+/** Machinary to add Reader functionality to a CharStream */
+public abstract class CharStreamReader extends Reader implements CharStream
+{
+ @Override
+ public int read(char[] cbuf, int off, int len) throws IOException
+ {
+ for ( int i = 0 ; i < len ; i++ )
+ {
+ int x = advance() ;
+ if ( x == -1 )
+ return (i==0)? -1 : i ;
+ cbuf[i] = (char)x ;
+ }
+ return len ;
+ }
+
+ @Override
+ public int read() throws IOException
+ {
+ return advance() ;
+ }
+
+
+ @Override
+ public void close() throws IOException
+ { closeStream() ; }
+
+ @Override
+ public abstract int advance() ;
+
+ @Override
+ public abstract void closeStream() ;
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamSequence.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamSequence.java b/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamSequence.java
new file mode 100644
index 0000000..c0e9f40
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamSequence.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.atlas.io;
+import static org.apache.jena.atlas.io.IO.EOF ;
+
+public final class CharStreamSequence implements CharStream
+{
+ private CharSequence string ;
+ // Next character.
+ private int idx ;
+
+ public CharStreamSequence(CharSequence string)
+ {
+ this.string = string ;
+ this.idx = 0 ;
+ }
+
+ @Override
+ public int advance()
+ {
+ if ( idx >= string.length() )
+ return EOF ;
+ return string.charAt(idx++);
+ }
+
+ @Override
+ public void closeStream()
+ {
+ string = null ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/IO.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/IO.java b/jena-base/src/main/java/org/apache/jena/atlas/io/IO.java
new file mode 100644
index 0000000..ac312e8
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/IO.java
@@ -0,0 +1,325 @@
+/*
+ * 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.io;
+
+import java.io.* ;
+import java.nio.charset.Charset ;
+import java.nio.charset.StandardCharsets ;
+import java.util.zip.GZIPInputStream ;
+import java.util.zip.GZIPOutputStream ;
+
+import org.apache.jena.atlas.RuntimeIOException ;
+import org.apache.jena.atlas.lib.IRILib ;
+
+public class IO
+{
+ public static final int EOF = -1 ;
+ public static final int UNSET = -2 ;
+
+ private static Charset utf8 = StandardCharsets.UTF_8 ;
+ private static Charset ascii = StandardCharsets.US_ASCII ;
+
+ /** Open an input stream to a file.
+ * If the filename is null or "-", return System.in
+ * If the filename ends in .gz, wrap in GZIPInputStream
+ */
+ static public InputStream openFile(String filename) {
+ try {
+ return openFileEx(filename) ;
+ }
+ catch (Exception ex) { throw new RuntimeIOException(ex) ; }
+ }
+
+ /** Open an input stream to a file; do not mask IOExceptions.
+ * If the filename is null or "-", return System.in
+ * If the filename ends in .gz, wrap in GZIPInputStream
+ * @param filename
+ * @throws FileNotFoundException
+ * @throws IOException
+ */
+ static public InputStream openFileEx(String filename) throws IOException, FileNotFoundException {
+ if ( filename == null || filename.equals("-") )
+ return System.in ;
+ if ( filename.startsWith("file:") )
+ {
+ filename = filename.substring("file:".length()) ;
+ filename = IRILib.decode(filename) ;
+ }
+ InputStream in = new FileInputStream(filename) ;
+ if ( filename.endsWith(".gz") )
+ in = new GZIPInputStream(in) ;
+ return in ;
+ }
+
+ /** Open a UTF8 Reader for a file.
+ * If the filename is null or "-", use System.in
+ * If the filename ends in .gz, use GZIPInputStream
+ */
+ static public Reader openFileUTF8(String filename) { return openFileReader(filename, utf8) ; }
+
+ /** Open an ASCII Reader for a file.
+ * If the filename is null or "-", use System.in
+ * If the filename ends in .gz, use GZIPInputStream
+ */
+ static public Reader openFileASCII(String filename) { return openFileReader(filename, ascii) ; }
+
+ private static Reader openFileReader(String filename, Charset charset)
+ {
+ InputStream in = openFile(filename) ;
+ return new InputStreamReader(in, charset) ;
+ }
+
+ /** Create an unbuffered reader that uses UTF-8 encoding */
+ static public Reader asUTF8(InputStream in)
+ {
+ return new InputStreamReader(in, utf8.newDecoder());
+ }
+
+ /** Create a unbuffered reader that uses ASCII encoding */
+ static public Reader asASCII(InputStream in)
+ {
+ return new InputStreamReader(in, ascii.newDecoder());
+ }
+
+ /** Create an buffered reader that uses UTF-8 encoding */
+ static public BufferedReader asBufferedUTF8(InputStream in) {
+ return new BufferedReader(asUTF8(in)) ;
+ }
+
+ /** Create a writer that uses UTF-8 encoding */
+ static public Writer asUTF8(OutputStream out) {
+ return new OutputStreamWriter(out, utf8.newEncoder());
+ }
+
+ /** Create a writer that uses ASCII encoding */
+ static public Writer asASCII(OutputStream out) {
+ return new OutputStreamWriter(out, ascii.newEncoder());
+ }
+
+ /** Create a writer that uses UTF-8 encoding and is buffered. */
+ static public Writer asBufferedUTF8(OutputStream out) {
+ Writer w = new OutputStreamWriter(out, utf8.newEncoder());
+ return new BufferingWriter(w) ;
+ }
+
+ /** Open a file for output - may include adding gzip processing. */
+ static public OutputStream openOutputFile(String filename)
+ {
+ try {
+ return openOutputFileEx(filename) ;
+ }
+ catch (IOException ex) { IO.exception(ex) ; return null ; }
+ }
+
+ /** Open an input stream to a file; do not mask IOExceptions.
+ * If the filename ends in .gz, wrap in GZIPOutputStream
+ * @param filename
+ * @throws FileNotFoundException If the output can't be opened.
+ * @throws IOException for bad gzip encoded data
+ */
+ static public OutputStream openOutputFileEx(String filename) throws FileNotFoundException,IOException
+ {
+ if ( filename == null || filename.equals("-") )
+ return System.out ;
+ if ( filename.startsWith("file:") )
+ {
+ filename = filename.substring("file:".length()) ;
+ filename = IRILib.decode(filename) ;
+ }
+ OutputStream out = new FileOutputStream(filename) ;
+ if ( filename.endsWith(".gz") )
+ out = new GZIPOutputStream(out) ;
+ return out ;
+ }
+
+ /** Wrap in a general writer interface */
+ static public AWriter wrap(Writer w) {
+ return Writer2.wrap(w) ;
+ }
+
+ /** Wrap in a general writer interface */
+ static public AWriter wrapUTF8(OutputStream out) { return wrap(asUTF8(out)) ; }
+
+ /** Wrap in a general writer interface */
+ static public AWriter wrapASCII(OutputStream out) { return wrap(asASCII(out)) ; }
+
+ /** Create a print writer that uses UTF-8 encoding */
+ static public PrintWriter asPrintWriterUTF8(OutputStream out) {
+ return new PrintWriter(asUTF8(out));
+ }
+
+ public static void close(org.apache.jena.atlas.lib.Closeable resource) {
+ resource.close() ;
+ }
+
+ public static void closeSilent(org.apache.jena.atlas.lib.Closeable resource) {
+ try { resource.close(); } catch (Exception ex) { }
+ }
+
+ public static void close(java.io.Closeable resource) {
+ if ( resource == null )
+ return ;
+ try { resource.close(); } catch (IOException ex) { exception(ex) ; }
+ }
+
+ public static void closeSilent(java.io.Closeable resource) {
+ if ( resource == null )
+ return ;
+ try { resource.close(); } catch (IOException ex) { }
+ }
+
+ public static void close(AWriter resource) {
+ if ( resource == null )
+ return ;
+ resource.close();
+ }
+
+ public static void closeSilent(AWriter resource) {
+ if ( resource == null )
+ return ;
+ try { resource.close(); } catch (Exception ex) { }
+ }
+
+ public static void close(IndentedWriter resource) {
+ if ( resource == null )
+ return ;
+ resource.close();
+ }
+
+ public static void closeSilent(IndentedWriter resource) {
+ if ( resource == null )
+ return ;
+ try { resource.close(); } catch (Exception ex) { }
+ }
+
+ public static void exception(IOException ex) {
+ throw new RuntimeIOException(ex) ;
+ }
+
+ public static void exception(String msg, IOException ex) {
+ throw new RuntimeIOException(msg, ex) ;
+ }
+
+ public static void flush(OutputStream out) {
+ if ( out == null )
+ return ;
+ try { out.flush(); } catch (IOException ex) { exception(ex) ; }
+ }
+
+ public static void flush(Writer out) {
+ if ( out == null )
+ return ;
+ try { out.flush(); } catch (IOException ex) { exception(ex) ; }
+ }
+
+ public static void flush(AWriter out) {
+ if ( out == null )
+ return ;
+ out.flush();
+ }
+
+ private static final int BUFFER_SIZE = 32*1024 ;
+
+ public static byte[] readWholeFile(InputStream in) {
+ try(ByteArrayOutputStream out = new ByteArrayOutputStream(BUFFER_SIZE)) {
+ byte buff[] = new byte[BUFFER_SIZE] ;
+ while (true) {
+ int l = in.read(buff) ;
+ if ( l <= 0 )
+ break ;
+ out.write(buff, 0, l) ;
+ }
+ return out.toByteArray() ;
+ }
+ catch (IOException ex) {
+ exception(ex) ;
+ return null ;
+ }
+ }
+
+ /** Read a whole file as UTF-8
+ * @param filename
+ * @return String
+ * @throws IOException
+ */
+
+ public static String readWholeFileAsUTF8(String filename) throws IOException {
+ try ( InputStream in = new FileInputStream(filename) ) {
+ return readWholeFileAsUTF8(in) ;
+ }
+ }
+
+ /** Read a whole stream as UTF-8
+ *
+ * @param in InputStream to be read
+ * @return String
+ * @throws IOException
+ */
+ public static String readWholeFileAsUTF8(InputStream in) throws IOException {
+ // Don't buffer - we're going to read in large chunks anyway
+ try ( Reader r = asUTF8(in) ) {
+ return readWholeFileAsUTF8(r) ;
+ }
+ }
+
+ /** Read a whole file as UTF-8
+ *
+ * @param r
+ * @return String The whole file
+ * @throws IOException
+ */
+
+ // Private worker as we are trying to force UTF-8.
+ private static String readWholeFileAsUTF8(Reader r) throws IOException {
+ try(StringWriter sw = new StringWriter(BUFFER_SIZE)) {
+ char buff[] = new char[BUFFER_SIZE];
+ for (;;)
+ {
+ int l = r.read(buff);
+ if (l < 0)
+ break;
+ sw.write(buff, 0, l);
+ }
+ return sw.toString();
+ }
+ }
+
+ public static String uniqueFilename(String directory, String base, String ext) {
+ File d = new File(directory) ;
+ if ( !d.exists() )
+ throw new IllegalArgumentException("Not found: " + directory) ;
+ try {
+ String fn0 = d.getCanonicalPath() + File.separator + base ;
+ String fn = fn0 ;
+ int x = 1 ;
+ while (true) {
+ if ( ext != null )
+ fn = fn + "."+ext ;
+ File f = new File(fn) ;
+ if ( ! f.exists() )
+ return fn ;
+ fn = fn0 + "-" + (x++) ;
+ }
+ } catch (IOException e) {
+ IO.exception(e) ;
+ return null ;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/InStreamASCII.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/InStreamASCII.java b/jena-base/src/main/java/org/apache/jena/atlas/io/InStreamASCII.java
new file mode 100644
index 0000000..049449c
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/InStreamASCII.java
@@ -0,0 +1,89 @@
+/*
+ * 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.io;
+
+import java.io.IOException ;
+import java.io.InputStream ;
+import java.io.Reader ;
+
+import org.apache.jena.atlas.AtlasException ;
+
+/** Fast and streaming.
+ */
+public final class InStreamASCII extends Reader implements CharStream
+{
+ private InputStreamBuffered input ;
+ private long count = 0 ;
+
+ public InStreamASCII(InputStream in)
+ {
+ if ( in instanceof InputStreamBuffered )
+ {
+ input = (InputStreamBuffered)in ;
+ return ;
+ }
+ input = new InputStreamBuffered(in) ;
+ }
+
+ public InStreamASCII(InputStreamBuffered in) { input = in ; }
+
+ @Override
+ public boolean ready() throws IOException
+ {
+ return input.available() > 0 ;
+ }
+
+ @Override
+ public void close() throws IOException
+ { input.close() ; }
+
+ @Override
+ public void closeStream()
+ { IO.close(input) ; }
+
+ @Override
+ public int read(char[] cbuf, int off, int len) throws IOException
+ {
+ for ( int i = off ; i < off+len ; i++ )
+ {
+ int x = read() ;
+ if ( x == -1 )
+ {
+ if ( i == off )
+ return -1 ;
+ return (i-off) ;
+ }
+ if ( x > 128 )
+ throw new AtlasException("Illegal ASCII character : "+x) ;
+ cbuf[i] = (char)x ;
+ }
+ return len ;
+ }
+
+ @Override
+ public int read() throws IOException
+ { return advance() ; }
+
+ @Override
+ public int advance()
+ {
+ count++ ;
+ return input.advance() ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/InStreamUTF8.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/InStreamUTF8.java b/jena-base/src/main/java/org/apache/jena/atlas/io/InStreamUTF8.java
new file mode 100644
index 0000000..5903882
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/InStreamUTF8.java
@@ -0,0 +1,254 @@
+/*
+ * 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.io;
+
+import java.io.ByteArrayInputStream ;
+import java.io.IOException ;
+import java.io.InputStream ;
+import java.io.Reader ;
+
+import org.apache.jena.atlas.AtlasException ;
+
+/** Fast and streaming UTF-8 */
+public final class InStreamUTF8 extends Reader implements CharStream
+{
+ // TODO Add line and col counts.
+ // See arq.utf8.
+ // TODO Better ready()/available() in InputStreamBuffered
+
+ // The standard Java way of doing this is via charset decoders.
+ // One small disadvantage is that bad UTF-8 does not get flagged as to
+ // the byte position of the error.
+
+ // This class collects knowledge of how UTF-8 encoding works;
+ // the Java classes are usually slightly faster compared to using
+ // this class with an InputStreamBuffered but the difference is small.
+ // This class generated meaningful error messages (when line/col added).
+
+ // The Java classes copy-convert a byte buffer into a char buffer.
+ // Sometimes, for example in a parser, this isn't a convenient model
+ // because the app is looking one character at a time and accumulating
+ // the chars until it sees the end of a token of arbitrary length
+ // or processes escape sequences.
+ //
+ // The app might use a StringBuilder so the bytes get copied into
+ // a char buffer and out again. Instead, this code assumes the
+ // app is in charge of that.
+
+ // UTF-8 (UTF-16) is different from other character sets because
+ // the relationship with Java's internal character representation is
+ // arithmetic, not a character mapping.
+
+ // Todo: chars > 16 bits -> surrogate pairs.
+
+ /*
+ * http://en.wikipedia.org/wiki/UTF-8
+ * http://tools.ietf.org/html/rfc3629
+ * http://www.ietf.org/rfc/rfc3629.txt
+ *
+ * Unicode Byte1 Byte2 Byte3 Byte4
+ * U+0000–U+007F 0 to 127 0xxxxxxx
+ * U+0080–U+07FF 128 to 2,047 110yyyxx 10xxxxxx
+ * U+0800–U+FFFF 2,048 to 65,535 1110yyyy 10yyyyxx 10xxxxxx
+ * U+10000–U+10FFFF 65,536 to 1,114,111 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx
+ *
+ * Restricted cases (RFC 3629)
+ * 11110101-11110111 F5-F7 245-247 start of 4-byte sequence for codepoint above 10FFFF
+ * 11111000-11111011 F8-FB 248-251 start of 5-byte sequence
+ * 11111100-11111101 FC-FD 252-253 start of 6-byte sequence
+ *
+ * Illegal:
+ * 11000000-11000001 C0-C1 192-193 Overlong encoding: start of a 2-byte sequence, but code point <= 127
+ * 11111110-11111111 FE-FF 254-255 Invalid: not defined by original UTF-8 specification
+ */
+
+ // There is some sort of stream decoder backing the Sun implementation
+ // of CharsetDecoder (sun.io.StreamDecoder) but it's not on all platforms
+ // I want a known decoder specifically for UTF8
+
+ private InputStreamBuffered input ;
+ //private long count = 0 ;
+
+ public InStreamUTF8(InputStream in)
+ {
+ if ( in instanceof InputStreamBuffered )
+ {
+ input = (InputStreamBuffered)in ;
+ return ;
+ }
+ input = new InputStreamBuffered(in) ;
+ }
+
+ public InStreamUTF8(InputStreamBuffered in) { input = in ; }
+
+
+ @Override
+ public boolean ready() throws IOException
+ {
+ return input.available() > 0 ;
+ }
+
+ @Override
+ public void close() throws IOException
+ { input.close() ; }
+
+ @Override
+ public void closeStream()
+ { IO.close(input) ; }
+
+ @Override
+ public int read(char[] cbuf, int off, int len) throws IOException
+ {
+ // Doing this on a block of bytes may be faster.
+ for ( int i = off ; i < off+len ; i++ )
+ {
+ int x = read() ;
+ if ( x == -1 )
+ {
+ if ( i == off )
+ return -1 ;
+ return (i-off) ;
+ }
+ cbuf[i] = (char)x ;
+ }
+ return len ;
+ }
+
+ @Override
+ public final int read() throws IOException
+ {
+ int ch = advance(input) ;
+ //if ( ! Character.isDefined(ch) ) throw new AtlasException(String.format("Undefined codepoint: 0x%04X", ch)) ;
+ return ch ;
+ }
+
+
+ /** Next codepoint, given the first byte of any UTF-8 byte sequence is already known.
+ * Not necessarily a valid char (this function can be used a straight UTF8 decoder
+ */
+ @Override
+ public final int advance()
+ { return advance(input) ; }
+
+ /** Next codepoint */
+ public static final int advance(InputStreamBuffered input)
+ {
+ int x = input.advance() ;
+ if ( x == -1 ) return -1 ;
+ return advance(input, x) ;
+ }
+
+ /** Next codepoint, given the first byte of any UTF-8 byte sequence is already known.
+ * Not necessarily a valid char (this function can be used a straight UTF8 decoder
+ */
+
+ public static final int advance(InputStreamBuffered input, int x)
+ {
+ //count++ ;
+ // Fastpath
+ if ( x == -1 || x <= 127 )
+ {
+ //count++ ;
+ return x ;
+ }
+
+ // 10 => extension byte
+ // 110..... => 2 bytes
+ if ( (x & 0xE0) == 0xC0 )
+ {
+ int ch = readMultiBytes(input, x & 0x1F, 2) ;
+ // count += 2 ;
+ return ch ;
+
+ }
+ // 1110.... => 3 bytes : 16 bits : not outside 16bit chars
+ if ( (x & 0xF0) == 0xE0 )
+ {
+ int ch = readMultiBytes(input, x & 0x0F, 3) ;
+ // count += 3 ;
+ //if ( ! Character.isDefined(ch) ) throw new AtlasException(String.format("Undefined codepoint: 0x%04X", ch)) ;
+ return ch ;
+ }
+
+ // Looking like 4 byte charcater.
+ int ch = -2 ;
+ // 11110zzz => 4 bytes.
+ if ( (x & 0xF8) == 0xF0 )
+ {
+ ch = readMultiBytes(input, x & 0x08, 4) ;
+ // Opsp - need two returns. Character.toChars(ch, chars, 0) ;
+ // count += 4 ;
+ }
+
+ else
+ IO.exception(new IOException("Illegal UTF-8: "+x)) ;
+
+ // This test will go off. We're processing a 4 byte sequence but Java only supports 16 bit chars.
+ if ( ch > Character.MAX_VALUE )
+ throw new AtlasException("Out of range character (must use a surrogate pair)") ;
+ if ( ! Character.isDefined(ch) ) throw new AtlasException(String.format("Undefined codepoint: 0x%04X", ch)) ;
+ return ch ;
+ }
+
+ private static int readMultiBytes(InputStreamBuffered input, int start, int len) //throws IOException
+ {
+ //System.out.print(" -("+len+")") ; p(start) ;
+
+ int x = start ;
+ for ( int i = 0 ; i < len-1 ; i++ )
+ {
+ int x2 = input.advance() ;
+ if ( x2 == -1 )
+ throw new AtlasException("Premature end to UTF-8 sequence at end of input") ;
+
+ if ( (x2 & 0xC0) != 0x80 )
+ //throw new AtlasException("Illegal UTF-8 processing character "+count+": "+x2) ;
+ throw new AtlasException(String.format("Illegal UTF-8 processing character: 0x%04X",x2)) ;
+ // 6 bits of x2
+ x = (x << 6) | (x2 & 0x3F);
+ }
+ return x ;
+ }
+
+ private static void p(int ch)
+ {
+ System.out.printf(" %02X", ch) ;
+ if ( ch == -1 )
+ System.out.println();
+ }
+
+ public static String decode(byte[] bytes)
+ {
+ try
+ {
+ char[] chars = new char[bytes.length] ;
+ InputStream in = new ByteArrayInputStream(bytes) ;
+ StringBuilder buff = new StringBuilder() ;
+ Reader r = new InStreamUTF8(in) ;
+ int len ;
+ len = r.read(chars) ;
+ IO.close(r) ;
+ return new String(chars, 0, len) ;
+ } catch (IOException ex)
+ {
+ IO.exception(ex) ;
+ return null ;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedLineBuffer.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedLineBuffer.java b/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedLineBuffer.java
new file mode 100644
index 0000000..7c7b5f5
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedLineBuffer.java
@@ -0,0 +1,50 @@
+/*
+ * 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.io;
+
+import java.io.StringWriter ;
+
+/** IndentLineBuffer is a buffer that records an indent level
+ * and uses that to insert a prefix at each line.
+ * It can also insert line numbers at the beginning of lines.
+ */
+
+public class IndentedLineBuffer extends IndentedWriter
+{
+ StringWriter sw ;
+ public IndentedLineBuffer() { this(false) ; }
+
+ public IndentedLineBuffer(boolean withLineNumbers)
+ {
+ super(new StringWriter(), withLineNumbers) ;
+ sw = (StringWriter)super.out ;
+ }
+
+ public StringBuffer getBuffer() { return sw.getBuffer(); }
+
+ public String asString() { return sw.toString() ; }
+ @Override
+ public String toString() { return asString() ; }
+
+ // Names more usually used for a buffer.
+ public void append(String fmt, Object... args) { printf(fmt, args) ; }
+ public void append(char ch) { print(ch) ;}
+
+ public void clear() { sw.getBuffer().setLength(0) ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedWriter.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedWriter.java b/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedWriter.java
new file mode 100644
index 0000000..51414f9
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedWriter.java
@@ -0,0 +1,366 @@
+/*
+ * 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.io;
+import static java.lang.String.format ;
+
+import java.io.IOException ;
+import java.io.OutputStream ;
+import java.io.Writer ;
+
+import org.apache.jena.atlas.RuntimeIOException ;
+import org.apache.jena.atlas.lib.Closeable ;
+
+/** A writer that records what the current indentation level is, and
+ * uses that to insert a prefix at each line.
+ * It can also insert line numbers at the beginning of lines. */
+
+public class IndentedWriter extends AWriterBase implements AWriter, Closeable
+{
+ /** Stdout wrapped in an IndentedWriter - no line numbers */
+ public static final IndentedWriter stdout = new IndentedWriter(System.out) ;
+ /** Stderr wrapped in an IndentedWriter - no line numbers */
+ public static final IndentedWriter stderr = new IndentedWriter(System.err) ;
+
+ static {
+ stdout.setFlushOnNewline(true) ;
+ stderr.setFlushOnNewline(true) ;
+ }
+ // Note cases:if (!flatMode)
+ // 1/ incIndent - decIndent with no output should not cause any padding
+ // 2/ newline() then no text, then finish should not cause a line number.
+
+ protected Writer out = null ;
+
+ protected static final int INDENT = 2 ;
+ protected int unitIndent = INDENT ;
+ protected int currentIndent = 0 ;
+ protected int column = 0 ;
+ protected int row = 1 ;
+ protected boolean lineNumbers = false ;
+ protected boolean startingNewLine = true ;
+ private char padChar = ' ' ;
+ private String endOfLineMarker = null ; // Null mean none.
+ private String padString = null ;
+
+ protected boolean flatMode = false ;
+ private boolean flushOnNewline = false ;
+
+ private IndentedWriter() { this(System.out, false) ; }
+
+ /** Construct a UTF8 IndentedWriter around an OutputStream */
+ public IndentedWriter(OutputStream outStream) { this(outStream, false) ; }
+
+ /** Construct a UTF8 IndentedWriter around an OutputStream */
+ public IndentedWriter(OutputStream outStream, boolean withLineNumbers)
+ {
+ this(makeWriter(outStream), withLineNumbers) ;
+ }
+
+ private static Writer makeWriter(OutputStream out)
+ {
+ // return BufferingWriter.create(out) ;
+ return IO.asBufferedUTF8(out) ;
+ }
+
+ /** Using Writers directly is discouraged */
+ protected IndentedWriter(Writer writer) { this(writer, false) ; }
+
+ /** Using Writers directly is discouraged */
+ protected IndentedWriter(Writer writer, boolean withLineNumbers)
+ {
+ out = writer ;
+ lineNumbers = withLineNumbers ;
+ startingNewLine = true ;
+ }
+
+ @Override
+ public void print(String str)
+ {
+ if ( str == null )
+ str = "null" ;
+ if ( false )
+ {
+ // Don't check for embedded newlines.
+ write$(str) ;
+ return ;
+ }
+ for ( int i = 0 ; i < str.length() ; i++ )
+ printOneChar(str.charAt(i)) ;
+ }
+
+ @Override
+ public void printf(String formatStr, Object... args)
+ {
+ print(format(formatStr, args)) ;
+ }
+
+ @Override
+ public void print(char ch) { printOneChar(ch) ; }
+
+ @Override
+ public void println(String str) { print(str) ; newline() ; }
+ public void println(char ch) { print(ch) ; newline() ; }
+
+ @Override
+ public void println() { newline() ; }
+
+ @Override
+ public void print(char[] cbuf)
+ {
+ for ( char aCbuf : cbuf )
+ {
+ printOneChar( aCbuf );
+ }
+ }
+
+ /** Print a string N times */
+ public void print(String s, int n)
+ {
+ for ( int i = 0 ; i < n ; i++ ) print(s) ;
+ }
+
+ /** Print a char N times */
+ public void print(char ch, int n)
+ {
+ lineStart() ;
+ for ( int i = 0 ; i < n ; i++ ) printOneChar(ch) ;
+ }
+
+ private char lastChar = '\0' ;
+ // Worker
+ private void printOneChar(char ch)
+ {
+ // Turn \r\n into a single newline call.
+ // Assumes we don't get \r\r\n etc
+ if ( ch == '\n' && lastChar == '\r' )
+ {
+ lastChar = ch ;
+ return ;
+ }
+
+ lineStart() ;
+ lastChar = ch ;
+
+ // newline
+ if ( ch == '\n' || ch == '\r' )
+ {
+ newline() ;
+ return ;
+ }
+ write$(ch) ;
+ column += 1 ;
+ }
+
+ private void write$(char ch)
+ { try { out.write(ch) ; } catch (IOException ex) { throw new RuntimeIOException(ex) ; } }
+
+ private void write$(String s)
+ { try { out.write(s) ; } catch (IOException ex) { throw new RuntimeIOException(ex) ; } }
+
+ public void newline()
+ {
+ lineStart() ;
+
+ if ( endOfLineMarker != null )
+ print(endOfLineMarker) ;
+ if ( ! flatMode )
+ write$('\n') ;
+ startingNewLine = true ;
+ row++ ;
+ column = 0 ;
+ // Note that PrintWriters do not autoflush by default
+ // so if layered over a PrintWirter, need to flush that as well.
+ if (flushOnNewline) flush() ;
+ }
+
+ private boolean atStartOfLine() { return column <= currentIndent ; }
+
+ public void ensureStartOfLine()
+ {
+ if ( !atStartOfLine() )
+ newline() ;
+ }
+
+ @Override
+ public void close() { try { out.close(); } catch (IOException ex) {} }
+
+ @Override
+ public void flush() { try { out.flush(); } catch (IOException ex) {} }
+
+ /** Pad to the indent (if we are before it) */
+ public void pad()
+ {
+ if ( startingNewLine && currentIndent > 0 )
+ lineStart() ;
+ padInt() ;
+ }
+
+ /** Pad to a given number of columns EXCLUDING the indent.
+ *
+ * @param col Column number (first column is 1).
+ */
+ public void pad(int col) { pad(col, false) ; }
+
+ /** Pad to a given number of columns maybe including the indent.
+ *
+ * @param col Column number (first column is 1).
+ * @param absoluteColumn Whether to include the indent
+ */
+ public void pad(int col, boolean absoluteColumn )
+ {
+ // Make absolute
+ if ( !absoluteColumn )
+ col = col+currentIndent ;
+ int spaces = col - column ;
+ for ( int i = 0 ; i < spaces ; i++ )
+ {
+ write$(' ') ; // Always a space.
+ column++ ;
+ }
+ }
+
+
+ private void padInt()
+ {
+ if ( padString == null )
+ {
+ for ( int i = column ; i < currentIndent ; i++ )
+ {
+ write$(padChar) ;
+ column++ ;
+ }
+ }
+ else
+ {
+ for ( int i = column ; i < currentIndent ; i += padString.length() )
+ {
+ write$(padString) ;
+ column += padString.length() ;
+ }
+ }
+ }
+
+ /** Get row/line (counts from 1) */
+ public int getRow() { return row ; }
+ /** Get the absolute column.
+ * This is the location where the next charcter on the line will be printed.
+ * The IndentedWriter may not yet have padded to this place.
+ */
+ public int getCol() {
+ if ( currentIndent > column )
+ return currentIndent ;
+ return column ;
+ }
+
+ /** Get indent from the left hand edge */
+ public int getAbsoluteIndent() { return currentIndent ; }
+ /** Set indent from the left hand edge */
+ public void setAbsoluteIndent(int x) { currentIndent = x ; }
+
+ /** Position past current indent */
+ public int getCurrentOffset()
+ {
+ int x = getCol() - getAbsoluteIndent() ;
+ if ( x >= 0 )
+ return x ;
+ // At start of line somehow.
+ return 0 ;
+ }
+
+ public boolean hasLineNumbers()
+ {
+ return lineNumbers ;
+ }
+
+ public void setLineNumbers(boolean lineNumbers)
+ {
+ this.lineNumbers = lineNumbers ;
+ }
+
+ public String getEndOfLineMarker() { return endOfLineMarker ; }
+
+ /** Set the marker included at end of line - set to null for "none". Usually used for debugging. */
+ public void setEndOfLineMarker(String marker) { endOfLineMarker = marker ; }
+
+ /** Flat mode - print without NL, for a more compact representation - depends on caller */
+ public boolean inFlatMode() { return flatMode ; }
+ public void setFlatMode(boolean flatMode) { this.flatMode = flatMode ; }
+
+ /** Flush on newline **/
+ public boolean getFlushOnNewline() { return flushOnNewline; }
+ public void setFlushOnNewline(boolean flushOnNewline) { this.flushOnNewline = flushOnNewline; }
+
+ public char getPadChar() { return padChar ; }
+ public void setPadChar(char ch) { this.padChar = ch ; }
+ public String getPadString() { return padString ; }
+ public void setPadString(String str) { this.padString = str ; unitIndent = str.length(); }
+
+ public void incIndent() { incIndent(unitIndent) ; }
+ public void incIndent(int x)
+ {
+ currentIndent += x ;
+ }
+
+ public void decIndent() { decIndent(unitIndent) ; }
+ public void decIndent(int x)
+ {
+ currentIndent -= x ;
+ }
+
+ public void setUnitIndent(int x) { unitIndent = x ; }
+ public int getUnitIndent() { return unitIndent ; }
+ public boolean atLineStart() { return startingNewLine ; }
+
+ private void lineStart()
+ {
+ if ( flatMode )
+ {
+ if ( startingNewLine && row > 1 )
+ // Space between each line.
+ write$(' ') ;
+ startingNewLine = false ;
+ return ;
+ }
+
+ // Need to do its just before we append anything, not after a NL,
+ // so that a final blank does not cause a line number
+ if ( startingNewLine )
+ insertLineNumber() ;
+ padInt() ;
+ startingNewLine = false ;
+ }
+
+ private static int WidthLineNumber = 3 ;
+
+ private void insertLineNumber()
+ {
+ if ( ! lineNumbers )
+ return ;
+ String s = Integer.toString(row) ;
+ for ( int i = 0 ; i < WidthLineNumber-s.length() ; i++ )
+ write$(' ') ;
+ write$(s) ;
+ write$(' ') ;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Indent = %d : [%d, %d]", currentIndent, row, column) ;
+ }
+}
[7/9] jena git commit: Import of lib, io,
logging and iterator packages
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorArray.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorArray.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorArray.java
new file mode 100644
index 0000000..ee45935
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorArray.java
@@ -0,0 +1,92 @@
+/*
+ * 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.iterator;
+
+import java.util.Iterator ;
+import java.util.NoSuchElementException ;
+
+/** Iterator over a Java base array */
+public final class IteratorArray<T> implements Iterator<T>
+{
+ /** Iterator over all the array elements */
+ public static <T> IteratorArray<T> create(T[] array)
+ { return new IteratorArray<>(array, 0, array.length) ; }
+
+ /** Iterator over array elements from start (inclusive) to finish (exclusive) */
+ public static <T> IteratorArray<T> create(T[] array, int start, int finish)
+ { return new IteratorArray<>(array, start, finish) ; }
+
+ private int idx ;
+ private int finishIdx ;
+ private T[] array ;
+
+ private IteratorArray(T[] array, int start, int finish)
+ {
+ if ( start < 0 )
+ throw new IllegalArgumentException("Start: "+start) ;
+
+ if ( start > finish )
+ throw new IllegalArgumentException("Start >= finish: "+start+" >= "+finish) ;
+
+// Instead: truncate to array length
+// if ( finish > array.length )
+// throw new IllegalArgumentException("Finish outside array") ;
+//
+// Instead: immediate end iterator
+// if ( start >= array.length )
+// throw new IllegalArgumentException("Start outside array") ;
+
+ this.array = array ;
+ idx = start ;
+ finishIdx = finish ;
+ if ( idx < 0 )
+ idx = 0 ;
+ if ( finishIdx > array.length )
+ finishIdx = array.length ;
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+// if ( idx < 0 )
+// return false ;
+ if ( idx >= finishIdx )
+ return false ;
+ return true ;
+ }
+
+ public T current()
+ {
+ if ( idx >= finishIdx )
+ throw new NoSuchElementException() ;
+ return array[idx] ;
+ }
+
+ @Override
+ public T next()
+ {
+ if ( ! hasNext() )
+ throw new NoSuchElementException() ;
+ return array[idx++] ;
+ }
+
+ @Override
+ public void remove()
+ { throw new UnsupportedOperationException("ArrayIterator") ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorBlockingQueue.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorBlockingQueue.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorBlockingQueue.java
new file mode 100644
index 0000000..c11b262
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorBlockingQueue.java
@@ -0,0 +1,73 @@
+/*
+ * 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.iterator;
+
+import java.util.Iterator ;
+import java.util.NoSuchElementException ;
+import java.util.concurrent.BlockingQueue ;
+
+/** Iterator over a blocking queue until queue end seen */
+
+public class IteratorBlockingQueue<T> implements Iterator<T>
+{
+ private BlockingQueue<T> queue ;
+ private boolean finished = false ;
+ private T slot = null ;
+ private T endMarker ;
+
+ public IteratorBlockingQueue(BlockingQueue<T> queue, T endMarker) { this.queue = queue ; this.endMarker = endMarker ; }
+
+ @Override
+ public boolean hasNext()
+ {
+ if ( finished ) return false ;
+ if ( slot != null ) return true ;
+ try
+ {
+ slot = queue.take() ;
+ if ( slot == endMarker )
+ {
+ finished = true ;
+ slot = null ;
+ return false ;
+ }
+ return true ;
+
+ } catch (InterruptedException ex)
+ {
+ ex.printStackTrace();
+
+ }
+ return false ;
+ }
+
+ @Override
+ public T next()
+ {
+ if ( ! hasNext() )
+ throw new NoSuchElementException() ;
+ T item = slot ;
+ slot = null ;
+ return item ;
+ }
+
+ @Override
+ public void remove()
+ { throw new UnsupportedOperationException() ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorConcat.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorConcat.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorConcat.java
new file mode 100644
index 0000000..65e6430
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorConcat.java
@@ -0,0 +1,104 @@
+/*
+ * 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.iterator;
+
+import java.util.Iterator ;
+import java.util.List ;
+import java.util.NoSuchElementException ;
+
+import org.apache.jena.atlas.lib.DS ;
+
+/** Iterator of Iterators
+ * IteratorConcat is better when there are lots of iterators to be joined.
+ * IteratorCons is slightly better for two iterators.
+ */
+
+public class IteratorConcat<T> implements Iterator<T>
+{
+ private List<Iterator<T>> iterators = DS.list();
+ int idx = -1 ;
+ private Iterator<T> current = null ;
+ private Iterator<T> removeFrom = null ;
+ boolean finished = false ;
+
+ /**
+ * Usually, it is better to create an IteratorConcat explicitly and add iterator if there are going to be many.
+ * @param iter1
+ * @param iter2
+ * @return Iterator
+ * @see IteratorCons
+ */
+ public static <T> Iterator<T> concat(Iterator<T> iter1, Iterator<T> iter2)
+ {
+ if (iter2 == null) return iter1 ;
+ if (iter1 == null) return iter2 ;
+ IteratorConcat<T> c = new IteratorConcat<>() ;
+ c.add(iter1) ;
+ c.add(iter2) ;
+ return c ;
+ }
+
+ public IteratorConcat() {}
+
+
+ public void add(Iterator<T> iter) { iterators.add(iter) ; }
+
+ @Override
+ public boolean hasNext()
+ {
+ if ( finished )
+ return false ;
+
+ if ( current != null && current.hasNext() )
+ return true ;
+
+ while ( idx < iterators.size()-1 )
+ {
+ idx++ ;
+ current = iterators.get(idx) ;
+ if ( current.hasNext() )
+ return true ;
+ // Nothing here - move on.
+ current = null ;
+ }
+ // idx has run off the end.
+ return false ;
+ }
+
+ @Override
+ public T next()
+ {
+ if ( ! hasNext() )
+ throw new NoSuchElementException() ;
+ removeFrom = current ;
+ return current.next();
+ }
+
+ @Override
+ public void remove()
+ {
+ if ( null == removeFrom )
+ throw new IllegalStateException("no calls to next() since last call to remove()") ;
+
+ removeFrom.remove() ;
+ removeFrom = null ;
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorCons.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorCons.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorCons.java
new file mode 100644
index 0000000..c6cfd61
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorCons.java
@@ -0,0 +1,122 @@
+/*
+ * 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.iterator;
+
+import java.util.Iterator ;
+import java.util.NoSuchElementException ;
+
+/** IteratorCons : the concatenation of two iterators.
+ * See also {@link IteratorConcat}.
+ * If there potentially many iterators to be joined, it is better to
+ * create an IteratorConcat explicitly and add each iterator.
+ * IteratorCons is slightly better in the two iterator case.
+ */
+public class IteratorCons<T> implements Iterator<T>, Iterable<T>
+{
+ // No - we don't really need IteratorCons and IteratorConcat
+ // Historical - IteratorCons came first.
+ // IteratorConcat is nearly as good as IteratorCons in the small when it
+ // it is hard to see when it woudl matter much.
+
+ private Iterator<? extends T> iter1 ;
+ private Iterator<? extends T> iter2 ;
+ private Iterator<? extends T> removeFrom ;
+
+ public static <X> Iterator<X> create(Iterator<? extends X> iter1, Iterator<? extends X> iter2)
+ {
+ if ( iter1 == null && iter2 == null )
+ return Iter.nullIterator() ;
+
+ // The casts are safe because an iterator can only return X, and does not take an X an an assignment.
+ if ( iter1 == null )
+ {
+ @SuppressWarnings("unchecked")
+ Iterator<X> x = (Iterator<X>)iter2 ;
+ return x ;
+ }
+
+ if ( iter2 == null )
+ {
+ @SuppressWarnings("unchecked")
+ Iterator<X> x = (Iterator<X>)iter1 ;
+ return x ;
+ }
+
+ return new IteratorCons<>(iter1, iter2) ;
+ }
+
+ private IteratorCons(Iterator<? extends T> iter1, Iterator<? extends T> iter2)
+ {
+ this.iter1 = iter1 ;
+ this.iter2 = iter2 ;
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ if ( iter1 != null )
+ {
+ if ( iter1.hasNext() ) return true ;
+ // Iter1 ends
+ iter1 = null ;
+ }
+
+ if ( iter2 != null )
+ {
+ if ( iter2.hasNext() ) return true ;
+ // Iter2 ends
+ iter2 = null ;
+ }
+ return false ;
+ }
+
+ @Override
+ public T next()
+ {
+ if ( ! hasNext() )
+ throw new NoSuchElementException("Iterator2.next") ;
+ if ( iter1 != null )
+ {
+ removeFrom = iter1 ;
+ return iter1.next();
+ }
+ if ( iter2 != null )
+ {
+ removeFrom = iter2 ;
+ return iter2.next();
+ }
+ throw new Error("Iterator2.next") ;
+ }
+
+ @Override
+ public void remove()
+ {
+ if ( null == removeFrom )
+ throw new IllegalStateException("no calls to next() since last call to remove()") ;
+
+ removeFrom.remove() ;
+ removeFrom = null ;
+ }
+
+ @Override
+ public Iterator<T> iterator()
+ {
+ return this ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorDelayedInitialization.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorDelayedInitialization.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorDelayedInitialization.java
new file mode 100644
index 0000000..807105e
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorDelayedInitialization.java
@@ -0,0 +1,78 @@
+/*
+ * 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.iterator;
+
+import java.util.Iterator ;
+import java.util.NoSuchElementException ;
+
+import org.apache.jena.atlas.lib.Closeable ;
+
+/** Class to delay the initialization of an iterator until first call of an Iterator operation. */
+
+public abstract class IteratorDelayedInitialization<T> implements Iterator<T>, Closeable
+{
+ private boolean initialized = false ;
+ private Iterator<T> iterator ;
+
+ public IteratorDelayedInitialization() {}
+
+ private void init()
+ {
+ if ( ! initialized )
+ {
+ initialized = true ;
+ iterator = initializeIterator() ;
+ }
+ }
+
+ // Called exactly once
+ protected abstract Iterator<T> initializeIterator() ;
+
+ @Override
+ public boolean hasNext()
+ {
+ init() ;
+ boolean b = iterator.hasNext() ;
+ if ( ! b )
+ close() ;
+ return b ;
+ }
+
+ @Override
+ public T next()
+ {
+ init() ;
+ try { return iterator.next() ; }
+ catch (NoSuchElementException ex) { close() ; throw(ex) ; }
+ }
+
+ @Override
+ public void remove()
+ {
+ init() ;
+ iterator.remove() ;
+ }
+
+ @Override
+ public void close()
+ {
+ Iter.close(iterator) ;
+ iterator = null ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorInteger.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorInteger.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorInteger.java
new file mode 100644
index 0000000..6fff27c
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorInteger.java
@@ -0,0 +1,61 @@
+/*
+ * 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.iterator;
+
+import java.util.Iterator ;
+
+public class IteratorInteger implements Iterator<Long>
+{
+ private final long start ;
+ private final long finish ;
+ private long current ;
+
+ public static IteratorInteger range(long start, long finish)
+ {
+ return new IteratorInteger(start, finish) ;
+ }
+
+
+ /** [start, finish) */
+ public IteratorInteger(long start, long finish)
+ {
+ this.start = start ;
+ this.finish = finish ;
+ this.current = start ;
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ return ( current < finish ) ;
+ }
+
+ @Override
+ public Long next()
+ {
+ Long v = current;
+ current++ ;
+ return v ;
+ }
+
+ @Override
+ public void remove()
+ { throw new UnsupportedOperationException() ; }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorResourceClosing.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorResourceClosing.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorResourceClosing.java
new file mode 100644
index 0000000..89a54aa
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorResourceClosing.java
@@ -0,0 +1,107 @@
+/*
+ * 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.iterator;
+
+import java.util.Iterator;
+
+import org.apache.jena.atlas.AtlasException ;
+import org.apache.jena.atlas.io.IO ;
+import org.apache.jena.atlas.lib.Closeable ;
+
+/**
+ * This iterator will automatically close a {@link org.apache.jena.atlas.lib.Closeable} or {@link java.io.Closeable}
+ * resource when the iterator is exhausted. Alternatively, the resource will be closed when {@link #close()} is
+ * called. An {@link AtlasException} will be thrown if access is attempted after {@link #close()} has been called.
+ */
+public class IteratorResourceClosing<T> implements Iterator<T>, Closeable
+{
+ private final Iterator<T> iter ;
+ private final Object resource ;
+ private boolean finished;
+
+ public IteratorResourceClosing(Iterator<T> iter, Closeable resource)
+ {
+ this.iter = iter;
+ this.resource = resource;
+ this.finished = false;
+ }
+
+ public IteratorResourceClosing(Iterator<T> iter, java.io.Closeable resource)
+ {
+ this.iter = iter;
+ this.resource = resource ;
+ this.finished = false;
+ }
+
+ private void checkFinished()
+ {
+ if (finished) throw new AtlasException("IteratorResourceClosing is closed, no further operations can be performed on it.") ;
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ if (finished)
+ return false;
+
+ boolean toReturn = iter.hasNext();
+
+ // Clean up if we are done
+ if (!toReturn)
+ {
+ close();
+ }
+ return toReturn ;
+ }
+
+ @Override
+ public T next()
+ {
+ checkFinished();
+ return iter.next() ;
+ }
+
+ @Override
+ public void remove()
+ {
+ checkFinished();
+ iter.remove() ;
+ }
+
+ @Override
+ public void close()
+ {
+ if (!finished)
+ {
+ Iter.close(iter) ;
+ if (null != resource)
+ {
+ if (resource instanceof Closeable)
+ {
+ ((Closeable)resource).close() ;
+ }
+ else
+ {
+ IO.close((java.io.Closeable)resource) ;
+ }
+ }
+ finished = true;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorSlotted.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorSlotted.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorSlotted.java
new file mode 100644
index 0000000..fd846dc
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorSlotted.java
@@ -0,0 +1,117 @@
+/*
+ * 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.iterator;
+
+import java.util.Iterator ;
+import java.util.NoSuchElementException ;
+
+import org.apache.jena.atlas.lib.Lib ;
+
+/** An Iterator with a one slot lookahead. */
+public abstract class IteratorSlotted<T> implements Iterator<T>
+{
+ private boolean finished = false ;
+ private boolean slotIsSet = false ;
+ private T slot = null ;
+
+ protected IteratorSlotted() { }
+
+ // -------- The contract with the subclasses
+
+ /** Implement this, not next() or nextBinding() */
+ protected abstract T moveToNext() ;
+
+ /** Can return true here then null from moveToNext() to indicate end. */
+ protected abstract boolean hasMore() ;
+ // alter add a flag to say if null is a legal value.
+
+ /** Close the iterator. */
+ protected void closeIterator() { }
+
+ // -------- The contract with the subclasses
+
+ protected boolean isFinished() { return finished ; }
+
+ @Override
+ public final boolean hasNext()
+ {
+ if ( finished )
+ return false ;
+ if ( slotIsSet )
+ return true ;
+
+ boolean r = hasMore() ;
+ if ( ! r )
+ {
+ close() ;
+ return false ;
+ }
+
+ slot = moveToNext() ;
+ if ( slot == null ) {
+ close() ;
+ return false ;
+ }
+
+ slotIsSet = true ;
+ return true ;
+ }
+
+ /** final - autoclose and registration relies on it - implement moveToNextBinding() */
+ @Override
+ public final T next()
+ {
+ if ( ! hasNext() ) throw new NoSuchElementException(Lib.className(this)) ;
+
+ T obj = slot ;
+ slot = null ;
+ slotIsSet = false ;
+ return obj ;
+ }
+
+ /** Look at the next element - returns null when there is no element */
+ public final T peek()
+ {
+ return peek(null) ;
+ }
+
+ /** Look at the next element - returns dft when there is no element */
+ public final T peek(T dft)
+ {
+ hasNext() ;
+ if ( ! slotIsSet ) return dft ;
+ return slot ;
+ }
+
+ @Override
+ public final void remove()
+ {
+ throw new UnsupportedOperationException(Lib.className(this)+".remove") ;
+ }
+
+ public final void close()
+ {
+ if ( finished )
+ return ;
+ closeIterator() ;
+ slotIsSet = false ;
+ slot = null ;
+ finished = true ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorTruncate.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorTruncate.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorTruncate.java
new file mode 100644
index 0000000..86ef52e
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorTruncate.java
@@ -0,0 +1,79 @@
+/*
+ * 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.iterator;
+
+import java.util.Iterator ;
+import java.util.NoSuchElementException ;
+
+/** Iterate while a condition return true, then stop */
+public class IteratorTruncate<T> implements Iterator<T>
+{
+ static public interface Test { boolean accept(Object object) ; }
+ private Test test ;
+ private T slot = null ;
+ private boolean active = true ;
+ private Iterator<T> iter ;
+
+ public IteratorTruncate (Test test, Iterator<T> iter)
+ { this.test = test ; this.iter = iter ; }
+
+ @Override
+ public boolean hasNext()
+ {
+ if ( ! active ) return false ;
+ if ( slot != null )
+ return true ;
+
+ if ( ! iter.hasNext() )
+ {
+ active = false ;
+ return false ;
+ }
+
+ slot = iter.next() ;
+ if ( test.accept(slot) )
+ return true ;
+ // Once the test goes false, no longer yield anything.
+ Iter.close(iter) ;
+ active = false ;
+ iter = null ;
+ slot = null ;
+ return false ;
+ }
+
+ @Override
+ public T next()
+ {
+ if ( ! hasNext() )
+ throw new NoSuchElementException("IteratorTruncate.next") ;
+ T x = slot ;
+ slot = null ;
+ return x ;
+ }
+
+ @Override
+ public void remove()
+ { throw new UnsupportedOperationException("IteratorTruncate.remove"); }
+
+ public void close() {
+ if ( iter != null )
+ Iter.close(iter) ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWithBuffer.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWithBuffer.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWithBuffer.java
new file mode 100644
index 0000000..7af9ac8
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWithBuffer.java
@@ -0,0 +1,132 @@
+/*
+ * 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.iterator ;
+
+import java.util.ArrayList ;
+import java.util.Iterator ;
+import java.util.List ;
+import java.util.NoSuchElementException ;
+
+/**
+ * Iterator that delays output by N slots so you can react to the output before
+ * it's yielded. See also {@link PeekIterator} (which predates this code). See also
+ * {@link IteratorWithHistory} for an iterator that remembers what it has yielded.
+ *
+ * @see PeekIterator
+ * @see PushbackIterator
+ * @see IteratorWithHistory
+ */
+public class IteratorWithBuffer<T> implements Iterator<T> {
+ private List<T> lookahead ;
+ private Iterator<T> iter ;
+ private int capacity ;
+ private boolean innerHasEnded = false ;
+
+ public IteratorWithBuffer(Iterator<T> iter, int N) {
+ if ( N < 0 )
+ throw new IllegalArgumentException("Buffering size < 0") ;
+ this.iter = iter ;
+ this.lookahead = new ArrayList<>(N) ;
+ this.capacity = N ;
+ // Fill the lookahead.
+ for ( int i = 0 ; i < N ; i++ ) {
+ if ( !iter.hasNext() ) {
+ atEndInner() ;
+ break ;
+ }
+ T nextItem = iter.next() ;
+ // System.out.println("Fill: "+nextItem) ;
+ lookahead.add(nextItem) ;
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ return lookahead.size() > 0 ;
+ }
+
+ @Override
+ public T next() {
+ if ( !hasNext() )
+ throw new NoSuchElementException(this.getClass().getName()) ;
+
+ if ( !iter.hasNext() )
+ atEndInner() ;
+
+ T item = lookahead.remove(0) ;
+ // System.out.println("remove: "+item) ;
+ if ( iter.hasNext() ) {
+ // Should not throw NoSuchElementException.
+ T nextItem = iter.next() ;
+ // System.out.println("add : "+nextItem) ;
+ lookahead.add(nextItem) ;
+ }
+ return item ;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("remove") ;
+ }
+
+ /**
+ * Look at elements that will be returned by a subsequnet call of .next().
+ * The next element is index 0, then index 1 etc. This operation is valid
+ * immediately after the constructor returns. Returns null for no such
+ * element (underlying iterator didn't yeild enough elements). Throws
+ * IndexOutOfBoundsException if an attempt i smade to go beyond the
+ * buffering window.
+ */
+ public T peek(int idx) {
+ if ( idx < 0 || idx >= capacity )
+ throw new IndexOutOfBoundsException("Index: " + idx) ;
+ if ( idx >= lookahead.size() )
+ return null ;
+ return lookahead.get(idx) ;
+ }
+
+ /**
+ * Return the current size of the lookahead. This can be used to tell the
+ * difference between an iterator returning null and an iterator that is
+ * just short.
+ */
+ public int currentSize() {
+ return lookahead.size() ;
+ }
+
+ /**
+ * Set the element to be returned by a subsequent .next(). Use with care.
+ * The original element to be returned at this position is lost.
+ */
+ public void set(int idx, T item) {
+ lookahead.set(idx, item) ;
+ }
+
+ /** Called when the underlying iterator ends */
+ private void atEndInner() {
+ if ( !innerHasEnded ) {
+ innerHasEnded = true ;
+ endReachedInner() ;
+ }
+ }
+
+ /** Called, once, at the end of the wrapped iterator. */
+ protected void endReachedInner() {}
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWithHistory.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWithHistory.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWithHistory.java
new file mode 100644
index 0000000..b5b800a
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWithHistory.java
@@ -0,0 +1,109 @@
+/*
+ * 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.iterator;
+
+import java.util.ArrayList ;
+import java.util.Iterator ;
+import java.util.List ;
+import java.util.NoSuchElementException ;
+
+/** Remembers the last N yields.
+ * See also {@link IteratorWithBuffer}, for an iterator that looks ahead to what it will yield.
+ * @see IteratorWithBuffer
+ * @see PeekIterator
+ * @see PushbackIterator
+ */
+public class IteratorWithHistory<T> implements Iterator<T>
+{
+ private List<T> history ;
+ private Iterator<T> iter ;
+ private int capacity ;
+ private boolean hasEnded = false ;
+
+ public IteratorWithHistory(Iterator<T> iter, int N) {
+ this.iter = iter ;
+ this.history = new ArrayList<>(N) ;
+ this.capacity = N ;
+ }
+
+ @Override
+ public boolean hasNext() {
+ boolean b = iter.hasNext() ;
+ if ( !b )
+ atEnd() ;
+ return b ;
+ }
+
+ @Override
+ public T next() {
+ T item = null ;
+ try {
+ item = iter.next() ;
+ }
+ catch (NoSuchElementException ex) {
+ atEnd() ;
+ }
+ // Shuffle up, add at bottom.
+ if ( history.size() >= capacity )
+ history.remove(history.size() - 1) ;
+ history.add(0, item) ;
+ return item ;
+ }
+
+ @Override
+ public void remove()
+ { throw new UnsupportedOperationException("remove") ; }
+
+ /**
+ * return the previous i'th element returned by next(). 0 means last call of
+ * next. History is retained after the end of iteration.
+ *
+ * @return Element or null for no such element (that is for haven't yielded
+ * that many elements).
+ * @throws IndexOutOfBoundsException
+ * if index is negative.
+ */
+ public T getPrevious(int idx) {
+ if ( idx >= capacity || idx < 0 )
+ throw new IndexOutOfBoundsException("Index: " + idx) ;
+ if ( idx >= history.size() )
+ return null ;
+ return history.get(idx) ;
+ }
+
+ /**
+ * Return the current size of the histiory. This can be used to tell the
+ * difference between an iterator returning null and an iterator that is
+ * just short.
+ */
+ public int currentSize() {
+ return history.size() ;
+ }
+
+ /** Called when the underlying iterator ends */
+ protected void atEnd() {
+ if ( !hasEnded ) {
+ hasEnded = true ;
+ endReached() ;
+ }
+ }
+
+ /** Called, once, at the end */
+ protected void endReached() { }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWrapper.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWrapper.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWrapper.java
new file mode 100644
index 0000000..83901f2
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWrapper.java
@@ -0,0 +1,41 @@
+/**
+ * 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.iterator;
+
+import java.util.Iterator ;
+
+public class IteratorWrapper<T> implements Iterator<T>
+{
+ protected final Iterator<T> iterator ;
+
+ public IteratorWrapper(Iterator<T> iterator)
+ {
+ this.iterator = iterator ;
+ }
+
+ @Override
+ public boolean hasNext() { return iterator.hasNext() ; }
+
+ @Override
+ public T next() { return iterator.next() ; }
+
+ @Override
+ public void remove() { iterator.remove() ; }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/MapUtils.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/MapUtils.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/MapUtils.java
new file mode 100644
index 0000000..3c6492e
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/MapUtils.java
@@ -0,0 +1,36 @@
+/*
+ * 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.iterator;
+
+import java.util.Map ;
+
+import org.apache.jena.atlas.lib.ActionKeyValue ;
+
+
+
+public class MapUtils
+{
+ // Map specific operations
+
+ public static <K, V> void apply(Map<K, V> map, ActionKeyValue<K, V> action)
+ {
+ for ( Map.Entry<K,V> entry : map.entrySet() )
+ action.apply(entry.getKey(), entry.getValue()) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/NullIterator.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/NullIterator.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/NullIterator.java
new file mode 100644
index 0000000..ff2b2f1
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/NullIterator.java
@@ -0,0 +1,49 @@
+/*
+ * 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.iterator;
+
+import java.util.Iterator ;
+import java.util.NoSuchElementException ;
+
+/** Null Iterator - also guaranteed sharable and immutable */
+public class NullIterator<T> implements Iterator<T>, Iterable<T>
+{
+ @Override
+ public boolean hasNext()
+ {
+ return false ;
+ }
+
+ @Override
+ public T next()
+ {
+ throw new NoSuchElementException("NullIterator.next") ;
+ }
+
+ @Override
+ public void remove()
+ { throw new NoSuchElementException("NullIterator.remove") ;}
+
+ @Override
+ public Iterator<T> iterator()
+ {
+ return this ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/PeekIterator.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/PeekIterator.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/PeekIterator.java
new file mode 100644
index 0000000..d9c0d2e
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/PeekIterator.java
@@ -0,0 +1,100 @@
+/*
+ * 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.iterator;
+
+import java.util.Iterator ;
+import java.util.NoSuchElementException ;
+import java.util.Queue ;
+
+/** PeekIterator - is one slot ahead from the wrapped iterator */
+public class PeekIterator<T> implements Iterator<T>
+{
+ private final Iterator<T> iter ;
+ private boolean finished = false ;
+ // Slot always full when iterator active. Null is a a valid element.
+ private T slot ;
+
+ public static <T> PeekIterator<T> create(PeekIterator<T> iter) { return iter ; }
+ public static <T> PeekIterator<T> create(Iterator<T> iter)
+ {
+ if ( iter instanceof PeekIterator<?> )
+ return (PeekIterator<T>)iter ;
+ return new PeekIterator<>(iter) ;
+ }
+
+ public PeekIterator(Iterator<T> iter)
+ {
+ this.iter = iter ;
+ fill() ;
+ }
+
+ private void fill()
+ {
+ if ( finished ) return ;
+ if ( iter.hasNext() )
+ slot = iter.next();
+ else
+ {
+ finished = true ;
+ slot = null ;
+ }
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ if ( finished )
+ return false ;
+ return true ;
+ }
+
+ /** Peek the next element or return null
+ * @see Queue#peek
+ */
+ public T peek()
+ {
+ if ( finished )
+ return null ;
+ return slot ;
+ }
+
+ /** Peek the next element or throw NoSuchElementException */
+ public T element()
+ {
+ if ( finished )
+ throw new NoSuchElementException() ;
+ return slot ;
+ }
+
+ @Override
+ public T next()
+ {
+ if ( finished )
+ throw new NoSuchElementException() ;
+ T x = slot ;
+ // Move on now so the slot is loaded for peek.
+ fill() ;
+ return x ;
+ }
+
+ @Override
+ public void remove()
+ { throw new UnsupportedOperationException() ; }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/PushbackIterator.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/PushbackIterator.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/PushbackIterator.java
new file mode 100644
index 0000000..355c563
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/PushbackIterator.java
@@ -0,0 +1,62 @@
+/*
+ * 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.iterator ;
+
+import java.util.ArrayDeque ;
+import java.util.Deque ;
+import java.util.Iterator ;
+
+/** An iterator where you can push items backinto the iterator, to be yielded (LIFO) next time.
+ * @see PeekIterator
+ */
+public class PushbackIterator<T> implements Iterator<T> {
+ private Deque<T> items = new ArrayDeque<>() ;
+ private Iterator<T> iter ;
+
+ public PushbackIterator(Iterator<T> iter) {
+ if ( iter == null )
+ throw new IllegalArgumentException("Wrapped iterator can't be null") ;
+ this.iter = iter ;
+ }
+
+ public void pushback(T item) {
+ items.push(item) ;
+ }
+
+ @Override
+ public boolean hasNext() {
+ if ( !items.isEmpty() )
+ return true ;
+ return iter.hasNext() ;
+ }
+
+ @Override
+ public T next() {
+ if ( !items.isEmpty() )
+ return items.pop() ;
+ return iter.next() ;
+ }
+
+ @Override
+ public void remove() {
+ // Need to track if last next() was from the stack or not.
+ throw new UnsupportedOperationException() ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/RepeatApplyIterator.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/RepeatApplyIterator.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/RepeatApplyIterator.java
new file mode 100644
index 0000000..e504265
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/RepeatApplyIterator.java
@@ -0,0 +1,86 @@
+/*
+ * 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.iterator;
+
+import java.util.Iterator ;
+import java.util.NoSuchElementException ;
+
+import org.apache.jena.atlas.lib.Closeable ;
+import org.apache.jena.atlas.lib.Lib ;
+
+public abstract class RepeatApplyIterator<T> implements Iterator<T>, Closeable
+{
+ private Iterator<T> input ;
+ private boolean finished = false ;
+ private Iterator<T> currentStage = null ;
+
+ protected RepeatApplyIterator(Iterator<T> input)
+ {
+ this.input = input ;
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ if ( finished )
+ return false ;
+ for ( ;; )
+ {
+ if ( currentStage == null && input.hasNext() )
+ {
+ T nextItem = input.next();
+ currentStage = makeNextStage(nextItem) ;
+ }
+
+ if ( currentStage == null )
+ {
+ hasFinished() ;
+ finished = true ;
+ return false ;
+ }
+
+ if ( currentStage.hasNext() )
+ return true ;
+
+ currentStage = null ;
+ }
+ }
+
+ protected abstract Iterator<T> makeNextStage(T t) ;
+
+ protected void hasFinished() {}
+
+ @Override
+ public T next()
+ {
+ if ( ! hasNext() )
+ throw new NoSuchElementException(Lib.className(this)+".next()/finished") ;
+ return currentStage.next() ;
+ }
+
+ @Override
+ public final void remove()
+ { throw new UnsupportedOperationException() ; }
+
+ @Override
+ public void close()
+ {
+ Iter.close(input) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/SingletonIterator.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/SingletonIterator.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/SingletonIterator.java
new file mode 100644
index 0000000..9c49e48
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/SingletonIterator.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 org.apache.jena.atlas.iterator;
+
+import java.util.Iterator ;
+import java.util.NoSuchElementException ;
+
+public class SingletonIterator<T> implements Iterator<T>
+{
+ private T thing = null ;
+ private boolean yielded = false ;
+
+ public static <T> SingletonIterator<T> create(T thing) { return new SingletonIterator<>(thing) ; }
+
+ public SingletonIterator(T thing) { this.thing = thing ; }
+
+ @Override
+ public boolean hasNext()
+ {
+ return ! yielded ;
+ }
+
+ @Override
+ public T next()
+ {
+ if ( yielded )
+ throw new NoSuchElementException("SingletonIterator.next") ;
+ yielded = true ;
+ return thing ;
+ }
+
+ @Override
+ public void remove()
+ { throw new NoSuchElementException("SingletonIterator.remove") ;}
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/Transform.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/Transform.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/Transform.java
new file mode 100644
index 0000000..d5d6a0a
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/Transform.java
@@ -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.iterator;
+
+public interface Transform <T, R> { R convert(T item) ; }
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/WrapperIterator.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/WrapperIterator.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/WrapperIterator.java
new file mode 100644
index 0000000..0a8a0b0
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/WrapperIterator.java
@@ -0,0 +1,45 @@
+/*
+ * 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.iterator;
+
+import java.util.Iterator ;
+
+public class WrapperIterator<T> implements Iterator<T>
+{
+ private final Iterator<T> iter ;
+
+ public WrapperIterator(Iterator<T> iter) { this.iter = iter ; }
+
+ @Override
+ public boolean hasNext()
+ {
+ return iter.hasNext() ;
+ }
+
+ @Override
+ public T next()
+ {
+ return iter.next() ;
+ }
+
+ @Override
+ public void remove()
+ { iter.remove() ; }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/ActionKeyValue.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/ActionKeyValue.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/ActionKeyValue.java
new file mode 100644
index 0000000..894107a
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/ActionKeyValue.java
@@ -0,0 +1,24 @@
+/*
+ * 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.lib;
+
+public interface ActionKeyValue<KeyType, ValueType>
+{
+ public void apply(KeyType key, ValueType value) ;
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/AlarmClock.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/AlarmClock.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/AlarmClock.java
new file mode 100644
index 0000000..6210bf1
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/AlarmClock.java
@@ -0,0 +1,69 @@
+/*
+ * 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.lib ;
+
+import java.util.concurrent.ScheduledThreadPoolExecutor ;
+import java.util.concurrent.TimeUnit ;
+
+/**
+ * An AlarmClock is an object that will make a callback (with a value) at a
+ * preset time. Simple abstraction of add/reset/cancel of a Runnable. Currently,
+ * backed by {@link ScheduledThreadPoolExecutor}
+ */
+public class AlarmClock {
+ private ScheduledThreadPoolExecutor timer = new ScheduledThreadPoolExecutor(1) ;
+
+ /* package */AlarmClock() {}
+
+ static private AlarmClock singleton = new AlarmClock() ;
+
+ /** Global singleton for general use */
+ static public AlarmClock get() {
+ return singleton ;
+ }
+
+ /** Add a task to be called after a delay (in milliseconds) */
+ public void add(Runnable task, long delay) {
+ if ( task == null )
+ throw new IllegalArgumentException("Task is null") ;
+ timer.schedule(task, delay, TimeUnit.MILLISECONDS) ;
+ }
+
+ /** Reschedule a task to now run after a different delay from now (in milliseconds) */
+ public void reset(Runnable task, long delay) {
+ if ( task == null )
+ throw new IllegalArgumentException("Task is null") ;
+ cancel(task) ;
+ add(task, delay) ;
+ }
+
+ /** Cancel a task */
+ public void cancel(Runnable task) {
+ if ( task == null )
+ throw new IllegalArgumentException("Task is null") ;
+ timer.remove(task) ;
+ }
+
+ // public int getCount() { return timer.getQueue().size(); }
+
+ /** Clean up */
+ public void release() {
+ timer.shutdownNow() ;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Alg.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Alg.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Alg.java
new file mode 100644
index 0000000..3a3dacb
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Alg.java
@@ -0,0 +1,239 @@
+/*
+ * 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.lib;
+
+import java.nio.IntBuffer ;
+import java.util.Comparator ;
+import java.util.List ;
+
+public class Alg
+{
+ // Linear search is really there to test binary search.
+ static int linearSearch(IntBuffer buff, int key)
+ {
+ return linearSearch(buff, 0, buff.limit(), key) ;
+ }
+
+ static int linearSearch(IntBuffer buff, int low, int high, int key)
+ {
+ int len = buff.limit(); // In int units.
+ check(len, low, high) ;
+ for ( int i = low ; i < high ; i++ )
+ {
+ int k2 = buff.get(i) ;
+ if ( k2 == key )
+ return i ;
+ if ( k2 > key )
+ return encodeIndex(i) ;
+ }
+ return encodeIndex(high) ;
+ }
+
+ // The encoded offset (insertion point) when not found.
+ public static final int encodeIndex(int i) { return -(i+1) ; }
+ public static final int decodeIndex(int i) { return -(i+1) ; }
+
+
+ /* Both Arrays and Collections have a binary search implementation.
+ * Arrays searches Object[] arrays, and Collections searches List<T>
+ *
+ * But sometime things are not so easy, and it isn't neat as to
+ * what is being searched, like a slice of an NIO Buffer
+ *
+ * http://en.wikipedia.org/wiki/Binary_search
+ */
+
+ public static int binarySearch(IntBuffer buff, int value)
+ {
+ return binarySearch(buff, 0, buff.limit(), value) ;
+ }
+
+ public static int binarySearch(IntBuffer buff, int low, int high, int value)
+ {
+ // Low is inclusive, high is exclusive.
+ check(buff.limit(), low, high) ;
+ high -- ; // Convert high to inclusive.
+
+ // Non-tail-recursive form, because tail-recursion removal
+ // is not required by java (unlike scheme).
+
+ while (low <= high)
+ {
+ int mid = (low + high) >>> 1 ; // int divide by 2 : better: mid = low + ((high - low) / 2)
+ int k = buff.get(mid) ;
+
+ // Two comparisons : see wikipedia for one comparison version.
+ if (k < value)
+ low = mid + 1 ;
+ else if ( k > value)
+ high = mid - 1 ;
+ else
+ return mid ;
+ }
+ // On exit, when not finding, low is the least value
+ // above, including off the end of the array.
+ return encodeIndex(low) ;
+ }
+
+ // Alt form - no early termination.
+// public static int binarySearch2(IntBuffer buff, int value, int low, int high)
+// {
+// // Low is inclusive, high is exclusive
+// check(buff.limit(), low, high) ;
+// int N = high ;
+//
+// // Uses high as exclusive index
+// while (low < high)
+// {
+// int mid = (low + high) >>> 1 ; // int divide by 2 : better: mid = low + ((high - low) / 2)
+// int k = buff.get(mid) ;
+//
+// // Two comparisons : see wikipedia for one comparison version.
+// if ( k < value)
+// low = mid + 1 ;
+// else
+// //can't be high = mid-1: here A[mid] >= value,
+// //so high can't be < mid if A[mid] == value
+// high = mid;
+// }
+// if (low < N && buff.get(low) == value )
+// return low ;
+// else
+// return enc(low) ;
+// }
+
+ private static void check(int len, int low, int high)
+ {
+ if ( low > high )
+ throw new IllegalArgumentException("Low index ("+low+") is not less than high index ("+high+")") ;
+ if ( low < 0 )
+ throw new ArrayIndexOutOfBoundsException("Low index is negative: "+low) ;
+ if ( high > len )
+ throw new ArrayIndexOutOfBoundsException("High index is too large: "+high) ;
+ }
+
+ // Why isn't this in the java RT?
+ public static <T> int binarySearch( List<T> array, int low, int high, T value, Comparator<T> comparator )
+ {
+ check(array.size(), low, high) ;
+ high -- ;
+
+ while( low <= high )
+ {
+ int mid = ( low + high ) >>> 1 ;
+
+ T k = array.get(mid) ;
+
+ int x = comparator.compare(k, value) ;
+ if ( x < 0 )
+ low = mid + 1 ;
+ else if ( x > 0 )
+ high = mid - 1 ;
+ else
+ return mid ;
+ }
+ return encodeIndex(low) ;
+ }
+
+ // Why isn't this in the java RT?
+ public static <T extends Comparable<? super T>>
+ int binarySearch(T[] array, int low, int high, T value)
+ {
+ check(array.length, low, high) ;
+ high -- ;
+
+ while( low <= high )
+ {
+ int mid = ( low + high ) >>> 1 ;
+
+ T k = array[mid] ;
+
+ int x = k.compareTo(value) ; // comparator.compare(k, value) ;
+ if ( x < 0 )
+ low = mid + 1 ;
+ else if ( x > 0 )
+ high = mid - 1 ;
+ else
+ return mid ;
+ }
+ return encodeIndex(low) ;
+ }
+
+
+ // Use Arrays.binarySearch functions
+
+// public static int binarySearch(int buff[], int value)
+// { return binarySearch(buff, value, 0, buff.length) ; }
+//
+// public static int binarySearch(int buff[], int low, int high, int value)
+// {
+// check(buff.length, low, high) ;
+// // Low is inclusive, high is exclusive.
+// high -- ; // Convert high to inclusive.
+//
+// // Non-tail-recursive form, because tail-recursion removal
+// // is not required by java (unlike scheme).
+//
+// while (low <= high)
+// {
+// int mid = (low + high) >>> 1 ; // int divide by 2
+// int k = buff[mid] ;
+//
+// if (k < value)
+// low = mid + 1 ;
+// else if ( k > value)
+// high = mid - 1 ;
+// else
+// return mid ;
+// }
+// // On exit, when not finding, low is the least value
+// // above, including off the end of the array.
+// return encodeIndex(low) ;
+// }
+//
+//
+// public static int binarySearch(long buff[], int value)
+// { return binarySearch(buff, value, 0, buff.length) ; }
+//
+// public static int binarySearch(long buff[], int low, int high, long value)
+// {
+// check(buff.length, low, high) ;
+// // Low is inclusive, high is exclusive.
+// high -- ; // Convert high to inclusive.
+//
+// // Non-tail-recursive form, because tail-recursion removal
+// // is not required by java (unlike scheme).
+//
+// while (low <= high)
+// {
+// int mid = (low + high) >>> 1 ; // int divide by 2
+// long k = buff[mid] ;
+//
+// if (k < value)
+// low = mid + 1 ;
+// else if ( k > value)
+// high = mid - 1 ;
+// else
+// return mid ;
+// }
+// // On exit, when not finding, low is the least value
+// // above, including off the end of the array.
+// return encodeIndex(low) ;
+// }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Allocator.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Allocator.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Allocator.java
new file mode 100644
index 0000000..84005de
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Allocator.java
@@ -0,0 +1,28 @@
+/*
+ * 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.lib;
+
+public interface Allocator<T>
+{
+ /** Allocate a new T, different from others allocated */
+ public T create() ;
+
+// /** Reset the process of allocation - may cause equivalent objects to be created from before the reset */
+// public void reset() ;
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/ArrayUtils.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/ArrayUtils.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/ArrayUtils.java
new file mode 100644
index 0000000..d45a107
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/ArrayUtils.java
@@ -0,0 +1,64 @@
+/*
+ * 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.lib;
+
+import java.lang.reflect.Array ;
+import java.util.Arrays ;
+
+/** Collection of array-related operations */
+public class ArrayUtils
+{
+ private ArrayUtils() {}
+
+ /** Allocate an array of generic type T (initialized to null) */
+ @SuppressWarnings("unchecked")
+ public static <T> T[] alloc(Class<T> cls, int n)
+ {
+ return (T[])Array.newInstance(cls, n) ;
+ }
+
+ // Compiles but fails at runtime (class cast exception if the reuls is assigned or accessed)
+// @SuppressWarnings("unchecked")
+// T[] array = (T[])new Object[n] ;
+// or is T known
+// @SuppressWarnings("unchecked")
+// Set<T> x[] = new Set[length] ;
+// return array ;
+
+ /** Allocation space and copy */
+ public static <T> T[] copy(T[] array)
+ {
+ return copy(array, 0, array.length) ;
+ }
+
+ /** Allocation space and copy */
+ public static <T> T[] copy(T[] array, int start, int finish)
+ {
+ return Arrays.copyOfRange(array, start, finish) ;
+
+// // Java5.
+// // Fails for arrays of length 0;
+// if ( array.length <= start )
+// throw new IllegalArgumentException("Zero length array not supported") ;
+// @SuppressWarnings("unchecked")
+// T[] array2 = (T[])Array.newInstance(array[start].getClass(), finish-start) ;
+// System.arraycopy(array, start, array2, 0, finish-start) ;
+// return array2 ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/BitsInt.java
----------------------------------------------------------------------
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/BitsInt.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/BitsInt.java
new file mode 100644
index 0000000..1e112a0
--- /dev/null
+++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/BitsInt.java
@@ -0,0 +1,309 @@
+/*
+ * 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.lib;
+
+// NB shifting is "mod 32" -- <<32 is a no-op (not a clear).
+// http://mindprod.com/jgloss/masking.html
+
+/** Utilities for manipulating a bit pattern which are held in a 32 bit int.
+ * @see BitsLong
+ */
+public final class BitsInt
+{
+ private BitsInt() {}
+
+ private static int IntLen = Integer.SIZE ;
+
+ /** Extract the value packed into bits start (inclusive) and finish (exclusive).
+ * The value is returned in the low part of the returned int.
+ * The low bit is bit zero.
+ * @param bits
+ * @param start
+ * @param finish
+ * @return int
+ */
+
+ public static final
+ int unpack(int bits, int start, int finish)
+ {
+ check(start, finish) ;
+ if ( finish == 0 ) return 0 ;
+ // Remove top bits by moving up. Clear bottom bits by them moving down.
+ return (bits<<(IntLen-finish)) >>> ((IntLen-finish)+start) ;
+ }
+
+ /** Place the value into the bit pattern between start and finish
+ * and returns the new int.
+ * @param bits
+ * @param value
+ * @param start
+ * @param finish
+ * @return int
+ */
+ public static final
+ int pack(int bits, int value, int start, int finish)
+ {
+ check(start, finish) ;
+ bits = clear$(bits, start, finish) ;
+ bits = bits | (value<<start) ;
+ return bits ;
+ }
+
+ /** Get bits from a hex string.
+ *
+ * @param str
+ * @param startChar Index of first character (counted from the left, string style).
+ * @param finishChar Index after the last character (counted from the left, string style).
+ * @return int
+ */
+
+ public static final
+ int unpack(String str, int startChar, int finishChar)
+ {
+ String s = str.substring(startChar, finishChar) ;
+ return Integer.parseInt(s, 16) ;
+ }
+
+ /** Set the bits specificied.
+ *
+ * @param bits Pattern
+ * @param bitIndex
+ * @return Modified pattern
+ */
+ public static final
+ int set(int bits, int bitIndex)
+ {
+ check(bitIndex) ;
+ return set$(bits, bitIndex) ;
+ }
+
+ /** Set the bits from start (inc) to finish (exc) to one
+ *
+ * @param bits Pattern
+ * @param start start (inclusive)
+ * @param finish finish (exclusive)
+ * @return Modified pattern
+ */
+ public static final
+ int set(int bits, int start, int finish)
+ {
+ check(start, finish) ;
+ return set$(bits, start, finish) ;
+ }
+
+ /** Test whether a bit is the same as isSet
+ * @param bits Pattern
+ * @param isSet Test whether is set or not.
+ * @param bitIndex Bit index
+ * @return Boolean
+ */
+ public static final
+ boolean test(int bits, boolean isSet, int bitIndex)
+ {
+ check(bitIndex) ;
+ return test$(bits, isSet, bitIndex) ;
+ }
+
+ /** Test whether a bit is set
+ * @param bits Pattern
+ * @param bitIndex Bit index
+ * @return Boolean
+ */
+ public static final
+ boolean isSet(int bits, int bitIndex)
+ {
+ check(bitIndex) ;
+ return test$(bits, true, bitIndex) ;
+ }
+
+ /** Test whether a range has a specific value or not
+ * @param bits Pattern
+ * @param value Value to test for
+ * @param start start (inclusive)
+ * @param finish finish (exclusive)
+ * @return Boolean
+ */
+ public static final
+ boolean test(int bits, int value, int start, int finish)
+ {
+ check(start, finish) ;
+ return test$(bits, value, start, finish) ;
+ }
+
+ /** Get the bits from start (inclusive) to finish (exclusive),
+ * leaving them aligned in the int. See also unpack, returns
+ * the value found at that place.
+ * @see #unpack(int, int, int)
+ * @param bits
+ * @param start
+ * @param finish
+ * @return int
+ */
+
+ public static final
+ int access(int bits, int start, int finish)
+ {
+ check(start, finish) ;
+ return access$(bits, start, finish) ;
+ }
+
+ /**
+ * Clear the bits specified.
+ * @param bits
+ * @param start
+ * @param finish
+ * @return int
+ */
+ public static final
+ int clear(int bits, int start, int finish)
+ {
+ check(start, finish) ;
+ return clear$(bits, start, finish) ;
+ }
+
+ /**
+ * Create a mask that has ones between bit positions start (inc) and finish (exc),
+ * and zeros elsewhere.
+ * @param start
+ * @param finish
+ * @return int
+ */
+ public static final
+ int mask(int start, int finish)
+ {
+ check(start, finish) ;
+ return mask$(start, finish) ;
+ }
+
+ /**
+ * Create a mask that has zeros between bit positions start (inc) and finish (exc),
+ * and ones elsewhere
+ * @param start
+ * @param finish
+ * @return int
+ */
+ public static final
+ int maskZero(int start, int finish)
+ {
+ check(start, finish) ;
+ return maskZero$(start, finish) ;
+ }
+
+ private static final
+ int clear$(int bits, int start, int finish)
+ {
+ int mask = maskZero$(start, finish) ;
+ bits = bits & mask ;
+ return bits ;
+ }
+
+ private static final
+ int set$(int bits, int bitIndex)
+ {
+ int mask = mask$(bitIndex) ;
+ return bits | mask ;
+ }
+
+ private static final
+ int set$(int bits, int start, int finish)
+ {
+ int mask = mask$(start, finish) ;
+ return bits | mask ;
+ }
+
+ private static
+ boolean test$(int bits, boolean isSet, int bitIndex)
+ {
+ return isSet == access$(bits, bitIndex) ;
+ }
+
+ private static
+ boolean test$(int bits, int value, int start, int finish)
+ {
+ int v = access$(bits, start, finish) ;
+ return v == value ;
+ }
+
+
+
+ private static final
+ boolean access$(int bits, int bitIndex)
+ {
+ int mask = mask$(bitIndex) ;
+ return (bits & mask) != 0L ;
+ }
+
+ private static final
+ int access$(int bits, int start, int finish)
+ {
+ // Two ways:
+// int mask = mask$(start, finish) ;
+// return bits & mask ;
+
+ return ( (bits<<(IntLen-finish)) >>> (IntLen-finish+start) ) << start ;
+ }
+
+
+ private static final
+ int mask$(int bitIndex)
+ {
+ return 1 << bitIndex ;
+ }
+
+ private static final
+ int mask$(int start, int finish)
+ {
+ // int mask = 0 ;
+ // if ( finish == int.SIZE )
+ // // <<int.SIZE is a no-op
+ // mask = -1 ;
+ // else
+ // mask = (1L<<finish)-1 ;
+ if ( finish == 0 )
+ // So start is zero and so the mask is zero.
+ return 0 ;
+
+
+ int mask = -1 ;
+// mask = mask << (IntLen-finish) >>> (intLen-finish) ; // Clear the top bits
+// return mask >>> start << start ; // Clear the bottom bits
+ return mask << (IntLen-finish) >>> (IntLen-finish+start) << start ;
+ }
+
+ private static final
+ int maskZero$(int start, int finish)
+ {
+ return ~mask$(start, finish) ;
+ }
+
+ private static final
+ void check(int bitIndex)
+ {
+ if ( bitIndex < 0 || bitIndex >= IntLen ) throw new IllegalArgumentException("Illegal bit index: "+bitIndex) ;
+ }
+
+ private static final
+ void check(int start, int finish)
+ {
+ if ( start < 0 || start >= IntLen ) throw new IllegalArgumentException("Illegal start: "+start) ;
+ if ( finish < 0 || finish > IntLen ) throw new IllegalArgumentException("Illegal finish: "+finish) ;
+ if ( start > finish ) throw new IllegalArgumentException("Illegal range: ("+start+", "+finish+")") ;
+ }
+
+}