All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.infinispan.commons.configuration.io.json.JsonConfigurationReader Maven / Gradle / Ivy
package org.infinispan.commons.configuration.io.json;
import java.io.BufferedReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.infinispan.commons.configuration.io.AbstractConfigurationReader;
import org.infinispan.commons.configuration.io.ConfigurationFormatFeature;
import org.infinispan.commons.configuration.io.ConfigurationReaderException;
import org.infinispan.commons.configuration.io.ConfigurationResourceResolver;
import org.infinispan.commons.configuration.io.Location;
import org.infinispan.commons.configuration.io.NamingStrategy;
import org.infinispan.commons.configuration.io.PropertyReplacer;
import org.infinispan.commons.dataconversion.internal.Json;
import org.infinispan.commons.util.SimpleImmutableEntry;
import org.infinispan.commons.util.Util;
/**
* @author Tristan Tarrant <[email protected] >
* @since 12.1
**/
public class JsonConfigurationReader extends AbstractConfigurationReader {
private static final String NAMESPACE = "_namespace";
private final Deque> iteratorStack;
private final Deque nameStack;
private final BufferedReader reader;
private final List> attributes = new ArrayList<>();
private final String namespace;
private String name;
private Json element, current;
private ElementType type;
public JsonConfigurationReader(BufferedReader reader, ConfigurationResourceResolver resourceResolver, Properties properties, PropertyReplacer replacer, NamingStrategy namingStrategy) {
super(resourceResolver, properties, replacer, namingStrategy);
this.reader = reader;
try (Stream lines = this.reader.lines()) {
Map json = Json.read(lines.collect(Collectors.joining("\n"))).asJsonMap();
Json namespace = json.remove(NAMESPACE);
this.namespace = namespace == null ? "" : namespace.asString();
iteratorStack = new ArrayDeque<>();
iteratorStack.push(json.entrySet().iterator());
nameStack = new ArrayDeque<>();
type = ElementType.START_DOCUMENT;
}
}
@Override
public ElementType nextElement() {
Iterator> iterator = iteratorStack.peek();
if (iterator == null) {
return null;
} else if (iterator.hasNext()) {
Object item = iterator.next();
if (item instanceof Map.Entry) {
// this is a map
Map.Entry e = (Map.Entry) item;
Json value = (Json) e.getValue();
current = value;
if (value.isPrimitive()) {
throw new IllegalStateException("Primitive attribute should have been detected as attribute: " + e.getKey());
} else if (value.isObject()) {
processObject(value);
} else if (value.isArray()) {
processArray(e.getKey(), value);
} else if (value.isNull()) {
attributes.clear();
iteratorStack.push(Collections.emptyIterator());
}
name = e.getKey();
nameStack.push(name);
return (type = ElementType.START_ELEMENT);
} else if (item instanceof ElementEntry) {
ElementEntry entry = (ElementEntry) item;
name = entry.k;
type = entry.type;
if (type == ElementType.START_ELEMENT) {
nameStack.push(name);
current = element = entry.v;
if (element.isObject()) {
processObject(element);
} else if (element.isArray()) {
processArray(name, element);
} else {
throw new IllegalStateException("Element is neither an object nor an array: " + entry.k);
}
} else {
nameStack.pop();
iteratorStack.pop();
element = null;
}
return type;
} else {
throw new IllegalStateException(item.toString());
}
} else {
// We've reached the end of the current iterator
iteratorStack.pop();
element = null;
attributes.clear();
if (nameStack.isEmpty()) {
return (type = ElementType.END_DOCUMENT);
} else {
name = nameStack.pop();
return (type = ElementType.END_ELEMENT);
}
}
}
private void processArray(String name, Json value) {
attributes.clear();
List list = value.asJsonList();
List array = new ArrayList<>(list.size() * 2 + 2);
boolean primitive = (list.size() > 0 && list.get(0).isPrimitive());
if (!primitive) {
array.add(new ElementEntry(name, null, ElementType.START_ELEMENT));
}
for (Json json : list) {
array.add(new ElementEntry(name, json, ElementType.START_ELEMENT));
}
if (!primitive) {
array.add(new ElementEntry(name, null, ElementType.END_ELEMENT));
}
Iterator it = array.iterator();
iteratorStack.push(it);
current = element = it.next().v; // Already remove the first one
}
private void processObject(Json value) {
// Find all the attributes
attributes.clear();
Map map = value.asJsonMap();
for (Iterator> it = map.entrySet().iterator(); it.hasNext(); ) {
Map.Entry entry = it.next();
if (entry.getValue().isPrimitive()) {
this.attributes.add(entry);
it.remove();
} else if (isArrayOfPrimitives(entry.getValue())) {
this.attributes.add(entry);
it.remove();
}
}
iteratorStack.push(map.entrySet().iterator());
}
private boolean isArrayOfPrimitives(Json json) {
if (json.isArray()) {
List list = json.asJsonList();
if (list.isEmpty()) {
return false;
}
for(Json item : list) {
if (!item.isPrimitive()) {
return false;
}
}
return true;
} else {
return false;
}
}
@Override
public Location getLocation() {
if (current != null) {
return new Location(getName(), current.getLine(), current.getColumn());
} else {
return new Location(getName(), 1, 0);
}
}
@Override
public String getAttributeName(int index, NamingStrategy strategy) {
String name = attributes.get(index).getKey();
return basename(strategy, name);
}
private String basename(NamingStrategy strategy, String name) {
int colon = name.lastIndexOf(':');
return strategy.convert(colon < 0 ? name : name.substring(colon + 1));
}
@Override
public String getLocalName(NamingStrategy strategy) {
return basename(strategy, name);
}
@Override
public String getAttributeNamespace(int index) {
String name = attributes.get(index).getKey();
int colon = name.lastIndexOf(':');
return colon < 0 ? "" : name.substring(0, colon);
}
@Override
public String getAttributeValue(String name, NamingStrategy strategy) {
for (Map.Entry attribute : attributes) {
if (name.equals(basename(strategy, attribute.getKey()))) {
return replaceProperties(attribute.getValue().asString());
}
}
return null;
}
@Override
public String[] getListAttributeValue(int index) {
Json value = attributes.get(index).getValue();
if (value.isArray()) {
List list = value.asJsonList();
String[] array = new String[list.size()];
for(int i = 0; i < list.size(); i++) {
array[i] = replaceProperties(list.get(i).asString());
}
return array;
} else {
return replaceProperties(value.isString() ? value.asString() : value.toString()).split("\\s+");
}
}
@Override
public String getAttributeValue(int index) {
Json value = attributes.get(index).getValue();
return replaceProperties(value.isString() ? value.asString() : value.toString());
}
@Override
public String getElementText() {
String text = (element != null && element.isPrimitive()) ? element.asString() : null;
nextElement();// Consume the end element
return text;
}
@Override
public String getNamespace() {
int colon = name.lastIndexOf(':');
return colon < 0 ? namespace : name.substring(0, colon);
}
@Override
public boolean hasNext() {
return !iteratorStack.isEmpty();
}
@Override
public int getAttributeCount() {
return attributes.size();
}
@Override
public void require(ElementType type, String namespace, String name) {
if (type != this.type
|| (namespace != null && !namespace.equals(getNamespace()))
|| (name != null && !name.equals(getLocalName()))) {
throw new ConfigurationReaderException("Expected event " + type
+ (name != null ? " with name '" + name + "'" : "")
+ (namespace != null && name != null ? " and" : "")
+ (namespace != null ? " with namespace '" + namespace + "'" : "")
+ " but got"
+ (type != this.type ? " " + this.type : "")
+ (name != null && getLocalName() != null && !name.equals(getLocalName())
? " name '" + getLocalName() + "'" : "")
+ (namespace != null && name != null
&& getLocalName() != null && !name.equals(getLocalName())
&& getNamespace() != null && !namespace.equals(getNamespace())
? " and" : "")
+ (namespace != null && getNamespace() != null && !namespace.equals(getNamespace())
? " namespace '" + getNamespace() + "'" : ""), new Location(getName(), 1, 1));
}
}
@Override
public Map.Entry getMapItem(String nameAttribute) {
String name = getLocalName(NamingStrategy.IDENTITY);
nextElement();
String type = getLocalName();
return new SimpleImmutableEntry<>(name, type);
}
@Override
public void endMapItem() {
nextElement();
}
@Override
public String[] readArray(String outer, String inner) {
Iterator iterator = (Iterator) iteratorStack.peek();
List array = new ArrayList<>();
while (iterator.hasNext()) {
ElementEntry next = iterator.next();
if (next.type == ElementType.END_ELEMENT) {
array.add(next.v.asString());
}
}
nextElement();
require(ElementType.END_ELEMENT, null, outer);
return array.stream().toArray(String[]::new);
}
@Override
public boolean hasFeature(ConfigurationFormatFeature feature) {
return false;
}
@Override
public void close() {
Util.close(reader);
}
@Override
public void setAttributeValue(String namespace, String name, String value) {
attributes.add(new SimpleImmutableEntry<>(name, Json.make(value)));
}
private static class ElementEntry {
final String k;
final Json v;
final ElementType type;
ElementEntry(String k, Json v, ElementType type) {
this.k = k;
this.v = v;
this.type = type;
}
}
}