WIP
[maven-thymeleaf-skin] / src / main / java / de / juplo / jackson / SimpleMapper.java
index 941c4b1..e4028db 100644 (file)
@@ -5,14 +5,17 @@ import com.fasterxml.jackson.core.JsonFactory;
 import com.fasterxml.jackson.core.JsonLocation;
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonToken;
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.Collections;
+import java.io.Reader;
+import java.net.URL;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.NoSuchElementException;
 import java.util.Spliterator;
 import static java.util.Spliterator.IMMUTABLE;
@@ -35,16 +38,395 @@ public class SimpleMapper
       LoggerFactory.getLogger(SimpleMapper.class);
 
 
-  private JsonFactory factory = new JsonFactory();
+  private final JsonFactory factory;
 
 
-  public static Stream<Object> getArrayStream(final JsonParser parser)
+  public SimpleMapper(JsonFactory factory)
+  {
+    this.factory = factory;
+  }
+
+
+  public Spliterator<Object> getArraySpliterator(File file)
       throws
         IOException
   {
-    return StreamSupport.stream(getArraySpliterator(parser), false);
+    return getArraySpliterator(factory.createParser(file));
+  }
+
+  public Spliterator<Object> getArraySpliterator(InputStream is)
+      throws
+        IOException
+  {
+    return getArraySpliterator(factory.createParser(is));
+  }
+
+  public Spliterator<Object> getArraySpliterator(Reader r)
+      throws
+        IOException
+  {
+    return getArraySpliterator(factory.createParser(r));
+  }
+
+  public Spliterator<Object> getArraySpliterator(String content)
+      throws
+        IOException
+  {
+    return getArraySpliterator(factory.createParser(content));
+  }
+
+  public Spliterator<Object> getArraySpliterator(URL url)
+      throws
+        IOException
+  {
+    return getArraySpliterator(factory.createParser(url));
+  }
+
+  public Spliterator<Object> getArraySpliterator(byte[] data)
+      throws
+        IOException
+  {
+    return getArraySpliterator(factory.createParser(data));
+  }
+
+  public Spliterator<Object> getArraySpliterator(char[] content)
+      throws
+        IOException
+  {
+    return getArraySpliterator(factory.createParser(content));
+  }
+
+  public Spliterator<Object> getArraySpliterator(byte[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getArraySpliterator(factory.createParser(data, offset, len));
+  }
+
+  public Spliterator<Object> getArraySpliterator(char[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getArraySpliterator(factory.createParser(data, offset, len));
+  }
+
+  public Stream<Object> getArrayStream(File file)
+      throws
+        IOException
+  {
+    return getArrayStream(factory.createParser(file));
+  }
+
+  public Stream<Object> getArrayStream(InputStream is)
+      throws
+        IOException
+  {
+    return getArrayStream(factory.createParser(is));
+  }
+
+  public Stream<Object> getArrayStream(Reader r)
+      throws
+        IOException
+  {
+    return getArrayStream(factory.createParser(r));
+  }
+
+  public Stream<Object> getArrayStream(String content)
+      throws
+        IOException
+  {
+    return getArrayStream(factory.createParser(content));
+  }
+
+  public Stream<Object> getArrayStream(URL url)
+      throws
+        IOException
+  {
+    return getArrayStream(factory.createParser(url));
+  }
+
+  public Stream<Object> getArrayStream(byte[] data)
+      throws
+        IOException
+  {
+    return getArrayStream(factory.createParser(data));
+  }
+
+  public Stream<Object> getArrayStream(char[] content)
+      throws
+        IOException
+  {
+    return getArrayStream(factory.createParser(content));
+  }
+
+  public Stream<Object> getArrayStream(byte[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getArrayStream(factory.createParser(data, offset, len));
+  }
+
+  public Stream<Object> getArrayStream(char[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getArrayStream(factory.createParser(data, offset, len));
+  }
+
+  public Iterator<Object> getArrayIterator(File file)
+      throws
+        IOException
+  {
+    return getArrayIterator(factory.createParser(file));
+  }
+
+  public Iterator<Object> getArrayIterator(InputStream is)
+      throws
+        IOException
+  {
+    return getArrayIterator(factory.createParser(is));
+  }
+
+  public Iterator<Object> getArrayIterator(Reader r)
+      throws
+        IOException
+  {
+    return getArrayIterator(factory.createParser(r));
+  }
+
+  public Iterator<Object> getArrayIterator(String content)
+      throws
+        IOException
+  {
+    return getArrayIterator(factory.createParser(content));
+  }
+
+  public Iterator<Object> getArrayIterator(URL url)
+      throws
+        IOException
+  {
+    return getArrayIterator(factory.createParser(url));
+  }
+
+  public Iterator<Object> getArrayIterator(byte[] data)
+      throws
+        IOException
+  {
+    return getArrayIterator(factory.createParser(data));
+  }
+
+  public Iterator<Object> getArrayIterator(char[] content)
+      throws
+        IOException
+  {
+    return getArrayIterator(factory.createParser(content));
+  }
+
+  public Iterator<Object> getArrayIterator(byte[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getArrayIterator(factory.createParser(data, offset, len));
+  }
+
+  public Iterator<Object> getArrayIterator(char[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getArrayIterator(factory.createParser(data, offset, len));
+  }
+
+
+  public Spliterator<Entry<String, Object>> getObjectSpliterator(File file)
+      throws
+        IOException
+  {
+    return getObjectSpliterator(factory.createParser(file));
+  }
+
+  public Spliterator<Entry<String, Object>> getObjectSpliterator(InputStream is)
+      throws
+        IOException
+  {
+    return getObjectSpliterator(factory.createParser(is));
+  }
+
+  public Spliterator<Entry<String, Object>> getObjectSpliterator(Reader r)
+      throws
+        IOException
+  {
+    return getObjectSpliterator(factory.createParser(r));
+  }
+
+  public Spliterator<Entry<String, Object>> getObjectSpliterator(String content)
+      throws
+        IOException
+  {
+    return getObjectSpliterator(factory.createParser(content));
+  }
+
+  public Spliterator<Entry<String, Object>> getObjectSpliterator(URL url)
+      throws
+        IOException
+  {
+    return getObjectSpliterator(factory.createParser(url));
+  }
+
+  public Spliterator<Entry<String, Object>> getObjectSpliterator(byte[] data)
+      throws
+        IOException
+  {
+    return getObjectSpliterator(factory.createParser(data));
+  }
+
+  public Spliterator<Entry<String, Object>> getObjectSpliterator(char[] content)
+      throws
+        IOException
+  {
+    return getObjectSpliterator(factory.createParser(content));
+  }
+
+  public Spliterator<Entry<String, Object>> getObjectSpliterator(byte[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getObjectSpliterator(factory.createParser(data, offset, len));
+  }
+
+  public Spliterator<Entry<String, Object>> getObjectSpliterator(char[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getObjectSpliterator(factory.createParser(data, offset, len));
   }
 
+  public Stream<Entry<String, Object>> getObjectStream(File file)
+      throws
+        IOException
+  {
+    return getObjectStream(factory.createParser(file));
+  }
+
+  public Stream<Entry<String, Object>> getObjectStream(InputStream is)
+      throws
+        IOException
+  {
+    return getObjectStream(factory.createParser(is));
+  }
+
+  public Stream<Entry<String, Object>> getObjectStream(Reader r)
+      throws
+        IOException
+  {
+    return getObjectStream(factory.createParser(r));
+  }
+
+  public Stream<Entry<String, Object>> getObjectStream(String content)
+      throws
+        IOException
+  {
+    return getObjectStream(factory.createParser(content));
+  }
+
+  public Stream<Entry<String, Object>> getObjectStream(URL url)
+      throws
+        IOException
+  {
+    return getObjectStream(factory.createParser(url));
+  }
+
+  public Stream<Entry<String, Object>> getObjectStream(byte[] data)
+      throws
+        IOException
+  {
+    return getObjectStream(factory.createParser(data));
+  }
+
+  public Stream<Entry<String, Object>> getObjectStream(char[] content)
+      throws
+        IOException
+  {
+    return getObjectStream(factory.createParser(content));
+  }
+
+  public Stream<Entry<String, Object>> getObjectStream(byte[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getObjectStream(factory.createParser(data, offset, len));
+  }
+
+  public Stream<Entry<String, Object>> getObjectStream(char[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getObjectStream(factory.createParser(data, offset, len));
+  }
+
+  public Iterator<Entry<String, Object>> getObjectIterator(File file)
+      throws
+        IOException
+  {
+    return getObjectIterator(factory.createParser(file));
+  }
+
+  public Iterator<Entry<String, Object>> getObjectIterator(InputStream is)
+      throws
+        IOException
+  {
+    return getObjectIterator(factory.createParser(is));
+  }
+
+  public Iterator<Entry<String, Object>> getObjectIterator(Reader r)
+      throws
+        IOException
+  {
+    return getObjectIterator(factory.createParser(r));
+  }
+
+  public Iterator<Entry<String, Object>> getObjectIterator(String content)
+      throws
+        IOException
+  {
+    return getObjectIterator(factory.createParser(content));
+  }
+
+  public Iterator<Entry<String, Object>> getObjectIterator(URL url)
+      throws
+        IOException
+  {
+    return getObjectIterator(factory.createParser(url));
+  }
+
+  public Iterator<Entry<String, Object>> getObjectIterator(byte[] data)
+      throws
+        IOException
+  {
+    return getObjectIterator(factory.createParser(data));
+  }
+
+  public Iterator<Entry<String, Object>> getObjectIterator(char[] content)
+      throws
+        IOException
+  {
+    return getObjectIterator(factory.createParser(content));
+  }
+
+  public Iterator<Entry<String, Object>> getObjectIterator(byte[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getObjectIterator(factory.createParser(data, offset, len));
+  }
+
+  public Iterator<Entry<String, Object>> getObjectIterator(char[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getObjectIterator(factory.createParser(data, offset, len));
+  }
+
+
   public static Spliterator<Object> getArraySpliterator(final JsonParser parser)
       throws
         IOException
@@ -58,9 +440,7 @@ public class SimpleMapper
     }
 
     if (!JsonToken.START_ARRAY.equals(token))
-    {
-      throw new IllegalArgumentException("The root-element must be an array!");
-    }
+      fail(parser, "The root-element must be an array!");
 
     return new Spliterator<Object>()
     {
@@ -71,7 +451,7 @@ public class SimpleMapper
         {
           JsonToken token = parser.nextToken();
           if (token == null)
-            throw new IllegalArgumentException("Unexpected end of data!");
+            fail(parser, "Unexpected end of data!");
           if (JsonToken.END_ARRAY.equals(token))
             return false;
           action.accept(convert(parser));
@@ -103,37 +483,104 @@ public class SimpleMapper
     };
   }
 
+  public static Stream<Object> getArrayStream(final JsonParser parser)
+      throws
+        IOException
+  {
+    return StreamSupport.stream(getArraySpliterator(parser), false);
+  }
+
   public static Iterator<Object> getArrayIterator(final JsonParser parser)
       throws
         IOException
+  {
+    Spliterator<Object> spliterator = getArraySpliterator(parser);
+    return new Iterator<Object>()
+    {
+      private Object next = null;
+
+
+      @Override
+      public boolean hasNext()
+      {
+        if (next != null)
+          return true;
+
+        return spliterator.tryAdvance(new Consumer<Object>()
+        {
+          @Override
+          public void accept(Object o)
+          {
+            next = o;
+          }
+        });
+      }
+
+      @Override
+      public Object next()
+      {
+        if (next == null && !hasNext())
+          throw new NoSuchElementException();
+        Object o = next;
+        next = null;
+        return o;
+      }
+    };
+  }
+
+
+  public static Spliterator<Entry<String, Object>> getObjectSpliterator(final JsonParser parser)
+      throws
+        IOException
   {
     JsonToken token = parser.nextToken();
 
     if (token == null)
     {
       LOG.warn("empty input");
-      return Collections.emptyIterator();
+      return Spliterators.emptySpliterator();
     }
 
-    if (!JsonToken.START_ARRAY.equals(token))
-    {
-      throw new IllegalArgumentException("The root-element must be an array!");
-    }
+    if (!JsonToken.START_OBJECT.equals(token))
+      fail(parser, "The root-element must be an array!");
 
-    return new Iterator<Object>()
+    return new Spliterator<Entry<String, Object>>()
     {
-      
       @Override
-      public boolean tryAdvance(Consumer<? super Object> action)
+      public boolean tryAdvance(Consumer<? super Entry<String, Object>> action)
       {
         try
         {
           JsonToken token = parser.nextToken();
           if (token == null)
-            throw new IllegalArgumentException("Unexpected end of data!");
-          if (JsonToken.END_ARRAY.equals(token))
-            throw new NoSuchElementException();
-          action.accept(convert(parser));
+            fail(parser, "Unexpected end of data!");
+          if (JsonToken.END_OBJECT.equals(token))
+            return false;
+          if (!JsonToken.FIELD_NAME.equals(token))
+            fail(parser, "expected a field-name");
+          final String key = parser.getText();
+          parser.nextToken();
+          final Object value = convert(parser);
+          action.accept(new Entry<String, Object>()
+          {
+            @Override
+            public String getKey()
+            {
+              return key;
+            }
+
+            @Override
+            public Object getValue()
+            {
+              return value;
+            }
+
+            @Override
+            public Object setValue(Object value)
+            {
+              throw new UnsupportedOperationException("Not supported.");
+            }
+          });
           return true;
         }
         catch (IOException e)
@@ -141,61 +588,72 @@ public class SimpleMapper
           throw new IllegalArgumentException(e);
         }
       }
+
       @Override
-      public boolean hasNext()
+      public Spliterator<Entry<String, Object>> trySplit()
       {
+        return null;
       }
 
       @Override
-      public Object next()
+      public long estimateSize()
       {
-        try
-        {
-          JsonToken token = parser.nextToken();
-          if (token == null)
-            throw new IllegalArgumentException("Unexpected end of data!");
-          if (JsonToken.END_ARRAY.equals(token))
-            return false;
-          action.accept(convert(parser));
-          return true;
-        }
-        catch (IOException e)
-        {
-          throw new IllegalArgumentException(e);
-        }
+        return Long.MAX_VALUE;
+      }
+
+      @Override
+      public int characteristics()
+      {
+        return IMMUTABLE;
       }
     };
   }
 
-  public Object processAttribute(InputStream is)
+  public static Stream<Entry<String, Object>> getObjectStream(final JsonParser parser)
+      throws
+        IOException
   {
-    try
+    return StreamSupport.stream(getObjectSpliterator(parser), false);
+  }
+
+  public static Iterator<Entry<String, Object>> getObjectIterator(
+      final JsonParser parser
+      )
+      throws
+        IOException
+  {
+    Spliterator<Entry<String, Object>> spliterator = getObjectSpliterator(parser);
+    return new Iterator<Entry<String, Object>>()
     {
-      /**
-       * Read the JSON and create the variables
-       */
-      JsonParser parser = factory.createParser(is);
+      private Entry<String, Object> next = null;
 
-      JsonToken token = parser.nextToken();
 
-      if (token == null)
+      @Override
+      public boolean hasNext()
       {
-        LOG.warn("empty input-stream");
-        return null;
-      }
-
-      Object result = convert(parser);
+        if (next != null)
+          return true;
 
-      if (parser.nextToken() != null)
-        fail(parser, "unexpected data after parsed variables");
+        return spliterator.tryAdvance(new Consumer<Entry<String, Object>>()
+        {
+          @Override
+          public void accept(Entry<String, Object> e)
+          {
+            next = e;
+          }
+        });
+      }
 
-      return result;
-    }
-    catch (IOException e)
-    {
-      LOG.error("cannot parse input-stream as JSON: {}", e.getMessage());
-      throw new RuntimeException(e);
-    }
+      @Override
+      public Entry<String, Object> next()
+      {
+        if (next == null && !hasNext())
+          throw new NoSuchElementException();
+        Entry<String, Object> e = next;
+        next = null;
+        return e;
+      }
+    };
   }
 
 
@@ -221,6 +679,7 @@ public class SimpleMapper
     return null; // << Will never be reached, because fail always throws an exception
   }
 
+
   static Map<String, Object> convertObject(JsonParser parser) throws IOException
   {
     JsonToken token = parser.nextToken();
@@ -267,6 +726,7 @@ public class SimpleMapper
     return list;
   }
 
+
   static void fail(JsonParser parser, String message)
   {
     JsonLocation location = parser.getCurrentLocation();
@@ -277,6 +737,6 @@ public class SimpleMapper
         location.getLineNr(),
         location.getColumnNr()
         );
-    throw new RuntimeException("Cannot parse JSON: " + message);
+    throw new IllegalArgumentException("Cannot parse JSON: " + message);
   }
 }