/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership. Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/
package org.teiid.translator.document;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* TODO: need to back this up with something like MapDB, to avoid OOM
* Also need to write our own JSONPaser that returns this object directly.
*/
public class Document {
private String name;
private Map<String, Object> properties = new LinkedHashMap<String, Object>();
private Map<String, List<Document>> children = new LinkedHashMap<String, List<Document>>();
private boolean array;
private Document parent;
public Document() {
}
public Document(String name, boolean array, Document parent) {
this.name = name;
this.parent = parent;
this.array = array;
}
public boolean isArray() {
return array;
}
static List<Map<String, Object>> crossjoinWith(
List<Map<String, Object>> left, List<? extends Document> rightDocuments) {
ArrayList<Map<String, Object>> joined = new ArrayList<Map<String,Object>>();
for (Document right : rightDocuments) {
List<Map<String,Object>> rightRows = right.flatten();
for (Map<String, Object> outer : left) {
for (Map<String, Object> inner : rightRows) {
LinkedHashMap<String, Object> row = new LinkedHashMap<String, Object>();
row.putAll(outer);
row.putAll(inner);
joined.add(row);
}
}
}
return joined;
}
public List<Map<String, Object>> flatten(){
List<Map<String, Object>> joined = new ArrayList<Map<String, Object>>();
LinkedHashMap<String, Object> row = new LinkedHashMap<String, Object>();
if (this.properties != null) {
row.putAll(this.properties);
}
joined.add(row);
if (this.children != null && !this.children.isEmpty()) {
for (List<? extends Document> childDoc:this.children.values()) {
joined = crossjoinWith(joined, childDoc);
}
}
return joined;
}
public Map<String, Object> getProperties(){
return this.properties;
}
public Map<String, List<Document>> getChildren() {
return children;
}
public List<? extends Document> getChildDocuments(String path) {
if (this.children != null) {
int index = path.indexOf('/');
if (index != -1) {
String parentName = path.substring(0, index);
if (parentName.equals(this.name)) {
return this.children.get(path.substring(index+1));
} else {
// then this is the sibiling
return this.parent.getChildDocuments(parentName);
}
}
List<? extends Document> children = this.children.get(path);
if (children == null && this.parent != null) {
children = this.parent.getChildDocuments(path);
}
return children;
}
return null;
}
private static String name(String s1, String s2) {
if (s1 != null) {
StringBuilder sb = new StringBuilder();
sb.append(s1).append("/").append(s2);
return sb.toString();
} else {
return s2;
}
}
public String getName() {
if (this.parent != null) {
return name(this.parent.getName(), this.name);
}
return name;
}
public void addProperty(String key, Object value) {
if (this.parent == null) {
this.properties.put(key, value);
} else {
this.properties.put(name(getName(), key), value);
}
}
public void addArrayProperty(String key, Object value) {
if (this.properties == null) {
this.properties = new LinkedHashMap<String, Object>();
}
String propkey = this.parent == null?key:name(getName(), key);
@SuppressWarnings("unchecked")
List<Object> propValue = (List<Object>)this.properties.get(propkey);
if (propValue == null) {
propValue = new ArrayList<Object>();
propValue.add(value);
} else {
propValue.add(value);
}
this.properties.put(propkey, propValue);
}
public void addChildDocuments(String path, List<Document> child) {
this.children.put(path, child);
}
public List<Document> addChildDocument(String path, Document child) {
if (this.children == null) {
this.children = new LinkedHashMap<String, List<Document>>();
}
if (children.get(path) == null) {
children.put(path, new ArrayList<Document>());
}
this.children.get(path).add(child);
return this.children.get(path);
}
public String toString() {
return this.name;
}
public Document getParent() {
return this.parent;
}
}