summaryrefslogtreecommitdiffstats
path: root/rosetta/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'rosetta/src/main/java')
-rw-r--r--rosetta/src/main/java/com/att/rosetta/InJson.java156
-rw-r--r--rosetta/src/main/java/com/att/rosetta/InXML.java488
-rw-r--r--rosetta/src/main/java/com/att/rosetta/JaxEval.java28
-rw-r--r--rosetta/src/main/java/com/att/rosetta/JaxInfo.java250
-rw-r--r--rosetta/src/main/java/com/att/rosetta/JaxSet.java92
-rw-r--r--rosetta/src/main/java/com/att/rosetta/Ladder.java114
-rw-r--r--rosetta/src/main/java/com/att/rosetta/Marshal.java83
-rw-r--r--rosetta/src/main/java/com/att/rosetta/Nulls.java68
-rw-r--r--rosetta/src/main/java/com/att/rosetta/Out.java45
-rw-r--r--rosetta/src/main/java/com/att/rosetta/OutJax.java54
-rw-r--r--rosetta/src/main/java/com/att/rosetta/OutJson.java234
-rw-r--r--rosetta/src/main/java/com/att/rosetta/OutRaw.java48
-rw-r--r--rosetta/src/main/java/com/att/rosetta/OutXML.java227
-rw-r--r--rosetta/src/main/java/com/att/rosetta/Parse.java47
-rw-r--r--rosetta/src/main/java/com/att/rosetta/ParseException.java44
-rw-r--r--rosetta/src/main/java/com/att/rosetta/Parsed.java91
-rw-r--r--rosetta/src/main/java/com/att/rosetta/Prop.java45
-rw-r--r--rosetta/src/main/java/com/att/rosetta/Saved.java195
-rw-r--r--rosetta/src/main/java/com/att/rosetta/XmlEscape.java373
-rw-r--r--rosetta/src/main/java/com/att/rosetta/env/RosettaDF.java267
-rw-r--r--rosetta/src/main/java/com/att/rosetta/env/RosettaData.java314
-rw-r--r--rosetta/src/main/java/com/att/rosetta/env/RosettaEnv.java90
-rw-r--r--rosetta/src/main/java/com/att/rosetta/marshal/DataWriter.java140
-rw-r--r--rosetta/src/main/java/com/att/rosetta/marshal/DocMarshal.java84
-rw-r--r--rosetta/src/main/java/com/att/rosetta/marshal/FieldArray.java94
-rw-r--r--rosetta/src/main/java/com/att/rosetta/marshal/FieldBlob.java40
-rw-r--r--rosetta/src/main/java/com/att/rosetta/marshal/FieldDate.java39
-rw-r--r--rosetta/src/main/java/com/att/rosetta/marshal/FieldDateTime.java39
-rw-r--r--rosetta/src/main/java/com/att/rosetta/marshal/FieldHexBinary.java37
-rw-r--r--rosetta/src/main/java/com/att/rosetta/marshal/FieldMarshal.java61
-rw-r--r--rosetta/src/main/java/com/att/rosetta/marshal/FieldNumeric.java38
-rw-r--r--rosetta/src/main/java/com/att/rosetta/marshal/FieldString.java38
-rw-r--r--rosetta/src/main/java/com/att/rosetta/marshal/ListIterator.java60
-rw-r--r--rosetta/src/main/java/com/att/rosetta/marshal/ObjArray.java92
-rw-r--r--rosetta/src/main/java/com/att/rosetta/marshal/ObjMarshal.java129
35 files changed, 4244 insertions, 0 deletions
diff --git a/rosetta/src/main/java/com/att/rosetta/InJson.java b/rosetta/src/main/java/com/att/rosetta/InJson.java
new file mode 100644
index 0000000..9462e67
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/InJson.java
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta;
+
+import java.io.IOException;
+import java.io.Reader;
+
+import com.att.inno.env.Env;
+import com.att.inno.env.TimeTaken;
+import com.att.rosetta.InJson.State;
+
+public class InJson implements Parse<Reader, State> {
+ public Parsed<State> parse(Reader r, Parsed<State> parsed) throws ParseException {
+ // First things first, if there's a "leftover" event, process that immediately
+ State state = (State)parsed.state;
+ if(state.unsent > 0) {
+ parsed.event = state.unsent;
+ state.unsent = 0;
+ return parsed;
+ }
+
+ int ch;
+ char c;
+ StringBuilder sb = parsed.sb;
+ boolean inQuotes = false, escaped = false;
+ boolean go = true;
+ try {
+ // Gather data from Reader, looking for special characters when not in Quotes
+ while(go && (ch=r.read())>=0) {
+ if(state.braces>=0 || ch==Parse.START_OBJ) { // ignore garbage/whitespace before content
+ c=(char)ch;
+ // Character is a quote.
+ if(c=='"') {
+ if(inQuotes) {
+ if(escaped) { // if escaped Quote, add to data.
+ sb.append(c);
+ escaped = false;
+ } else {
+ inQuotes = false;
+ }
+ } else {
+ parsed.isString=true;
+ inQuotes = true;
+ }
+ } else { // Not a Quote
+ if(inQuotes) {
+ if(c=='\\') {
+ if(escaped) {
+ sb.append("\\\\");
+ escaped = false;
+ } else {
+ escaped = true;
+ }
+ } else {
+ sb.append(c);
+ }
+ } else {
+ switch(c) {
+ case ':':
+ parsed.dataIsName();
+ parsed.isString = false;
+ break;
+ case Parse.START_OBJ:
+ if(state.braces++ == 0) {
+ parsed.event = START_DOC;
+ state.unsent = c;
+ } else {
+ parsed.event = c;
+ }
+ go = false;
+ break;
+ case Parse.END_OBJ:
+ if(--state.braces == 0) {
+ parsed.event = c;
+ state.unsent = END_DOC;
+ } else {
+ parsed.event = c;
+ }
+ go = false;
+ break;
+ // These three end the data gathering, and send it along with the event that is ending the data gathering
+ case Parse.NEXT:
+ if(parsed.name.startsWith("__")) {
+ parsed.event = Parse.ATTRIB;
+ parsed.name = parsed.name.substring(2);
+ } else {
+ parsed.event = c;
+ }
+ go = false;
+ break;
+ case Parse.START_ARRAY:
+ case Parse.END_ARRAY:
+ parsed.event = c;
+ go = false;
+ break;
+
+ // The Escape Sequence, for Quote marks within Quotes
+ case '\\':
+ // Ignore these, unless within quotes, at which point data-gather
+ case ' ':
+ case '\b':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ break;
+ // Normal data... gather it
+ default:
+ sb.append(c);
+ }
+ }
+ }
+ }
+ }
+ return parsed;
+ } catch (IOException e) {
+ throw new ParseException(e);
+ }
+ }
+
+ public static class State {
+ public int braces = 0;
+ public char unsent = 0;
+ }
+
+// @Override
+ public Parsed<State> newParsed() {
+ return new Parsed<State>(new State()); // no State needed
+ }
+
+// @Override
+ public TimeTaken start(Env env) {
+ return env.start("Rosetta JSON In", Env.JSON);
+ }
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/InXML.java b/rosetta/src/main/java/com/att/rosetta/InXML.java
new file mode 100644
index 0000000..1c56e14
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/InXML.java
@@ -0,0 +1,488 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+
+import com.att.inno.env.Env;
+import com.att.inno.env.TimeTaken;
+import com.att.rosetta.InXML.State;
+
+public class InXML implements Parse<Reader, State> {
+ // package on purpose
+ JaxInfo jaxInfo;
+
+ public InXML(JaxInfo jaxInfo) {
+ this.jaxInfo = jaxInfo;
+ }
+
+ public InXML(Class<?> cls, String ... rootNs) throws SecurityException, NoSuchFieldException, ClassNotFoundException, ParseException {
+ jaxInfo = JaxInfo.build(cls,rootNs);
+ }
+
+
+ // @Override
+ public Parsed<State> parse(Reader r, Parsed<State> parsed) throws ParseException {
+ State state = parsed.state;
+
+ // OK, before anything else, see if there is leftover processing, if so, do it!
+ if(state.unevaluated!=null) {
+ DerTag dt = state.unevaluated;
+ state.unevaluated = null;
+ if(!state.greatExp.eval(parsed, dt))return parsed;
+ }
+
+ if(state.hasAttributes()) {
+ Prop prop = state.pop();
+ parsed.event = Parse.ATTRIB;
+ parsed.name = prop.tag;
+ parsed.sb.append(prop.value);
+ parsed.isString=true;
+ return parsed;
+ }
+ int ch;
+ char c;
+ boolean inQuotes = false, escaped = false;
+
+ StringBuilder sb = parsed.sb, tempSB = new StringBuilder();
+ boolean go = true;
+
+ try {
+ while(go && (ch=r.read())>=0) {
+ c = (char)ch;
+ if(c == '"') {
+ if(state.greatExp instanceof LeafExpectations) { // within a set of Tags, make a Quote
+ sb.append(c);
+ } else {
+ if(inQuotes) {
+ if(escaped) {
+ sb.append('\\');
+ sb.append(c);
+ escaped = false;
+ } else {
+ inQuotes = false;
+ }
+ } else {
+ parsed.isString=true;
+ inQuotes = true;
+ }
+ }
+ } else if(inQuotes) {
+ sb.append(c);
+ } else if(c=='&') {
+ XmlEscape.xmlEscape(sb,r);
+ } else {
+ switch(c) {
+ case '<':
+ DerTag tag=new DerTag().parse(r, tempSB);
+ go = state.greatExp.eval(parsed, tag);
+ break;
+ default:
+ // don't add Whitespace to start of SB... saves removing later
+ if(sb.length()>0) {
+ sb.append(c);
+ } else if(!Character.isWhitespace(c)) {
+ sb.append(c);
+ }
+ }
+ }
+ }
+ return parsed;
+ } catch (IOException e) {
+ throw new ParseException(e);
+ }
+ }
+
+ public static final class DerTag {
+ public String name;
+ public boolean isEndTag;
+ public List<Prop> props;
+ private boolean isXmlInfo;
+ //private String ns;
+
+ public DerTag() {
+ name=null;
+ isEndTag = false;
+ props = null;
+ isXmlInfo = false;
+ }
+
+ public DerTag parse(Reader r, StringBuilder sb) throws ParseException {
+ int ch;
+ char c;
+ boolean inQuotes = false, escaped = false;
+ boolean go = true;
+ String tag = null;
+
+ try {
+ if((ch = r.read())<0) throw new ParseException("Reader content ended before complete");
+ if(ch=='?') {
+ isXmlInfo = true;
+ }
+ // TODO Check for !-- comments
+ do {
+ c=(char)ch;
+ if(c=='"') {
+ if(inQuotes) {
+ if(escaped) {
+ sb.append(c);
+ escaped = false;
+ } else {
+ inQuotes = false;
+ }
+ } else {
+ inQuotes = true;
+ }
+ } else if(inQuotes) {
+ sb.append(c);
+ } else {
+ switch(c) {
+ case '/':
+ isEndTag = true;
+ break;
+ case ' ':
+ endField(tag,sb);
+ tag = null;
+ break;
+ case '>':
+ endField(tag,sb);
+ go = false;
+ break;
+ case '=':
+ tag = sb.toString();
+ sb.setLength(0);
+ break;
+// case ':':
+// ns = sb.toString();
+// sb.setLength(0);
+// break;
+ case '?':
+ if(!isXmlInfo)sb.append(c);
+ break;
+ default:
+ sb.append(c);
+ }
+ }
+ } while(go && (ch=r.read())>=0);
+ } catch (IOException e) {
+ throw new ParseException(e);
+ }
+ return this;
+ }
+
+ private void endField(String tag, StringBuilder sb) {
+ if(name==null) {
+ name = sb.toString();
+ sb.setLength(0);
+ } else {
+ String value = sb.toString();
+ sb.setLength(0);
+ if(tag !=null && value != null) {
+ if(props==null)props = new ArrayList<Prop>();
+ props.add(new Prop(tag,value));
+ }
+ }
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(isEndTag?"End":"Start");
+ sb.append(" Tag\n");
+ sb.append(" Name: ");
+ sb.append(name);
+ if(props!=null) for(Prop p : props) {
+ sb.append("\n ");
+ sb.append(p.tag);
+ sb.append("=\"");
+ sb.append(p.value);
+ sb.append('"');
+ }
+ return sb.toString();
+ }
+ }
+
+ private static class ArrayState {
+ public boolean firstObj = true;
+ public boolean didNext = false;
+ }
+
+ public static class State {
+ public GreatExpectations greatExp;
+ public DerTag unevaluated;
+ public Stack<ArrayState> arrayInfo;
+ private List<Prop> attribs;
+ private int idx;
+ public State(JaxInfo ji, DerTag dt) throws ParseException {
+ greatExp = new RootExpectations(this, ji, null);
+ unevaluated = null;
+ attribs = null;;
+ }
+
+ public boolean hasAttributes() {
+ return attribs!=null && idx<attribs.size();
+ }
+
+ public void push(Prop prop) {
+ if(attribs==null) {
+ attribs = new ArrayList<Prop>();
+ idx = 0;
+ }
+ attribs.add(prop);
+ }
+
+ public Prop pop() {
+ Prop rv = null;
+ if(attribs!=null) {
+ rv = attribs.get(idx++);
+ if(idx>=attribs.size())attribs = null;
+ }
+ return rv;
+ }
+ }
+
+ private static abstract class GreatExpectations {
+ protected JaxInfo ji;
+ protected GreatExpectations prev;
+ private Map<String,String> ns;
+
+ public GreatExpectations(State state, JaxInfo curr, GreatExpectations prev, DerTag derTag) throws ParseException {
+ this.prev = prev;
+ ns = null;
+ ji = getDerived(state, curr,derTag);
+ }
+
+ public abstract boolean eval(Parsed<State> parsed, DerTag derTag) throws ParseException;
+
+ // Recursively look back for any namespaces
+ protected Map<String,String> getNS() {
+ if(ns!=null)return ns;
+ if(prev!=null) {
+ return prev.getNS();
+ }
+ return null;
+ }
+
+ private void addNS(Prop prop) {
+ Map<String,String> existingNS = getNS();
+ if(ns==null)ns = new HashMap<String,String>();
+ // First make a copy of previous NSs so that we have everything we need, but can overwrite, if necessary
+ if(existingNS!=null && ns!=existingNS) {
+ ns.putAll(ns);
+ }
+ ns.put(prop.tag, prop.value);
+ }
+
+ private JaxInfo getDerived(State state, JaxInfo ji, DerTag derTag) throws ParseException {
+ if(derTag==null)return ji;
+
+ List<Prop> props = derTag.props;
+
+ Prop derived = null;
+ if(props!=null) {
+ // Load Namespaces (if any)
+ for(Prop prop : props) {
+ if(prop.tag.startsWith("xmlns:")) {
+ addNS(prop);
+ }
+ }
+ for(Prop prop : props) {
+ if(prop.tag.endsWith(":type")) {
+ int idx = prop.tag.indexOf(':');
+ String potentialNS = "xmlns:"+prop.tag.substring(0,idx);
+ Map<String,String> ns = getNS();
+ boolean noNamespace = false;
+ if(ns==null) {
+ noNamespace = true;
+ } else {
+ String nsVal = ns.get(potentialNS);
+ if(nsVal==null) noNamespace = true;
+ else {
+ derived = new Prop(Parsed.EXTENSION_TAG,prop.value);
+ state.push(derived);
+ }
+ }
+ if(noNamespace) {
+ throw new ParseException(prop.tag + " utilizes an invalid Namespace prefix");
+ }
+ } else if(!prop.tag.startsWith("xmlns")) {
+ state.push(prop);
+ }
+ }
+ }
+ return derived==null?ji:ji.getDerived(derived.value);
+ }
+ }
+
+ private static class RootExpectations extends GreatExpectations {
+
+ public RootExpectations(State state, JaxInfo curr, GreatExpectations prev) throws ParseException {
+ super(state,curr,prev, null);
+ }
+
+ // @Override
+ public boolean eval(Parsed<State> parsed, DerTag derTag) throws ParseException {
+ if(derTag.isXmlInfo) {
+ parsed.event = START_DOC;
+ } else if(ji.name.equals(derTag.name)) {
+ if(derTag.isEndTag) {
+ parsed.event = END_DOC;
+ parsed.state.greatExp = prev;
+ } else {
+ //parsed.name = derTag.name;
+ parsed.event = START_OBJ;
+ parsed.state.greatExp = new ObjectExpectations(parsed.state,ji, this, false, derTag);
+ }
+ }
+ return false;
+ }
+ }
+
+ private static class ObjectExpectations extends GreatExpectations {
+ private boolean printName;
+
+ public ObjectExpectations(State state, JaxInfo curr, GreatExpectations prev, boolean printName, DerTag derTag) throws ParseException {
+ super(state, curr, prev, derTag);
+ this.printName=printName;
+ }
+
+ // @Override
+ public boolean eval(Parsed<State> parsed, DerTag derTag) throws ParseException {
+ if(derTag.isEndTag && ji.name.equals(derTag.name)) {
+ parsed.state.greatExp = prev;
+ parsed.event = END_OBJ;
+ if(printName)parsed.name = ji.name;
+ } else {
+ //Standard Members
+ for(JaxInfo memb : ji.members) {
+ if(memb.name.equals(derTag.name)) {
+ parsed.name = memb.name;
+ if(memb.isArray) {
+ parsed.state.unevaluated = derTag; // evaluate within Array Context
+ parsed.event = START_ARRAY;
+ parsed.state.greatExp = new ArrayExpectations(parsed.state,memb,this);
+ return false;
+ } else if(memb.isObject()) {
+ if(derTag.isEndTag) {
+ throw new ParseException("Unexpected End Tag </" + derTag.name + '>');
+ } else {
+ parsed.event = START_OBJ;
+
+ parsed.state.greatExp = new ObjectExpectations(parsed.state, memb,this,true,derTag);
+ return false;
+ }
+ } else { // a leaf
+ if(derTag.isEndTag) {
+ throw new ParseException("Misplaced End Tag </" + parsed.name + '>');
+ } else {
+ parsed.state.greatExp = new LeafExpectations(parsed.state,memb, this);
+ return true; // finish out Leaf without returning
+ }
+ }
+ }
+ }
+
+ throw new ParseException("Unexpected Tag <" + derTag.name + '>');
+ }
+ return false;
+ }
+ }
+
+ private static class LeafExpectations extends GreatExpectations {
+ public LeafExpectations(State state, JaxInfo curr, GreatExpectations prev) throws ParseException {
+ super(state, curr, prev, null);
+ }
+
+ // @Override
+ public boolean eval(Parsed<State> parsed, DerTag derTag) throws ParseException {
+ if(ji.name.equals(derTag.name) && derTag.isEndTag) {
+ parsed.event = NEXT;
+ parsed.isString = ji.isString;
+ parsed.state.greatExp = prev;
+ } else {
+ throw new ParseException("Expected </" + ji.name + '>');
+ }
+ return false;
+ }
+ }
+
+ private static class ArrayExpectations extends GreatExpectations {
+ public ArrayExpectations(State state, JaxInfo ji, GreatExpectations prev) throws ParseException {
+ super(state, ji, prev,null);
+ if(state.arrayInfo==null)state.arrayInfo=new Stack<ArrayState>();
+ state.arrayInfo.push(new ArrayState());
+ }
+ // @Override
+ public boolean eval(Parsed<State> parsed, DerTag derTag) throws ParseException {
+ if(ji.name.equals(derTag.name) && !derTag.isEndTag) {
+ if(ji.isObject()) {
+ if(derTag.isEndTag) {
+ throw new ParseException("Unexpected End Tag </" + derTag.name + '>');
+ } else {
+ ArrayState ai = parsed.state.arrayInfo.peek();
+ if(ai.firstObj || ai.didNext) {
+ ai.firstObj = false;
+ ai.didNext = false;
+ parsed.event = START_OBJ;
+ parsed.name=derTag.name;
+ parsed.state.greatExp = new ObjectExpectations(parsed.state,ji,this,true, derTag);
+ } else {
+ ai.didNext = true;
+ parsed.event = NEXT;
+ parsed.state.unevaluated = derTag;
+ }
+ }
+ } else { // a leave
+ if(derTag.isEndTag) {
+ throw new ParseException("Misplaced End Tag </" + parsed.name + '>');
+ } else {
+ parsed.state.greatExp = new LeafExpectations(parsed.state, ji, this);
+ return true; // finish out Leaf without returning
+ }
+ }
+ } else { // Tag now different... Array is done
+ parsed.state.unevaluated = derTag;
+ parsed.event=END_ARRAY;
+ parsed.state.greatExp = prev;
+ parsed.state.arrayInfo.pop();
+ }
+ return false;
+ }
+ }
+ // @Override
+ public Parsed<State> newParsed() throws ParseException {
+ return new Parsed<State>(new State(jaxInfo, null));
+ }
+
+ // @Override
+ public TimeTaken start(Env env) {
+ return env.start("Rosetta XML In", Env.XML);
+ }
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/JaxEval.java b/rosetta/src/main/java/com/att/rosetta/JaxEval.java
new file mode 100644
index 0000000..72a89f2
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/JaxEval.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta;
+
+public interface JaxEval{
+ public abstract JaxEval eval(Parsed<?> p) throws ParseException;
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/JaxInfo.java b/rosetta/src/main/java/com/att/rosetta/JaxInfo.java
new file mode 100644
index 0000000..23785af
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/JaxInfo.java
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlSchema;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+public class JaxInfo {
+ private static final String DEFAULT = "##default";
+ public static final int DATA = 0;
+ public static final int ARRAY = 1;
+ public static final int OBJECT = 2;
+
+ public final String name;
+ public final Class<?> clss;
+ public Map<String, JaxInfo> extensions; // Classes, which might be found at runtime, that extend this class. Lazy Instantiation
+ public final JaxInfo[] members;
+ public final boolean isArray;
+ public final boolean isString;
+ public final boolean required;
+ public final boolean nillable;
+ public String ns;
+ public boolean isObject() {return members!=null;}
+
+ private JaxInfo(String n, String ns, Class<?> c, JaxInfo[] members, boolean string, boolean array, boolean required, boolean nillable) {
+ name = n;
+ this.ns = ns;
+ clss = c;
+ this.members = members;
+ this.isString = string;
+ isArray = array;
+ this.required = required;
+ this.nillable = nillable;
+ extensions = null;
+ }
+
+
+ public int getType() {
+ if(isArray)return ARRAY;
+ else if(members!=null)return OBJECT;
+ return DATA;
+ }
+
+ public JaxInfo getDerived(String derivedName) {
+ JaxInfo derived;
+ // Lazy Instantiation
+ if(extensions == null) {
+ extensions = new HashMap<String,JaxInfo>();
+ derived = null;
+ } else {
+ derived = extensions.get(derivedName);
+ }
+
+ if(derived == null) {
+ //TODO for the moment, Classes are in same package
+ Package pkg = clss.getPackage();
+ try {
+ Class<?> dc = getClass().getClassLoader().loadClass(pkg.getName()+'.'+Character.toUpperCase(derivedName.charAt(0))+derivedName.substring(1));
+ derived = JaxInfo.build(dc, this); // Use this JAXInfo's name so the tags are correct
+ extensions.put(derivedName, derived);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ return derived;
+ }
+
+ public static JaxInfo get(JaxInfo[] fields, String name) {
+ for(JaxInfo f : fields) {
+ if(name.equals(f.name)) return f;
+ }
+ return null;
+ }
+
+ /**
+ * Build up JAXB Information (recursively)
+ *
+ * @param cls
+ * @param rootNns
+ * @return
+ * @throws SecurityException
+ * @throws NoSuchFieldException
+ * @throws ClassNotFoundException
+ * @throws ParseException
+ */
+ public static JaxInfo build(Class<?> cls, JaxInfo parent) throws NoSuchFieldException, ClassNotFoundException, ParseException {
+ return new JaxInfo(parent.name,parent.ns, cls,buildFields(cls,parent.ns),parent.isString, parent.isArray,parent.required,parent.nillable);
+ }
+ /**
+ * Build up JAXB Information (recursively)
+ *
+ * @param cls
+ * @param rootNns
+ * @return
+ * @throws SecurityException
+ * @throws NoSuchFieldException
+ * @throws ClassNotFoundException
+ * @throws ParseException
+ */
+ public static JaxInfo build(Class<?> cls, String ... rootNns) throws SecurityException, NoSuchFieldException, ClassNotFoundException, ParseException {
+ String defaultNS;
+ if(rootNns.length>0 && rootNns[0]!=null) {
+ defaultNS = rootNns[0];
+ } else {
+ Package pkg = cls.getPackage();
+ XmlSchema xs = pkg.getAnnotation(XmlSchema.class);
+ defaultNS = xs==null?"":xs.namespace();
+ }
+ String name;
+ if(rootNns.length>1) {
+ name = rootNns[1];
+ } else {
+ XmlRootElement xre = cls.getAnnotation(XmlRootElement.class);
+ if(xre!=null) {
+ name = xre.name();
+ } else {
+ XmlType xt = cls.getAnnotation(XmlType.class);
+ if(xt!=null) {
+ name=xt.name();
+ } else {
+ throw new ParseException("Need a JAXB Object with XmlRootElement, or stipulate in parms");
+ }
+ }
+ }
+
+ return new JaxInfo(name,defaultNS, cls,buildFields(cls,defaultNS),false,false,false,false);
+ }
+
+ // Build up the name and members of this particular class
+ // This is recursive, if a member is a JAXB Object as well.
+ private static JaxInfo[] buildFields(Class<?> clazz, String defaultNS) throws SecurityException, NoSuchFieldException, ClassNotFoundException {
+ ArrayList<JaxInfo> fields = null; // allow for lazy instantiation, because many structures won't have XmlType
+ Class<?> cls = clazz;
+ // Build up Method names from JAXB Annotations
+ XmlType xt;
+ while((xt = cls.getAnnotation(XmlType.class))!=null) {
+ if(fields==null)fields = new ArrayList<JaxInfo>();
+ for(String field : xt.propOrder()) {
+ if("".equals(field)) break; // odd bug. "" returned when no fields exist, rather than empty array
+ Field rf = cls.getDeclaredField(field);
+ Class<?> ft = rf.getType();
+
+ boolean required = false;
+ boolean nillable = false;
+ String xmlName = field;
+ String namespace = defaultNS;
+
+ XmlElement xe = rf.getAnnotation(XmlElement.class);
+ if(xe!=null) {
+ xmlName=xe.name();
+ required = xe.required();
+ nillable = false;
+ if(DEFAULT.equals(xmlName)) {
+ xmlName = field;
+ }
+ namespace = xe.namespace();
+ if(DEFAULT.equals(namespace)) {
+ namespace = defaultNS;
+ }
+ }
+ // If object is a List, then it is possible multiple, per XML/JAXB evaluation
+ if(ft.isAssignableFrom(List.class)) {
+ Type t = rf.getGenericType();
+ String classname = t.toString();
+ int start = classname.indexOf('<');
+ int end = classname.indexOf('>');
+ Class<?> genClass = Class.forName(classname.substring(start+1, end));
+ xe = genClass.getAnnotation(XmlElement.class);
+ if(xe!=null && !DEFAULT.equals(xe.namespace())) {
+ namespace = xe.namespace();
+ }
+ // add recursed recursed member, marked as array
+ fields.add(new JaxInfo(xmlName,namespace,genClass,buildFields(genClass,namespace), genClass.equals(String.class),true,required,nillable));
+ } else {
+ boolean isString = ft.equals(String.class) || ft.equals(XMLGregorianCalendar.class);
+ // add recursed member
+ fields.add(new JaxInfo(xmlName,namespace,ft,buildFields(ft,namespace),isString,false,required,nillable));
+ }
+ }
+ cls = cls.getSuperclass();
+ };
+ if(fields!=null) {
+ JaxInfo[] rv = new JaxInfo[fields.size()];
+ fields.toArray(rv);
+ return rv;
+ } else {
+ return null;
+ }
+ }
+
+
+ public StringBuilder dump(StringBuilder sb, int idx) {
+ for(int i=0;i<idx;++i)sb.append(' ');
+ sb.append("Field ");
+ sb.append(name);
+ sb.append(" [");
+ sb.append(clss.getName());
+ sb.append("] ");
+ if(isArray)sb.append(" (array)");
+ if(required)sb.append(" (required)");
+ if(nillable)sb.append(" (nillable)");
+ if(members!=null) {
+ for(JaxInfo f : members) {
+ sb.append('\n');
+ f.dump(sb,idx+2);
+ }
+ }
+ return sb;
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Structure of ");
+ sb.append(clss.getName());
+ sb.append('\n');
+ dump(sb,2);
+ return sb.toString();
+ }
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/JaxSet.java b/rosetta/src/main/java/com/att/rosetta/JaxSet.java
new file mode 100644
index 0000000..515c2c1
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/JaxSet.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * For specific XML class, quickly find a Setter Method which will load the object
+ *
+ * Object type of Setter must match String at this time.
+ *
+ *
+ * @param <T>
+ */
+public class JaxSet<T> {
+ private static Map<Class<?>,JaxSet<?>> jsets = new HashMap<Class<?>,JaxSet<?>>();
+ private Map<String,Setter<T>> members;
+
+ private JaxSet(Class<?> cls) {
+ members = new TreeMap<String, Setter<T>>();
+ XmlType xmltype = cls.getAnnotation(XmlType.class);
+ Class<?> paramType[] = new Class[] {String.class};
+ for(String str : xmltype.propOrder()) {
+ try {
+ String setName = "set" + Character.toUpperCase(str.charAt(0)) + str.subSequence(1, str.length());
+ Method meth = cls.getMethod(setName,paramType );
+ if(meth!=null) {
+ members.put(str, new Setter<T>(meth) {
+ public void set(T o, Object t) throws ParseException {
+ try {
+ this.meth.invoke(o, t);
+ } catch (Exception e) {
+ throw new ParseException(e);
+ }
+ }
+ });
+ }
+ } catch (Exception e) {
+ // oops
+ }
+ }
+ }
+
+ public static abstract class Setter<O> {
+ protected final Method meth;
+ public Setter(Method meth) {
+ this.meth = meth;
+ }
+ public abstract void set(O o, Object obj) throws ParseException;
+ }
+
+ public static <X> JaxSet<X> get(Class<?> cls) {
+ synchronized(jsets) {
+ @SuppressWarnings("unchecked")
+ JaxSet<X> js = (JaxSet<X>)jsets.get(cls);
+ if(js == null) {
+ jsets.put(cls, js = new JaxSet<X>(cls));
+ }
+ return js;
+ }
+ }
+
+ public Setter<T> get(String key) {
+ return members.get(key);
+ }
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/Ladder.java b/rosetta/src/main/java/com/att/rosetta/Ladder.java
new file mode 100644
index 0000000..95f5174
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/Ladder.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta;
+
+
+/**
+ * A Ladder is a Stack like Storage Class, but where you can ascend and descend while
+ * the elements exists.
+ *
+ * Like an extension ladder, you can make taller as you go
+ *
+ *
+ */
+public class Ladder<T> {
+ public static final int DEFAULT_INIT_SIZE=8;
+ private final int init_size;
+ private int rung; // as in ladder
+ private Object[] struts;
+
+ public Ladder() {
+ rung=0;
+ init_size = DEFAULT_INIT_SIZE;
+ struts=new Object[init_size];
+ }
+
+ public Ladder(int initSize) {
+ rung=0;
+ init_size = initSize;
+ struts=new Object[init_size];
+ }
+
+ public void bottom() {
+ rung = 0;
+ }
+
+ public void top() {
+ rung = struts.length-1;
+ while(rung>0 && struts[rung]==null)--rung;
+ }
+
+ public int howHigh() {
+ return rung;
+ }
+
+ public void jumpTo(int rung) {
+ if(rung>=struts.length) {
+ Object[] temp = new Object[init_size*((rung/init_size)+1)];
+ System.arraycopy(struts, 0, temp, 0, struts.length);
+ struts = temp;
+ }
+ this.rung = rung;
+ }
+
+ public int height() {
+ return struts.length;
+ }
+
+ public void cutTo(int rungs) {
+ Object[] temp = new Object[rungs];
+ System.arraycopy(struts, 0, temp, 0, Math.min(rungs, struts.length));
+ struts = temp;
+ }
+
+ public void ascend() {
+ ++rung;
+ if(rung>=struts.length) {
+ Object[] temp = new Object[struts.length+init_size];
+ System.arraycopy(struts, 0, temp, 0, struts.length);
+ struts = temp;
+ }
+ }
+
+ public void descend() {
+ --rung;
+ }
+
+ @SuppressWarnings("unchecked")
+ public T peek() {
+ return (T)struts[rung];
+ }
+
+ public void push(T t) {
+ struts[rung]=t;
+ }
+
+ @SuppressWarnings("unchecked")
+ public T pop() {
+ T t = (T)struts[rung];
+ struts[rung]=null;
+ return t;
+ }
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/Marshal.java b/rosetta/src/main/java/com/att/rosetta/Marshal.java
new file mode 100644
index 0000000..52c97c6
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/Marshal.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta;
+
+import java.util.Iterator;
+
+import com.att.inno.env.Env;
+import com.att.inno.env.TimeTaken;
+
+public abstract class Marshal<T> implements Parse<T, Marshal.State> {
+
+ /* (non-Javadoc)
+ * @see com.att.rosetta.Parse#newParsed()
+ */
+ @Override
+ public Parsed<State> newParsed() throws ParseException {
+ return new Parsed<State>(new State());
+ }
+
+ @Override
+ public TimeTaken start(Env env) {
+ //TODO is a way to mark not-JSON?
+ return env.start("Rosetta Marshal", Env.JSON);
+ };
+
+ public static class State {
+ // Note: Need a STATEFUL stack... one that will remain stateful until marked as finished
+ // "finished" is know by Iterators with no more to do/null
+ // Thus the concept of "Ladder", which one ascends and decends
+ public Ladder<Iterator<?>> ladder = new Ladder<Iterator<?>>();
+ public boolean smallest = true;
+ }
+
+ public static final Iterator<Void> DONE_ITERATOR = new Iterator<Void>() {
+ @Override
+ public boolean hasNext() {
+ return false;
+ }
+
+ @Override
+ public Void next() {
+ return null;
+ }
+
+ @Override
+ public void remove() {
+ }
+ };
+
+ /**
+ * Typical definition of Done is when Iterator in Ladder is "DONE_ITERATOR"
+ *
+ * It is important, however, that the "Ladder Rung" is set to the right level.
+ *
+ * @param state
+ * @return
+ */
+ public boolean amFinished(State state) {
+ return DONE_ITERATOR.equals(state.ladder.peek());
+ }
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/Nulls.java b/rosetta/src/main/java/com/att/rosetta/Nulls.java
new file mode 100644
index 0000000..74cc56e
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/Nulls.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+
+import com.att.inno.env.Env;
+import com.att.inno.env.TimeTaken;
+
+public class Nulls {
+ public static final Parse<Reader, ?> IN = new Parse<Reader, Void>() {
+
+ // @Override
+ public Parsed<Void> parse(Reader r, Parsed<Void> parsed)throws ParseException {
+ parsed.event = Parse.END_DOC;
+ return parsed;
+ }
+
+ // @Override
+ public Parsed<Void> newParsed() {
+ Parsed<Void> parsed = new Parsed<Void>();
+ parsed.event = Parse.END_DOC;
+ return parsed;
+ }
+
+ // @Override
+ public TimeTaken start(Env env) {
+ return env.start("IN", Env.SUB);
+ }
+
+ };
+
+ public static final Out OUT = new Out() {
+
+ // @Override
+ public <IN,S> void extract(IN in, Writer writer, Parse<IN, S> parse, boolean ... options)throws IOException, ParseException {
+ }
+ @Override
+ public String logName() {
+ return "Rosetta NULL";
+ }
+
+
+ };
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/Out.java b/rosetta/src/main/java/com/att/rosetta/Out.java
new file mode 100644
index 0000000..c2ad448
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/Out.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+
+public abstract class Out {
+ public abstract<IN,S> void extract(IN in, Writer writer, Parse<IN, S> parse, boolean ... options) throws IOException, ParseException;
+
+ public<IN,S> void extract(IN in, OutputStream os, Parse<IN, S> parse, boolean ... options) throws IOException, ParseException {
+ Writer w = new OutputStreamWriter(os);
+ try {
+ extract(in, w, parse, options);
+ } finally {
+ w.flush();
+ }
+ }
+
+ public abstract String logName();
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/OutJax.java b/rosetta/src/main/java/com/att/rosetta/OutJax.java
new file mode 100644
index 0000000..ec04f43
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/OutJax.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta;
+
+import java.io.IOException;
+import java.io.Writer;
+
+public class OutJax extends Out {
+ private JaxEval jaxEval;
+
+ public OutJax(JaxEval je) {
+ this.jaxEval = je;
+ }
+
+ @Override
+ public <IN,S> void extract(IN in, Writer writer, Parse<IN, S> parse, boolean... options) throws IOException, ParseException {
+ Parsed<S> p = parse.newParsed();
+ JaxEval je = this.jaxEval;
+ while((p = parse.parse(in,p.reuse())).valid()) {
+ if(je==null)throw new ParseException("Incomplete content");
+ je = je.eval(p);
+ }
+
+ }
+
+ @Override
+ public String logName() {
+ return "Rosetta JAX";
+ }
+
+
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/OutJson.java b/rosetta/src/main/java/com/att/rosetta/OutJson.java
new file mode 100644
index 0000000..98dd162
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/OutJson.java
@@ -0,0 +1,234 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Stack;
+
+import com.att.inno.env.util.IndentPrintWriter;
+
+public class OutJson extends Out {
+
+ @Override
+ public<IN,S> void extract(IN in, Writer writer, Parse<IN, S> prs, boolean ... options) throws IOException, ParseException {
+ Parsed<S> p = prs.newParsed();
+ IndentPrintWriter ipw;
+ if(options.length>0 && options[0]) { // is Pretty
+ ipw = writer instanceof IndentPrintWriter?(IndentPrintWriter)writer:new IndentPrintWriter(writer);
+ writer = ipw;
+ } else {
+ ipw = null;
+ }
+
+ // If it's a fragment, print first Object Name. If root Object, skip first name
+ Stack<LevelStack> jsonLevel = new Stack<LevelStack>();
+ jsonLevel.push(new LevelStack(options.length>1 && options[1]));
+ boolean print = true, hadData=false;
+ char afterName=0, beforeName=0, maybe = 0, prev=0;
+
+ int count = 0;
+ while((p = prs.parse(in,p.reuse())).valid()) {
+ ++count;
+ switch(p.event) {
+ case 1:
+ continue;
+ case 2:
+ if(count==2) { // it's empty, write open/close on it's own
+ writer.append('{');
+ writer.append('}');
+ }
+ writer.flush();
+ return;
+ case '{':
+ afterName = '{';
+ if(jsonLevel.peek().printObjectName) {
+ print = true;
+ } else { // don't print names on first
+ print=false;
+ }
+ maybe=jsonLevel.peek().listItem();
+ jsonLevel.push(new LevelStack(true));
+ break;
+ case '}':
+ if(p.hasData()) { // if we have data, we print that, so may need to prepend a comma.
+ maybe = jsonLevel.peek().listItem();
+ } else { // No data means just print,
+ p.name = ""; // XML tags come through with names, but no data
+ }
+ print = true;
+ jsonLevel.pop();
+ afterName = p.event;
+ break;
+ case '[':
+ afterName = p.event;
+ if((prev==',' && !hadData) || prev==']')maybe=',';
+ else maybe = jsonLevel.peek().listItem();
+
+ jsonLevel.push(new LevelStack(false));
+ print=true;
+ break;
+ case ']':
+ afterName = p.event;
+ if(p.hasData()) {
+ if(prev==',' && !hadData)maybe=',';
+ else maybe = jsonLevel.peek().listItem();
+ } else {
+ p.name = ""; // XML tags come through with names, but no data
+ }
+ jsonLevel.pop();
+
+ print = true;
+ break;
+ case 3:
+ case ',':
+ if(!p.hasData()) {
+ p.isString=false;
+ print=false;
+ } else {
+ maybe=jsonLevel.peek().listItem();
+ print = true;
+ }
+ break;
+ default:
+ print = true;
+ }
+
+ if(maybe!=0) {
+ if(ipw==null)writer.append(maybe);
+ else ipw.println(maybe);
+ maybe = 0;
+ }
+
+ if(beforeName!=0) {
+ if(ipw==null)writer.append(beforeName);
+ else ipw.println(beforeName);
+ beforeName = 0;
+ }
+ if(print) {
+ if(p.hasName()) {
+ writer.append('"');
+ if(p.event==3)writer.append("__");
+ writer.append(p.name);
+ writer.append("\":");
+ }
+ if(p.hasData()) {
+ if(p.isString) {
+ writer.append('"');
+ escapedWrite(writer, p.sb);
+ writer.append('"');
+ } else if(p.sb.length()>0) {
+ writer.append(p.sb);
+ }
+ }
+ }
+ if(afterName!=0) {
+ if(ipw==null)writer.append(afterName);
+ else {
+ switch(afterName) {
+ case '{':
+ ipw.println(afterName);
+ ipw.inc();
+ break;
+ case '}':
+ ipw.dec();
+ ipw.println();
+ ipw.print(afterName);
+ break;
+ case ']':
+ if(prev=='}' || prev==',')ipw.println();
+ ipw.dec();
+ ipw.print(afterName);
+ break;
+
+ case ',':
+ ipw.println(afterName);
+ break;
+ default:
+ ipw.print(afterName);
+ }
+ }
+ afterName = 0;
+ }
+
+ if(ipw!=null) {
+ switch(p.event) {
+ case '[':
+ ipw.inc();
+ ipw.println();
+ break;
+ }
+ }
+ prev = p.event;
+ hadData = p.hasData();
+
+ }
+ writer.flush();
+ }
+
+ private void escapedWrite(Writer writer, StringBuilder sb) throws IOException {
+ char c;
+ for(int i=0;i<sb.length();++i) {
+ switch(c=sb.charAt(i)) {
+ case '\\':
+ writer.append(c);
+ if(i<sb.length()) {
+ c=sb.charAt(++i);
+ writer.append(c);
+ }
+ break;
+ case '"':
+ writer.append('\\');
+ // Passthrough on purpose
+ default:
+ writer.append(c);
+ }
+ }
+
+
+ }
+
+ @Override
+ public String logName() {
+ return "Rosetta JSON";
+ }
+
+ private static class LevelStack {
+ public boolean printObjectName=false;
+ private boolean first_n_List=true;
+
+ public LevelStack(boolean printObjectName) {
+ this.printObjectName = printObjectName;
+ }
+
+ public char listItem() {
+ if(first_n_List) {
+ first_n_List=false;
+ return 0;
+ } else {
+ return ',';
+ }
+ }
+ }
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/OutRaw.java b/rosetta/src/main/java/com/att/rosetta/OutRaw.java
new file mode 100644
index 0000000..1a5d8d0
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/OutRaw.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta;
+
+import java.io.IOException;
+import java.io.Writer;
+
+public class OutRaw extends Out{
+
+ @Override
+ public<IN,S> void extract(IN in, Writer writer, Parse<IN,S> prs, boolean ... options) throws IOException, ParseException {
+ Parsed<S> p = prs.newParsed();
+
+ while((p = prs.parse(in,p.reuse())).valid()) {
+ writer.append(p.toString());
+ writer.append('\n');
+ }
+ }
+
+ @Override
+ public String logName() {
+ return "Rosetta RAW";
+ }
+
+
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/OutXML.java b/rosetta/src/main/java/com/att/rosetta/OutXML.java
new file mode 100644
index 0000000..cfef897
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/OutXML.java
@@ -0,0 +1,227 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+
+import com.att.inno.env.util.IndentPrintWriter;
+import com.att.inno.env.util.StringBuilderWriter;
+
+public class OutXML extends Out{
+ private static final String XMLNS_XSI = "xmlns:xsi";
+ public static final String XML_INFO = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
+ public static final String XML_SCHEMA_INSTANCE = "http://www.w3.org/2001/XMLSchema-instance";
+
+ private String root;
+ private List<Prop> props;
+
+ public OutXML(String root, String ... params) {
+ this.root = root;
+ props = new ArrayList<Prop>();
+ for(String p : params) {
+ String[] tv=p.split("=");
+ if(tv.length==2)
+ props.add(new Prop(tv[0],tv[1]));
+ }
+ }
+
+ public OutXML(JaxInfo jaxInfo) {
+ this(jaxInfo.name,genNS(jaxInfo));
+ }
+
+ public OutXML(InXML inXML) {
+ this(inXML.jaxInfo.name,genNS(inXML.jaxInfo));
+ }
+
+ private static String[] genNS(JaxInfo jaxInfo) {
+ return new String[] {"xmlns=" + jaxInfo.ns};
+ }
+
+
+ @Override
+ public<IN,S> void extract(IN in, Writer writer, Parse<IN,S> prs, boolean ... options) throws IOException, ParseException {
+ Parsed<S> p = prs.newParsed();
+ Stack<Level> stack = new Stack<Level>();
+ // If it's an IndentPrintWriter, it is pretty printing.
+ boolean pretty = (options.length>0&&options[0]);
+
+ IndentPrintWriter ipw;
+ if(pretty) {
+ if(writer instanceof IndentPrintWriter) {
+ ipw = (IndentPrintWriter)writer;
+ } else {
+ writer = ipw = new IndentPrintWriter(writer);
+ }
+ } else {
+ ipw=null;
+ }
+ boolean closeTag = false;
+ Level level = new Level(null);
+ while((p = prs.parse(in,p.reuse())).valid()) {
+ if(!p.hasName() && level.multi!=null) {
+ p.name=level.multi;
+ }
+ if(closeTag && p.event!=Parse.ATTRIB) {
+ writer.append('>');
+ if(pretty)writer.append('\n');
+ closeTag = false;
+ }
+ switch(p.event) {
+ case Parse.START_DOC:
+ if(!(options.length>1&&options[1])) // if not a fragment, print XML Info data
+ if(pretty)ipw.println(XML_INFO);
+ else writer.append(XML_INFO);
+ break;
+ case Parse.END_DOC:
+ break;
+ case Parse.START_OBJ:
+ stack.push(level);
+ level = new Level(level);
+ if(p.hasName()) {
+ closeTag = tag(writer,level.sbw,pretty,pretty,p.name,null);
+ } else if(root!=null && stack.size()==1) { // first Object
+ closeTag = tag(writer,level.sbw,pretty,pretty,root,null);
+ // Write Root Props
+ for(Prop prop : props) {
+ attrib(writer,pretty,prop.tag, prop.value,level);
+ }
+ }
+ if(pretty)ipw.inc();
+ break;
+ case Parse.END_OBJ:
+ if(p.hasData())
+ closeTag = tag(writer,writer,pretty,false,p.name, XmlEscape.convert(p.sb));
+ if(pretty)ipw.dec();
+ writer.append(level.sbw.getBuffer());
+ level = stack.pop();
+ break;
+ case Parse.START_ARRAY:
+ level.multi = p.name;
+ break;
+ case Parse.END_ARRAY:
+ if(p.hasData())
+ closeTag = tag(writer,writer,pretty,false, p.name, XmlEscape.convert(p.sb));
+ level.multi=null;
+ break;
+ case Parse.ATTRIB:
+ if(p.hasData())
+ attrib(writer,pretty,p.name, XmlEscape.convert(p.sb), level);
+ break;
+ case Parse.NEXT:
+ if(p.hasData())
+ closeTag = tag(writer,writer,pretty, false,p.name, XmlEscape.convert(p.sb));
+ break;
+ }
+ }
+ writer.append(level.sbw.getBuffer());
+ writer.flush();
+ }
+
+ private class Level {
+ public final StringBuilderWriter sbw;
+ public String multi;
+ private Level prev;
+ private Map<String,String> nses;
+
+ public Level(Level level) {
+ sbw = new StringBuilderWriter();
+ multi = null;
+ prev = level;
+ }
+
+ public boolean hasPrinted(String ns, String value, boolean create) {
+ boolean rv = false;
+ if(nses==null) {
+ if(prev!=null)rv = prev.hasPrinted(ns, value, false);
+ } else {
+ String v = nses.get(ns);
+ return value.equals(v); // note: accomodates not finding NS as well
+ }
+
+ if(create && !rv) {
+ if(nses == null) nses = new HashMap<String,String>();
+ nses.put(ns, value);
+ }
+ return rv;
+ }
+
+
+
+ }
+
+ private boolean tag(Writer fore, Writer aft, boolean pretty, boolean returns, String tag, String data) throws IOException {
+ fore.append('<');
+ fore.append(tag);
+ if(data!=null) {
+ fore.append('>'); // if no data, it may need some attributes...
+ fore.append(data);
+ if(returns)fore.append('\n');
+ }
+ aft.append("</");
+ aft.append(tag);
+ aft.append(">");
+ if(pretty)aft.append('\n');
+ return data==null;
+ }
+
+ private void attrib(Writer fore, boolean pretty, String tag, String value, Level level) throws IOException {
+ String realTag = tag.startsWith("__")?tag.substring(2):tag; // remove __
+ if(realTag.equals(Parsed.EXTENSION_TAG)) { // Convert Derived name into XML defined Inheritance
+ fore.append(" xsi:type=\"");
+ fore.append(value);
+ fore.append('"');
+ if(!level.hasPrinted(XMLNS_XSI, XML_SCHEMA_INSTANCE,true)) {
+ fore.append(' ');
+ fore.append(XMLNS_XSI);
+ fore.append("=\"");
+ fore.append(XML_SCHEMA_INSTANCE);
+ fore.append("\"");
+ }
+ } else {
+ if(realTag.startsWith("xmlns:") ) {
+ if(level.hasPrinted(realTag, value, true)) {
+ return;
+ }
+ }
+ fore.append(' ');
+ fore.append(realTag);
+ fore.append("=\"");
+ fore.append(value);
+ fore.append('"');
+ }
+ }
+
+ @Override
+ public String logName() {
+ return "Rosetta XML";
+ }
+
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/Parse.java b/rosetta/src/main/java/com/att/rosetta/Parse.java
new file mode 100644
index 0000000..93415b4
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/Parse.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta;
+
+import com.att.inno.env.Env;
+import com.att.inno.env.TimeTaken;
+
+public interface Parse<IN, S> {
+ public Parsed<S> parse(IN in, Parsed<S> parsed) throws ParseException;
+
+ // EVENTS
+ public static final char NONE = 0;
+ public static final char START_DOC = 1;
+ public static final char END_DOC = 2;
+ public static final char ATTRIB = 3;
+
+ public static final char NEXT = ',';
+ public static final char START_OBJ = '{';
+ public static final char END_OBJ = '}';
+ public static final char START_ARRAY = '[';
+ public static final char END_ARRAY = ']';
+
+ public Parsed<S> newParsed() throws ParseException;
+ public TimeTaken start(Env env);
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/ParseException.java b/rosetta/src/main/java/com/att/rosetta/ParseException.java
new file mode 100644
index 0000000..f086d00
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/ParseException.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta;
+
+public class ParseException extends Exception {
+ private static final long serialVersionUID = 7808836939102997012L;
+
+ public ParseException() {
+ }
+
+ public ParseException(String message) {
+ super(message);
+ }
+
+ public ParseException(Throwable cause) {
+ super(cause);
+ }
+
+ public ParseException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/Parsed.java b/rosetta/src/main/java/com/att/rosetta/Parsed.java
new file mode 100644
index 0000000..412251f
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/Parsed.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta;
+
+
+public class Parsed<S> {
+ public static final String EXTENSION_TAG="extension";
+
+ public boolean isString;
+
+ public StringBuilder sb;
+ public char event;
+ public String name;
+ public S state;
+
+ public Parsed() {
+ this(null);
+ }
+
+ // Package on purpose
+ Parsed(S theState) {
+ sb = new StringBuilder();
+ isString = false;
+ event = Parse.NONE;
+ name = "";
+ state = theState;
+ }
+
+ public boolean valid() {
+ return event!=Parse.NONE;
+ }
+
+ public Parsed<S> reuse() {
+ isString=false;
+ sb.setLength(0);
+ event = Parse.NONE;
+ name = "";
+ // don't touch T...
+ return this;
+ }
+
+ public void dataIsName() {
+ name = sb.toString();
+ sb.setLength(0);
+ }
+
+ public boolean hasName() {
+ return name.length()>0;
+ }
+
+ public boolean hasData() {
+ return sb.length()>0;
+ }
+
+ public String toString() {
+ StringBuilder sb2 = new StringBuilder();
+ if(event<40)sb2.append((int)event);
+ else sb2.append(event);
+ sb2.append(" - ");
+ sb2.append(name);
+ if(sb.length()>0) {
+ sb2.append(" : ");
+ if(isString)sb2.append('"');
+ sb2.append(sb);
+ if(isString)sb2.append('"');
+ }
+ return sb2.toString();
+ }
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/Prop.java b/rosetta/src/main/java/com/att/rosetta/Prop.java
new file mode 100644
index 0000000..78a8125
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/Prop.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta;
+
+class Prop {
+ public String tag;
+ public String value;
+ public Prop(String t, String v) {
+ tag = t;
+ value =v;
+ }
+
+ public Prop(String t_equals_v) {
+ String[] tv = t_equals_v.split("=");
+ if(tv.length>1) {
+ tag = tv[0];
+ value = tv[1];
+ }
+ }
+
+ public String toString() {
+ return tag + '=' + value;
+ }
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/Saved.java b/rosetta/src/main/java/com/att/rosetta/Saved.java
new file mode 100644
index 0000000..bc7e106
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/Saved.java
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.List;
+
+import com.att.inno.env.Env;
+import com.att.inno.env.TimeTaken;
+import com.att.rosetta.Saved.State;
+
+/**
+ * An Out Object that will save off produced Parsed Stream and
+ * a Parse (In) Object that will reproduce Parsed Stream on demand
+ *
+ *
+ */
+public class Saved extends Out implements Parse<Reader, State>{
+ private static final String ROSETTA_SAVED = "Rosetta Saved";
+ private final static int INIT_SIZE=128;
+ private Content content[];
+ private int idx;
+ private boolean append = false;
+
+ /**
+ * Read from Parsed Stream and save
+ */
+ // @Override
+ public<IN,S> void extract(IN in, Writer ignore, Parse<IN,S> parser, boolean ... options) throws IOException, ParseException {
+ Parsed<S> p = parser.newParsed();
+ if(!append) {
+ // reuse array if not too big
+ if(content==null||content.length>INIT_SIZE*3) {
+ content = new Content[INIT_SIZE];
+ idx = -1;
+ } else do {
+ content[idx]=null;
+ } while(--idx>=0);
+ }
+
+ // Note: idx needs to be -1 on initialization and no appendages
+ while((p = parser.parse(in,p.reuse())).valid()) {
+ if(!(append && (p.event==START_DOC || p.event==END_DOC))) { // skip any start/end of document in appendages
+ if(++idx>=content.length) {
+ Content temp[] = new Content[content.length*2];
+ System.arraycopy(content, 0, temp, 0, idx);
+ content = temp;
+ }
+ content[idx]= new Content(p);
+ }
+ }
+ }
+
+ // @Override
+ public Parsed<State> parse(Reader ignore, Parsed<State> parsed) throws ParseException {
+ int i;
+ if((i=parsed.state.count++)<=idx)
+ content[i].load(parsed);
+ else
+ parsed.event = Parse.NONE;
+ return parsed;
+ }
+
+ public Content[] cut(char event, int count) {
+ append = true;
+ for(int i=idx;i>=0;--i) {
+ if(content[i].event==event) count--;
+ if(count==0) {
+ Content[] appended = new Content[idx-i+1];
+ System.arraycopy(content, i, appended, 0, appended.length);
+ idx = i-1;
+ return appended;
+ }
+ }
+ return new Content[0];
+ }
+
+ public void paste(Content[] appended) {
+ if(appended!=null) {
+ if(idx+appended.length>content.length) {
+ Content temp[] = new Content[content.length*2];
+ System.arraycopy(content, 0, temp, 0, idx);
+ content = temp;
+ }
+ System.arraycopy(appended,0,content,idx+1,appended.length);
+ idx+=appended.length;
+ }
+ this.append = false;
+ }
+
+ public static class State {
+ public int count = 0;
+ }
+
+ public static class Content {
+ private boolean isString;
+ private char event;
+ private String name;
+ private List<Prop> props;
+ private String str;
+
+ public Content(Parsed<?> p) {
+ isString = p.isString;
+ event = p.event;
+ name = p.name;
+ // avoid copying, because most elements don't have content
+ // Cannot set to "equals", because sb ends up being cleared (and reused)
+ str = p.sb.length()==0?null:p.sb.toString();
+ }
+
+ public void load(Parsed<State> p) {
+ p.isString = isString;
+ p.event = event;
+ p.name = name;
+ if(str!=null)
+ p.sb.append(str);
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(event);
+ sb.append(" - ");
+ sb.append(name);
+ sb.append(": ");
+ if(isString)sb.append('"');
+ sb.append(str);
+ if(isString)sb.append('"');
+ sb.append(' ');
+ if(props!=null) {
+ boolean comma = false;
+ for(Prop prop : props) {
+ if(comma)sb.append(',');
+ else comma = true;
+ sb.append(prop.tag);
+ sb.append('=');
+ sb.append(prop.value);
+ }
+ }
+ return sb.toString();
+ }
+ }
+
+ //// @Override
+ public Parsed<State> newParsed() {
+ Parsed<State> ps = new Parsed<State>(new State());
+ return ps;
+ }
+
+ /**
+ * Convenience function
+ * @param rdr
+ * @param in
+ * @throws IOException
+ * @throws ParseException
+ */
+ public<IN,S> void load(IN in, Parse<IN, S> parser) throws IOException, ParseException {
+ extract(in,(Writer)null, parser);
+ }
+
+
+ // @Override
+ public TimeTaken start(Env env) {
+ return env.start(ROSETTA_SAVED, 0);
+ }
+
+ @Override
+ public String logName() {
+ return ROSETTA_SAVED;
+ }
+
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/XmlEscape.java b/rosetta/src/main/java/com/att/rosetta/XmlEscape.java
new file mode 100644
index 0000000..c61a80d
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/XmlEscape.java
@@ -0,0 +1,373 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
+public class XmlEscape {
+ private XmlEscape() {}
+
+ private static final TreeMap<String,Integer> charMap; // see initialization at end
+ private static final TreeMap<Integer,String> intMap; // see initialization at end
+
+ public static void xmlEscape(StringBuilder sb, Reader r) throws ParseException {
+ try {
+ int c;
+ StringBuilder esc = new StringBuilder();
+ for(int cnt = 0;cnt<9 /*max*/; ++cnt) {
+ if((c=r.read())<0)throw new ParseException("Invalid Data: Unfinished Escape Sequence");
+ if(c!=';') {
+ esc.append((char)c);
+ } else { // evaluate
+ Integer i = charMap.get(esc.toString());
+ if(i==null) {
+ // leave in nasty XML format for now.
+ sb.append('&');
+ sb.append(esc);
+ sb.append(';');
+ } else {
+ sb.append((char)i.intValue());
+ }
+ break;
+ }
+ }
+
+
+ } catch (IOException e) {
+ throw new ParseException(e);
+ }
+ }
+
+ public static void xmlEscape(StringBuilder sb, int chr) {
+ sb.append('&');
+ sb.append(intMap.get(chr));
+ sb.append(';');
+ }
+
+ public static String convert(StringBuilder insb) {
+ int idx, ch;
+ StringBuilder sb=null;
+ for(idx=0;idx<insb.length();++idx) {
+ ch = insb.charAt(idx);
+ if(ch>=160 || ch==34 || ch==38 || ch==39 || ch==60 || ch==62) {
+ sb = new StringBuilder();
+ sb.append(insb,0,idx);
+ break;
+ }
+ }
+
+ if(sb==null)return insb.toString();
+
+ for(int i=idx;i<insb.length();++i) {
+ ch = insb.charAt(i);
+ if(ch<160) {
+ switch(ch) {
+ case 34: sb.append("&quot;"); break;
+ case 38: sb.append("&amp;"); break;
+ case 39: sb.append("&apos;"); break;
+ case 60: sb.append("&lt;"); break;
+ case 62: sb.append("&gt;"); break;
+ default:
+ sb.append((char)ch);
+ }
+ } else { // use map
+ String s = intMap.get(ch);
+ if(s==null)sb.append((char)ch);
+ else {
+ sb.append('&');
+ sb.append(s);
+ sb.append(';');
+ }
+ }
+ }
+ return sb.toString();
+ }
+
+ static {
+ charMap = new TreeMap<String, Integer>();
+ intMap = new TreeMap<Integer,String>();
+ charMap.put("quot", 34);
+ charMap.put("amp",38);
+ charMap.put("apos",39);
+ charMap.put("lt",60);
+ charMap.put("gt",62);
+ charMap.put("nbsp",160);
+ charMap.put("iexcl",161);
+ charMap.put("cent",162);
+ charMap.put("pound",163);
+ charMap.put("curren",164);
+ charMap.put("yen",165);
+ charMap.put("brvbar",166);
+ charMap.put("sect",167);
+ charMap.put("uml",168);
+ charMap.put("copy",169);
+ charMap.put("ordf",170);
+ charMap.put("laquo",171);
+ charMap.put("not",172);
+ charMap.put("shy",173);
+ charMap.put("reg",174);
+ charMap.put("macr",175);
+ charMap.put("deg",176);
+ charMap.put("plusmn",177);
+ charMap.put("sup2",178);
+ charMap.put("sup3",179);
+ charMap.put("acute",180);
+ charMap.put("micro",181);
+ charMap.put("para",182);
+ charMap.put("middot",183);
+ charMap.put("cedil",184);
+ charMap.put("sup1",185);
+ charMap.put("ordm",186);
+ charMap.put("raquo",187);
+ charMap.put("frac14",188);
+ charMap.put("frac12",189);
+ charMap.put("frac34",190);
+ charMap.put("iquest",191);
+ charMap.put("Agrave",192);
+ charMap.put("Aacute",193);
+ charMap.put("Acirc",194);
+ charMap.put("Atilde",195);
+ charMap.put("Auml",196);
+ charMap.put("Aring",197);
+ charMap.put("AElig",198);
+ charMap.put("Ccedil",199);
+ charMap.put("Egrave",200);
+ charMap.put("Eacute",201);
+ charMap.put("Ecirc",202);
+ charMap.put("Euml",203);
+ charMap.put("Igrave",204);
+ charMap.put("Iacute",205);
+ charMap.put("Icirc",206);
+ charMap.put("Iuml",207);
+ charMap.put("ETH",208);
+ charMap.put("Ntilde",209);
+ charMap.put("Ograve",210);
+ charMap.put("Oacute",211);
+ charMap.put("Ocirc",212);
+ charMap.put("Otilde",213);
+ charMap.put("Ouml",214);
+ charMap.put("times",215);
+ charMap.put("Oslash",216);
+ charMap.put("Ugrave",217);
+ charMap.put("Uacute",218);
+ charMap.put("Ucirc",219);
+ charMap.put("Uuml",220);
+ charMap.put("Yacute",221);
+ charMap.put("THORN",222);
+ charMap.put("szlig",223);
+ charMap.put("agrave",224);
+ charMap.put("aacute",225);
+ charMap.put("acirc",226);
+ charMap.put("atilde",227);
+ charMap.put("auml",228);
+ charMap.put("aring",229);
+ charMap.put("aelig",230);
+ charMap.put("ccedil",231);
+ charMap.put("egrave",232);
+ charMap.put("eacute",233);
+ charMap.put("ecirc",234);
+ charMap.put("euml",235);
+ charMap.put("igrave",236);
+ charMap.put("iacute",237);
+ charMap.put("icirc",238);
+ charMap.put("iuml",239);
+ charMap.put("eth",240);
+ charMap.put("ntilde",241);
+ charMap.put("ograve",242);
+ charMap.put("oacute",243);
+ charMap.put("ocirc",244);
+ charMap.put("otilde",245);
+ charMap.put("ouml",246);
+ charMap.put("divide",247);
+ charMap.put("oslash",248);
+ charMap.put("ugrave",249);
+ charMap.put("uacute",250);
+ charMap.put("ucirc",251);
+ charMap.put("uuml",252);
+ charMap.put("yacute",253);
+ charMap.put("thorn",254);
+ charMap.put("yuml",255);
+ charMap.put("OElig",338);
+ charMap.put("oelig",339);
+ charMap.put("Scaron",352);
+ charMap.put("scaron",353);
+ charMap.put("Yuml",376);
+ charMap.put("fnof",402);
+ charMap.put("circ",710);
+ charMap.put("tilde",732);
+ charMap.put("Alpha",913);
+ charMap.put("Beta",914);
+ charMap.put("Gamma",915);
+ charMap.put("Delta",916);
+ charMap.put("Epsilon",917);
+ charMap.put("Zeta",918);
+ charMap.put("Eta",919);
+ charMap.put("Theta",920);
+ charMap.put("Iota",921);
+ charMap.put("Kappa",922);
+ charMap.put("Lambda",923);
+ charMap.put("Mu",924);
+ charMap.put("Nu",925);
+ charMap.put("Xi",926);
+ charMap.put("Omicron",927);
+ charMap.put("Pi",928);
+ charMap.put("Rho",929);
+ charMap.put("Sigma",931);
+ charMap.put("Tau",932);
+ charMap.put("Upsilon",933);
+ charMap.put("Phi",934);
+ charMap.put("Chi",935);
+ charMap.put("Psi",936);
+ charMap.put("Omega",937);
+ charMap.put("alpha",945);
+ charMap.put("beta",946);
+ charMap.put("gamma",947);
+ charMap.put("delta",948);
+ charMap.put("epsilon",949);
+ charMap.put("zeta",950);
+ charMap.put("eta",951);
+ charMap.put("theta",952);
+ charMap.put("iota",953);
+ charMap.put("kappa",954);
+ charMap.put("lambda",955);
+ charMap.put("mu",956);
+ charMap.put("nu",957);
+ charMap.put("xi",958);
+ charMap.put("omicron",959);
+ charMap.put("pi",960);
+ charMap.put("rho",961);
+ charMap.put("sigmaf",962);
+ charMap.put("sigma",963);
+ charMap.put("tau",964);
+ charMap.put("upsilon",965);
+ charMap.put("phi",966);
+ charMap.put("chi",967);
+ charMap.put("psi",968);
+ charMap.put("omega",969);
+ charMap.put("thetasym",977);
+ charMap.put("upsih",978);
+ charMap.put("piv",982);
+ charMap.put("ensp",8194);
+ charMap.put("emsp",8195);
+ charMap.put("thinsp",8201);
+ charMap.put("zwnj",8204);
+ charMap.put("zwj",8205);
+ charMap.put("lrm",8206);
+ charMap.put("rlm",8207);
+ charMap.put("ndash",8211);
+ charMap.put("mdash",8212);
+ charMap.put("lsquo",8216);
+ charMap.put("rsquo",8217);
+ charMap.put("sbquo",8218);
+ charMap.put("ldquo",8220);
+ charMap.put("rdquo",8221);
+ charMap.put("bdquo",8222);
+ charMap.put("dagger",8224);
+ charMap.put("Dagger",8225);
+ charMap.put("bull",8226);
+ charMap.put("hellip",8230);
+ charMap.put("permil",8240);
+ charMap.put("prime",8242);
+ charMap.put("Prime",8243);
+ charMap.put("lsaquo",8249);
+ charMap.put("rsaquo",8250);
+ charMap.put("oline",8254);
+ charMap.put("frasl",8260);
+ charMap.put("euro",8364);
+ charMap.put("image",8465);
+ charMap.put("weierp",8472);
+ charMap.put("real",8476);
+ charMap.put("trade",8482);
+ charMap.put("alefsym",8501);
+ charMap.put("larr",8592);
+ charMap.put("uarr",8593);
+ charMap.put("rarr",8594);
+ charMap.put("darr",8595);
+ charMap.put("harr",8596);
+ charMap.put("crarr",8629);
+ charMap.put("lArr",8656);
+ charMap.put("uArr",8657);
+ charMap.put("rArr",8658);
+ charMap.put("dArr",8659);
+ charMap.put("hArr",8660);
+ charMap.put("forall",8704);
+ charMap.put("part",8706);
+ charMap.put("exist",8707);
+ charMap.put("empty",8709);
+ charMap.put("nabla",8711);
+ charMap.put("isin",8712);
+ charMap.put("notin",8713);
+ charMap.put("ni",8715);
+ charMap.put("prod",8719);
+ charMap.put("sum",8721);
+ charMap.put("minus",8722);
+ charMap.put("lowast",8727);
+ charMap.put("radic",8730);
+ charMap.put("prop",8733);
+ charMap.put("infin",8734);
+ charMap.put("ang",8736);
+ charMap.put("and",8743);
+ charMap.put("or",8744);
+ charMap.put("cap",8745);
+ charMap.put("cup",8746);
+ charMap.put("int",8747);
+ charMap.put("there4",8756);
+ charMap.put("sim",8764);
+ charMap.put("cong",8773);
+ charMap.put("asymp",8776);
+ charMap.put("ne",8800);
+ charMap.put("equiv",8801);
+ charMap.put("le",8804);
+ charMap.put("ge",8805);
+ charMap.put("sub",8834);
+ charMap.put("sup",8835);
+ charMap.put("nsub",8836);
+ charMap.put("sube",8838);
+ charMap.put("supe",8839);
+ charMap.put("oplus",8853);
+ charMap.put("otimes",8855);
+ charMap.put("perp",8869);
+ charMap.put("sdot",8901);
+ charMap.put("lceil",8968);
+ charMap.put("rceil",8969);
+ charMap.put("lfloor",8970);
+ charMap.put("rfloor",8971);
+ charMap.put("lang",9001);
+ charMap.put("rang",9002);
+ charMap.put("loz",9674);
+ charMap.put("spades",9824);
+ charMap.put("clubs",9827);
+ charMap.put("hearts",9829);
+ charMap.put("diams",9830);
+
+ for( Entry<String, Integer> es: charMap.entrySet()) {
+ if(es.getValue()>=160); // save small space... note that no longer has amp, etc.
+ intMap.put(es.getValue(), es.getKey());
+ }
+ }
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/env/RosettaDF.java b/rosetta/src/main/java/com/att/rosetta/env/RosettaDF.java
new file mode 100644
index 0000000..7198c76
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/env/RosettaDF.java
@@ -0,0 +1,267 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta.env;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+
+import javax.xml.bind.JAXBException;
+import javax.xml.namespace.QName;
+import javax.xml.validation.Schema;
+
+import com.att.inno.env.APIException;
+import com.att.inno.env.BaseDataFactory;
+import com.att.inno.env.Data;
+import com.att.inno.env.Data.TYPE;
+import com.att.inno.env.DataFactory;
+import com.att.inno.env.Env;
+import com.att.inno.env.TimeTaken;
+import com.att.inno.env.Trans;
+import com.att.inno.env.jaxb.JAXBmar;
+import com.att.inno.env.jaxb.JAXBumar;
+import com.att.rosetta.InJson;
+import com.att.rosetta.InXML;
+import com.att.rosetta.JaxInfo;
+import com.att.rosetta.Marshal;
+import com.att.rosetta.Out;
+import com.att.rosetta.OutJson;
+import com.att.rosetta.OutRaw;
+import com.att.rosetta.OutXML;
+import com.att.rosetta.Parse;
+import com.att.rosetta.ParseException;
+import com.att.rosetta.marshal.DocMarshal;
+
+public class RosettaDF<T> extends BaseDataFactory implements DataFactory<T> {
+
+ static InJson inJSON = new InJson();
+ InXML inXML;
+
+ static OutJson outJSON = new OutJson();
+ OutXML outXML;
+ static OutRaw outRAW = new OutRaw();
+
+ // Temporary until we write JAXB impl...
+ JAXBmar jaxMar;
+ JAXBumar jaxUmar;
+
+ private Parse<Reader,?> defaultIn;
+ private Out defaultOut;
+ private RosettaEnv env;
+ private TYPE inType;
+ private TYPE outType;
+ private int defOption;
+ Marshal<T> marshal = null;
+
+
+ /**
+ * Private constructor to setup Type specific data manipulators
+ * @param schema
+ * @param rootNs
+ * @param cls
+ * @throws SecurityException
+ * @throws NoSuchFieldException
+ * @throws ClassNotFoundException
+ * @throws ParseException
+ * @throws JAXBException
+ */
+ // package on purpose
+ RosettaDF(RosettaEnv env, Schema schema, String rootNs, Class<T> cls) throws APIException {
+ this.env = env;
+ try {
+ // Note: rootNs can be null, in order to derive content from Class.
+ JaxInfo ji = rootNs==null?JaxInfo.build(cls):JaxInfo.build(cls,rootNs);
+ // Note: JAXBmar sets qname to null if not exists
+ jaxMar = new JAXBmar(rootNs==null?null:new QName("xmlns",rootNs),cls);
+ // Note: JAXBumar sets schema to null if not exists
+ jaxUmar = new JAXBumar(schema, cls);
+
+ defaultIn = inXML = new InXML(ji);
+ defaultOut = outXML = new OutXML(ji);
+ inType=outType=Data.TYPE.XML;
+ defOption = 0;
+ } catch (Exception e) {
+ throw new APIException(e);
+ }
+ }
+
+
+ // @Override
+ public RosettaData<T> newData() {
+ RosettaData<T> data = new RosettaData<T>(env, this)
+ .in(inType)
+ .out(outType)
+ .option(defOption);
+ return data;
+ }
+
+ // @Override
+ public RosettaData<T> newData(Env trans) {
+ RosettaData<T> data = new RosettaData<T>(trans, this)
+ .in(inType)
+ .out(outType)
+ .option(defOption);
+ return data;
+ }
+
+ @SuppressWarnings("unchecked")
+ // @Override
+ public Class<T> getTypeClass() {
+ return (Class<T>)jaxMar.getMarshalClass();
+ }
+
+ public RosettaDF<T> in(Data.TYPE type) {
+ inType = type;
+ defaultIn=getIn(type==Data.TYPE.DEFAULT?Data.TYPE.JSON:type);
+ return this;
+ }
+
+ /**
+ * If exists, first option is "Pretty", second is "Fragment"
+ *
+ * @param options
+ * @return
+ */
+ public RosettaDF<T> out(Data.TYPE type) {
+ outType = type;
+ defaultOut = getOut(type==Data.TYPE.DEFAULT?Data.TYPE.JSON:type);
+ return this;
+ }
+
+ public Parse<Reader,?> getIn(Data.TYPE type) {
+ switch(type) {
+ case DEFAULT:
+ return defaultIn;
+ case JSON:
+ return inJSON;
+ case XML:
+ return inXML;
+ default:
+ return defaultIn;
+ }
+ }
+
+ public Out getOut(Data.TYPE type) {
+ switch(type) {
+ case DEFAULT:
+ return defaultOut;
+ case JSON:
+ return outJSON;
+ case XML:
+ return outXML;
+ case RAW:
+ return outRAW;
+ default:
+ return defaultOut;
+ }
+ }
+
+ public int logType(com.att.inno.env.Data.TYPE ot) {
+ switch(ot) {
+ case JSON:
+ return Env.JSON;
+ default:
+ return Env.XML;
+ }
+ }
+
+
+ public RosettaEnv getEnv() {
+ return env;
+ }
+
+
+ public Data.TYPE getInType() {
+ return inType;
+ }
+
+ public Data.TYPE getOutType() {
+ return outType;
+ }
+
+ public RosettaDF<T> option(int option) {
+ defOption = option;
+
+ return this;
+ }
+
+ /**
+ * Assigning Root Marshal Object
+ *
+ * Will wrap with DocMarshal Object if not already
+ *
+ * @param marshal
+ * @return
+ */
+ public RosettaDF<T> rootMarshal(Marshal<T> marshal) {
+ if(marshal instanceof DocMarshal) {
+ this.marshal = marshal;
+ } else {
+ this.marshal = DocMarshal.root(marshal);
+ }
+ return this;
+ }
+
+ public void direct(Trans trans, T t, OutputStream os, boolean ... options) throws APIException, IOException {
+ Out out = getOut(outType);
+ TimeTaken tt = trans.start(out.logName(),logType(outType)); // determine from Out.. without dependency on Env?
+ try {
+ if(marshal==null) { // Unknown marshaller... do working XML marshal/extraction
+ StringWriter sw = new StringWriter();
+ jaxMar.marshal(trans.debug(), t, sw, options);
+ out.extract(new StringReader(sw.toString()), new OutputStreamWriter(os), inXML,options);
+ } else {
+ out.extract(t, new OutputStreamWriter(os), marshal,options);
+ }
+ } catch (Exception e) {
+ throw new APIException(e);
+ } finally {
+ tt.done();
+ }
+ }
+
+ public void direct(Trans trans, T t, Writer writer, boolean ... options) throws APIException, IOException {
+ Out out = getOut(outType);
+ TimeTaken tt = trans.start(out.logName(),logType(outType)); // determine from Out.. without dependency on Env?
+ try {
+ if(marshal==null) { // Unknown marshaller... do working XML marshal/extraction
+ StringWriter sw = new StringWriter();
+ jaxMar.marshal(trans.debug(), t, sw, options);
+ out.extract(new StringReader(sw.toString()), writer, inXML,options);
+ } else {
+ out.extract(t, writer, marshal,options);
+ }
+ } catch (Exception e) {
+ throw new APIException(e);
+ } finally {
+ tt.done();
+ }
+ }
+
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/env/RosettaData.java b/rosetta/src/main/java/com/att/rosetta/env/RosettaData.java
new file mode 100644
index 0000000..e07e883
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/env/RosettaData.java
@@ -0,0 +1,314 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta.env;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+
+import com.att.inno.env.APIException;
+import com.att.inno.env.Data;
+import com.att.inno.env.Env;
+import com.att.inno.env.TimeTaken;
+import com.att.rosetta.Out;
+import com.att.rosetta.Parse;
+import com.att.rosetta.Saved;
+
+public class RosettaData<T> implements Data<T>{
+ private Env trans;
+ private RosettaDF<T> df;
+ private Saved saved;
+ private TYPE inType, outType;
+ // Note: This is an array of boolean in order to pass into other methods
+ private boolean options[] = new boolean[] {false, false};
+ // Temp Storage of XML. Only when we must use JAXB to read in Objects
+ private String xml,json;
+
+ // package on purpose
+ RosettaData(Env env, RosettaDF<T> rosettaDF) {
+ df = rosettaDF;
+ saved = new Saved(); // Note: Saved constructs storage as needed...
+ trans = env;
+ inType = df.getInType();
+ outType = df.getOutType(); // take defaults
+ }
+
+// // @Override
+ public RosettaData<T> in(TYPE rosettaType) {
+ inType = rosettaType;
+ return this;
+ }
+
+// // @Override
+ public RosettaData<T> out(TYPE rosettaType) {
+ outType = rosettaType;
+ return this;
+ }
+
+// // @Override
+ public RosettaData<T> load(Reader rdr) throws APIException {
+ Parse<Reader,?> in = df.getIn(inType);
+ TimeTaken tt = in.start(trans);
+ try {
+ saved.extract(rdr, (Writer)null, in);
+ xml=json=null;
+ } catch (Exception e) {
+ throw new APIException(e);
+ } finally {
+ tt.done();
+ }
+ return this;
+ }
+
+ // @Override
+ public RosettaData<T> load(InputStream is) throws APIException {
+ Parse<Reader,?> in = df.getIn(inType);
+ TimeTaken tt = in.start(trans);
+ try {
+ saved.extract(new InputStreamReader(is), (Writer)null, in);
+ xml=json=null;
+ } catch (Exception e) {
+ throw new APIException(e);
+ } finally {
+ tt.done();
+ }
+ return this;
+ }
+
+ // @Override
+ public RosettaData<T> load(String str) throws APIException {
+ Parse<Reader,?> in = df.getIn(inType);
+ TimeTaken tt = in.start(trans);
+ try {
+ saved.extract(new StringReader(str), (Writer)null, in);
+ switch(inType) {
+ case XML:
+ xml = str;
+ break;
+ case JSON:
+ json = str;
+ break;
+ default:
+
+ }
+ } catch (Exception e) {
+ throw new APIException(e);
+ } finally {
+ tt.done();
+ }
+ return this;
+ }
+
+ // @Override
+ public RosettaData<T> load(T t) throws APIException {
+ Parse<?,?> in = df.getIn(inType);
+ TimeTaken tt = in.start(trans);
+ try {
+ if(df.marshal==null) { // Unknown marshaller... do working XML marshal/extraction
+ StringWriter sw = new StringWriter();
+ df.jaxMar.marshal(trans.debug(), t, sw, options);
+ saved.extract(new StringReader(xml = sw.toString()), (Writer)null, df.inXML);
+ } else {
+ saved.extract(t, (Writer)null, df.marshal);
+ }
+ } catch (Exception e) {
+ throw new APIException(e);
+ } finally {
+ tt.done();
+ }
+ return this;
+ }
+
+ public Saved getEvents() {
+ return saved;
+ }
+
+ // @Override
+ public T asObject() throws APIException {
+ Out out = df.getOut(TYPE.XML);
+ TimeTaken tt = trans.start(out.logName(),df.logType(outType)); // determine from Out.. without dependency on Env?
+ try {
+ //TODO Replace JAXB with Direct Object method!!!
+ StringWriter sw = new StringWriter();
+ out.extract(null, sw, saved);
+ return df.jaxUmar.unmarshal(trans.debug(), sw.toString());
+ } catch (Exception e) {
+ throw new APIException(e);
+ } finally {
+ tt.done();
+ }
+ }
+
+ // @Override
+ public String asString() throws APIException {
+ Out out = df.getOut(outType);
+ TimeTaken tt = trans.start(out.logName(),df.logType(outType)); // determine from Out.. without dependency on Env?
+ try {
+ if(outType==TYPE.XML) {
+ if(xml==null) {
+ StringWriter sw = new StringWriter();
+ out.extract(null, sw, saved, options);
+ xml = sw.toString();
+ }
+ return xml;
+ } else { // is JSON
+ if(json==null) {
+ StringWriter sw = new StringWriter();
+ out.extract(null, sw, saved, options);
+ json = sw.toString();
+ }
+ return json;
+ }
+ } catch (Exception e) {
+ throw new APIException(e);
+ } finally {
+ tt.done();
+ }
+ }
+
+
+ // @Override
+ public RosettaData<T> to(OutputStream os) throws APIException, IOException {
+ Out out = df.getOut(outType);
+ TimeTaken tt = trans.start(out.logName(),df.logType(outType)); // determine from Out.. without dependency on Env?
+ try {
+ if(outType==TYPE.XML && xml!=null) {
+ os.write(xml.getBytes());
+ } else if(outType==TYPE.JSON && json!=null) {
+ os.write(json.getBytes());
+ } else {
+ out.extract(null, os, saved, options);
+ }
+ } catch (Exception e) {
+ throw new APIException(e);
+ } finally {
+ tt.done();
+ }
+ return this;
+ }
+
+ // @Override
+ public RosettaData<T> to(Writer writer) throws APIException, IOException {
+ Out out = df.getOut(outType);
+ TimeTaken tt = trans.start(out.logName(),df.logType(outType)); // determine from Out.. without dependency on Env?
+ try {
+ if(outType==TYPE.XML && xml!=null) {
+ writer.append(xml);
+ } else if(outType==TYPE.JSON && json!=null) {
+ writer.append(json);
+ } else {
+ out.extract(null, writer, saved, options);
+ }
+ } catch (Exception e) {
+ throw new APIException(e);
+ } finally {
+ tt.done();
+ }
+ return this;
+ }
+
+ // @Override
+ public Class<T> getTypeClass() {
+ return df.getTypeClass();
+ }
+
+ private static final boolean[] emptyOption = new boolean[0];
+
+ public void direct(InputStream is, OutputStream os) throws APIException, IOException {
+ direct(is,os,emptyOption);
+ }
+
+ public void direct(Reader reader, Writer writer, boolean ... options) throws APIException, IOException {
+ Parse<Reader,?> in = df.getIn(inType);
+ Out out = df.getOut(outType);
+ TimeTaken tt = trans.start(out.logName(),df.logType(outType)); // determine from Out.. without dependency on Env?
+ try {
+ out.extract(reader, writer, in,options);
+ } catch (Exception e) {
+ throw new APIException(e);
+ } finally {
+ tt.done();
+ }
+ }
+
+ public void direct(T t, Writer writer, boolean ... options) throws APIException, IOException {
+ Out out = df.getOut(outType);
+ TimeTaken tt = trans.start(out.logName(),df.logType(outType)); // determine from Out.. without dependency on Env?
+ try {
+ if(df.marshal==null) { // Unknown marshaller... do working XML marshal/extraction
+ StringWriter sw = new StringWriter();
+ df.jaxMar.marshal(trans.debug(), t, sw, options);
+ out.extract(new StringReader(xml = sw.toString()), writer, df.inXML,options);
+ } else {
+ out.extract(t, writer, df.marshal,options);
+ }
+ } catch (Exception e) {
+ throw new APIException(e);
+ } finally {
+ tt.done();
+ }
+ }
+
+ public void direct(T t, OutputStream os, boolean ... options) throws APIException, IOException {
+ Out out = df.getOut(outType);
+ TimeTaken tt = trans.start(out.logName(),df.logType(outType)); // determine from Out.. without dependency on Env?
+ try {
+ if(df.marshal==null) { // Unknown marshaller... do working XML marshal/extraction
+ if(outType.equals(TYPE.XML)) {
+ df.jaxMar.marshal(trans.debug(), t, os, options);
+ } else {
+ StringWriter sw = new StringWriter();
+ df.jaxMar.marshal(trans.debug(), t, sw, options);
+ out.extract(new StringReader(xml = sw.toString()), new OutputStreamWriter(os), df.inXML,options);
+ }
+ } else {
+ out.extract(t, new OutputStreamWriter(os), df.marshal,options);
+ }
+
+ } catch (Exception e) {
+ throw new APIException(e);
+ } finally {
+ tt.done();
+ }
+ }
+
+
+ public void direct(InputStream is, OutputStream os, boolean ... options) throws APIException, IOException {
+ direct(new InputStreamReader(is),new OutputStreamWriter(os), options);
+ }
+
+ // // @Override
+ public RosettaData<T> option(int option) {
+ options[0] = (option&Data.PRETTY)==Data.PRETTY;
+ options[1] = (option&Data.FRAGMENT)==Data.FRAGMENT;
+ return this;
+ }
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/env/RosettaEnv.java b/rosetta/src/main/java/com/att/rosetta/env/RosettaEnv.java
new file mode 100644
index 0000000..78f963b
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/env/RosettaEnv.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta.env;
+
+import java.applet.Applet;
+import java.util.Properties;
+
+import javax.xml.namespace.QName;
+import javax.xml.validation.Schema;
+
+import com.att.inno.env.APIException;
+
+/**
+ * An essential Implementation of Env, which will fully function, without any sort
+ * of configuration.
+ *
+ * Use as a basis for Group level Env, just overriding where needed.
+ *
+ */
+public class RosettaEnv extends com.att.inno.env.impl.BasicEnv {
+
+ public RosettaEnv() {
+ super();
+ }
+
+ public RosettaEnv(Applet applet, String... tags) {
+ super(applet, tags);
+ }
+
+ public RosettaEnv(String[] args) {
+ super(args);
+ }
+
+ public RosettaEnv(String tag, String[] args) {
+ super(tag, args);
+ }
+
+ public RosettaEnv(String tag, Properties props) {
+ super(tag, props);
+ }
+
+ public RosettaEnv(Properties props) {
+ super(props);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> RosettaDF<T> newDataFactory(Class<?>... classes) throws APIException {
+ return new RosettaDF<T>(this, null, null, (Class<T>)classes[0]);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> RosettaDF<T> newDataFactory(Schema schema, Class<?>... classes) throws APIException {
+ return new RosettaDF<T>(this, schema, null, (Class<T>)classes[0]);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public<T> RosettaDF<T> newDataFactory(QName qName, Class<?> ... classes) throws APIException {
+ return new RosettaDF<T>(this, null, qName.getNamespaceURI(),(Class<T>)classes[0]);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public<T> RosettaDF<T> newDataFactory(Schema schema, QName qName, Class<?> ... classes) throws APIException {
+ return new RosettaDF<T>(this, schema,qName.getNamespaceURI(),(Class<T>)classes[0]);
+ }
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/marshal/DataWriter.java b/rosetta/src/main/java/com/att/rosetta/marshal/DataWriter.java
new file mode 100644
index 0000000..8d972d8
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/marshal/DataWriter.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta.marshal;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import com.att.inno.env.util.Chrono;
+
+/**
+ * We make these objects instead of static functions so they can be passed into
+ * FieldArray.
+ *
+ *
+ * @param <T>
+ */
+public abstract class DataWriter<T> {
+ public abstract boolean write(T t, StringBuilder sb);
+
+ public final static DataWriter<String> STRING = new DataWriter<String>() {
+ @Override
+ public boolean write(String s, StringBuilder sb) {
+ sb.append(s);
+ return true;
+ }
+ };
+
+ public final static DataWriter<Integer> INTEGER = new DataWriter<Integer>() {
+ @Override
+ public boolean write(Integer i, StringBuilder sb) {
+ sb.append(i);
+ return false;
+ }
+ };
+
+ public final static DataWriter<Long> LONG = new DataWriter<Long>() {
+ @Override
+ public boolean write(Long t, StringBuilder sb) {
+ sb.append(t);
+ return false;
+ }
+ };
+
+ public final static DataWriter<Byte> BYTE = new DataWriter<Byte>() {
+ @Override
+ public boolean write(Byte t, StringBuilder sb) {
+ sb.append(t);
+ return false;
+ }
+ };
+
+ public final static DataWriter<Character> CHAR = new DataWriter<Character>() {
+ @Override
+ public boolean write(Character t, StringBuilder sb) {
+ sb.append(t);
+ return true;
+ }
+ };
+
+ public final static DataWriter<Boolean> BOOL = new DataWriter<Boolean>() {
+ @Override
+ public boolean write(Boolean t, StringBuilder sb) {
+ sb.append(t);
+ return true;
+ }
+ };
+
+
+ /*
+ public final static DataWriter<byte[]> BYTE_ARRAY = new DataWriter<byte[]>() {
+ @Override
+ public boolean write(byte[] ba, StringBuilder sb) {
+ ByteArrayInputStream bais = new ByteArrayInputStream(ba);
+ StringBuilderOutputStream sbos = new StringBuilderOutputStream(sb);
+// try {
+ //TODO find Base64
+// Symm.base64noSplit().encode(bais, sbos);
+// } catch (IOException e) {
+// // leave blank
+// }
+ return true;
+ }
+
+ };
+ */
+
+ public final static DataWriter<XMLGregorianCalendar> DATE = new DataWriter<XMLGregorianCalendar>() {
+ @Override
+ public boolean write(XMLGregorianCalendar t, StringBuilder sb) {
+ sb.append(Chrono.dateOnlyStamp(t));
+ return true;
+ }
+ };
+
+ public final static DataWriter<XMLGregorianCalendar> DATE_TIME = new DataWriter<XMLGregorianCalendar>() {
+ @Override
+ public boolean write(XMLGregorianCalendar t, StringBuilder sb) {
+ sb.append(Chrono.dateTime(t));
+ return true;
+ }
+ };
+
+ private static final char[] chars="0123456789ABCDEF".toCharArray();
+ public final static DataWriter<byte[]> HEX_BINARY = new DataWriter<byte[]>() {
+ @Override
+ public boolean write(byte[] ba, StringBuilder sb) {
+ // FYI, doing this because don't want intermediate
+ // String in "HexString" or the processing in
+ // "String.format"
+ //sb.append("0x");
+ for(int i=0;i<ba.length;++i) {
+ byte b = ba[i];
+ sb.append(chars[((b&0xF0)>>4)]);
+ sb.append(chars[b&0xF]);
+ }
+ return true;
+ }
+ };
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/marshal/DocMarshal.java b/rosetta/src/main/java/com/att/rosetta/marshal/DocMarshal.java
new file mode 100644
index 0000000..27a4364
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/marshal/DocMarshal.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta.marshal;
+
+import java.util.Iterator;
+
+import com.att.rosetta.Ladder;
+import com.att.rosetta.Marshal;
+import com.att.rosetta.ParseException;
+import com.att.rosetta.Parsed;
+
+public class DocMarshal<T> extends Marshal<T> {
+ private Marshal<T> root;
+
+ public DocMarshal(Marshal<T> root) {
+ this.root = root;
+ }
+
+ @Override
+ public Parsed<State> parse(T t, Parsed<State> parsed) throws ParseException {
+ Ladder<Iterator<?>> ladder = parsed.state.ladder;
+ Iterator<?> iter = ladder.peek();
+ if(iter==null) {
+ ladder.push(PENDING_ITERATOR);
+ parsed.event = START_DOC;
+ } else if (DONE_ITERATOR.equals(iter)) {
+ } else {
+ ladder.ascend(); // look at field info
+ Iterator<?> currFieldIter = ladder.peek();
+ if(!DONE_ITERATOR.equals(currFieldIter)){
+ parsed = root.parse(t, parsed);
+ }
+ ladder.descend();
+ if(DONE_ITERATOR.equals(currFieldIter) || parsed.event==NONE) {
+ parsed.event = END_DOC;
+ ladder.push(DONE_ITERATOR);
+ }
+ }
+ return parsed; // if unchanged, then it will end process
+
+ }
+
+ public static final Iterator<Void> PENDING_ITERATOR = new Iterator<Void>() {
+ @Override
+ public boolean hasNext() {
+ return false;
+ }
+
+ @Override
+ public Void next() {
+ return null;
+ }
+
+ @Override
+ public void remove() {
+ }
+ };
+
+ public static<T> DocMarshal<T> root(Marshal<T> m) {
+ return (DocMarshal<T>)new DocMarshal<T>(m);
+ }
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/marshal/FieldArray.java b/rosetta/src/main/java/com/att/rosetta/marshal/FieldArray.java
new file mode 100644
index 0000000..7931e73
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/marshal/FieldArray.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta.marshal;
+
+import java.util.Iterator;
+import java.util.List;
+
+import com.att.rosetta.Ladder;
+import com.att.rosetta.Marshal;
+import com.att.rosetta.ParseException;
+import com.att.rosetta.Parsed;
+
+
+public abstract class FieldArray<T,S> extends Marshal<T> {
+ private DataWriter<S> dataWriter;
+ private String name;
+
+ public FieldArray(String name, DataWriter<S> dw) {
+ this.name = name;
+ dataWriter = dw;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Parsed<State> parse(T t, Parsed<State> parsed) throws ParseException {
+ Ladder<Iterator<?>> ladder = parsed.state.ladder;
+ Iterator<?> iter = ladder.peek();
+ if(iter==null) {
+ List<S> list = data(t);
+ if(list.isEmpty() && parsed.state.smallest) {
+ ladder.push(DONE_ITERATOR);
+ } else {
+ ladder.push(new ListIterator<S>(list));
+ parsed.event = START_ARRAY;
+ parsed.name = name;
+ }
+ } else if (DONE_ITERATOR.equals(iter)) {
+ } else {
+ ladder.ascend(); // look at field info
+ Iterator<?> memIter = ladder.peek();
+ ListIterator<S> mems = (ListIterator<S>)iter;
+ S mem;
+ if(memIter==null) {
+ mem=mems.next();
+ } else if(!DONE_ITERATOR.equals(memIter)) {
+ mem=mems.peek();
+ } else if(iter.hasNext()) {
+ mem=null;
+ ladder.push(null);
+ } else {
+ mem=null;
+ }
+
+ if(mem!=null) {
+ parsed.isString=dataWriter.write(mem, parsed.sb);
+ parsed.event = NEXT;
+ }
+ ladder.descend();
+ if(mem==null) {
+ if(iter.hasNext()) {
+ parsed.event = NEXT;
+ } else {
+ parsed.event = END_ARRAY;
+ ladder.push(DONE_ITERATOR);
+ }
+ }
+ }
+ return parsed; // if unchanged, then it will end process
+ }
+
+ protected abstract List<S> data(T t);
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/marshal/FieldBlob.java b/rosetta/src/main/java/com/att/rosetta/marshal/FieldBlob.java
new file mode 100644
index 0000000..b80cb48
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/marshal/FieldBlob.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta.marshal;
+
+public abstract class FieldBlob<T> extends FieldMarshal<T>{
+ public FieldBlob(String name) {
+ super(name);
+ }
+
+ protected abstract byte[] data(T t);
+
+ @Override
+ protected boolean data(T t, StringBuilder sb) {
+ return false;
+ // unimplemented
+ //return DataWriter.BYTE_ARRAY.write(data(t),sb);
+ }
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/marshal/FieldDate.java b/rosetta/src/main/java/com/att/rosetta/marshal/FieldDate.java
new file mode 100644
index 0000000..c2a8c03
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/marshal/FieldDate.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta.marshal;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+
+public abstract class FieldDate<T> extends FieldMarshal<T> {
+ public FieldDate(String name) {
+ super(name);
+ }
+
+ @Override
+ final protected boolean data(T t, StringBuilder sb) {
+ return DataWriter.DATE.write(data(t), sb);
+ }
+
+ protected abstract XMLGregorianCalendar data(T t);
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/marshal/FieldDateTime.java b/rosetta/src/main/java/com/att/rosetta/marshal/FieldDateTime.java
new file mode 100644
index 0000000..ce14c7f
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/marshal/FieldDateTime.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta.marshal;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+
+public abstract class FieldDateTime<T> extends FieldMarshal<T> {
+ public FieldDateTime(String name) {
+ super(name);
+ }
+
+ @Override
+ final protected boolean data(T t, StringBuilder sb) {
+ return DataWriter.DATE_TIME.write(data(t), sb);
+ }
+
+ protected abstract XMLGregorianCalendar data(T t);
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/marshal/FieldHexBinary.java b/rosetta/src/main/java/com/att/rosetta/marshal/FieldHexBinary.java
new file mode 100644
index 0000000..125f332
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/marshal/FieldHexBinary.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta.marshal;
+
+public abstract class FieldHexBinary<T> extends FieldMarshal<T>{
+ public FieldHexBinary(String name) {
+ super(name);
+ }
+
+ protected abstract byte[] data(T t);
+
+ @Override
+ protected boolean data(T t, StringBuilder sb) {
+ return DataWriter.HEX_BINARY.write(data(t), sb);
+ }
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/marshal/FieldMarshal.java b/rosetta/src/main/java/com/att/rosetta/marshal/FieldMarshal.java
new file mode 100644
index 0000000..63ba3b9
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/marshal/FieldMarshal.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta.marshal;
+
+
+import com.att.rosetta.Marshal;
+import com.att.rosetta.Parse;
+import com.att.rosetta.Parsed;
+
+public abstract class FieldMarshal<T> extends Marshal<T> {
+ private String name;
+
+ public FieldMarshal(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public Parsed<State> parse(T t, Parsed<State> parsed) {
+ parsed.state.ladder.push(DONE_ITERATOR);
+ parsed.event = Parse.NEXT;
+ parsed.name = name;
+ parsed.isString = data(t,parsed.sb);
+ return parsed;
+ }
+
+ /**
+ * Write Value to StringBuilder
+ * Return true if value looks like a String
+ * false if it is Numeric
+ * @param t
+ * @param sb
+ * @return
+ */
+ protected abstract boolean data(T t, StringBuilder sb);
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/marshal/FieldNumeric.java b/rosetta/src/main/java/com/att/rosetta/marshal/FieldNumeric.java
new file mode 100644
index 0000000..b53f12e
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/marshal/FieldNumeric.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta.marshal;
+
+public abstract class FieldNumeric<N,T> extends FieldMarshal<T> {
+ public FieldNumeric(String name) {
+ super(name);
+ }
+
+ @Override
+ final protected boolean data(T t, StringBuilder sb) {
+ sb.append(data(t));
+ return false;
+ }
+
+ protected abstract N data(T t);
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/marshal/FieldString.java b/rosetta/src/main/java/com/att/rosetta/marshal/FieldString.java
new file mode 100644
index 0000000..6fd3424
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/marshal/FieldString.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta.marshal;
+
+public abstract class FieldString<T> extends FieldMarshal<T> {
+ public FieldString(String name) {
+ super(name);
+ }
+
+ protected abstract String data(T t);
+
+ @Override
+ final protected boolean data(T t, StringBuilder sb) {
+ return DataWriter.STRING.write(data(t), sb);
+ }
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/marshal/ListIterator.java b/rosetta/src/main/java/com/att/rosetta/marshal/ListIterator.java
new file mode 100644
index 0000000..b444c68
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/marshal/ListIterator.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta.marshal;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Need an Iterator that can peek the current value without changing
+ *
+ * @param <T>
+ */
+final class ListIterator<T> implements Iterator<T> {
+ private T curr;
+ private Iterator<T> delg;
+ public ListIterator(List<T> list) {
+ curr = null;
+ delg = list.iterator();
+ }
+ @Override
+ public boolean hasNext() {
+ return delg.hasNext();
+ }
+
+ @Override
+ public T next() {
+ return curr = delg.hasNext()?delg.next():null;
+ }
+
+ public T peek() {
+ return curr==null?next():curr;
+ }
+
+ @Override
+ public void remove() {
+ delg.remove();
+ }
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/marshal/ObjArray.java b/rosetta/src/main/java/com/att/rosetta/marshal/ObjArray.java
new file mode 100644
index 0000000..89e07c5
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/marshal/ObjArray.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta.marshal;
+
+import java.util.Iterator;
+import java.util.List;
+
+import com.att.rosetta.Ladder;
+import com.att.rosetta.Marshal;
+import com.att.rosetta.ParseException;
+import com.att.rosetta.Parsed;
+
+
+public abstract class ObjArray<T,S> extends Marshal<T> {
+ private String name;
+ private Marshal<S> subMarshaller;
+
+ public ObjArray(String name, Marshal<S> subMarshaller) {
+ this.name = name;
+ this.subMarshaller = subMarshaller;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Parsed<State> parse(T t, Parsed<State> parsed) throws ParseException {
+ Ladder<Iterator<?>> ladder = parsed.state.ladder;
+ Iterator<?> iter = ladder.peek();
+ if(iter==null) {
+ List<S> list = data(t);
+ if(list.isEmpty() && parsed.state.smallest) {
+ ladder.push(DONE_ITERATOR);
+ } else {
+ ladder.push(new ListIterator<S>(list));
+ parsed.event = START_ARRAY;
+ parsed.name = name;
+ }
+ } else if (DONE_ITERATOR.equals(iter)) {
+ } else {
+ ladder.ascend(); // look at field info
+ Iterator<?> memIter = ladder.peek();
+ ListIterator<S> mems = (ListIterator<S>)iter;
+ S mem;
+ if(memIter==null) {
+ mem=mems.next();
+ } else if(!DONE_ITERATOR.equals(memIter)) {
+ mem=mems.peek();
+ } else if(iter.hasNext()) {
+ mem=null;
+ ladder.push(null);
+ } else {
+ mem=null;
+ }
+
+ if(mem!=null)
+ parsed = subMarshaller.parse(mem, parsed);
+ ladder.descend();
+ if(mem==null) {
+ if(iter.hasNext()) {
+ parsed.event = NEXT;
+ } else {
+ parsed.event = END_ARRAY;
+ ladder.push(DONE_ITERATOR);
+ }
+ }
+ }
+ return parsed; // if unchanged, then it will end process
+ }
+
+ protected abstract List<S> data(T t);
+
+}
diff --git a/rosetta/src/main/java/com/att/rosetta/marshal/ObjMarshal.java b/rosetta/src/main/java/com/att/rosetta/marshal/ObjMarshal.java
new file mode 100644
index 0000000..981dd78
--- /dev/null
+++ b/rosetta/src/main/java/com/att/rosetta/marshal/ObjMarshal.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * Licensed 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.
+ * * ============LICENSE_END====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.rosetta.marshal;
+
+import java.util.Iterator;
+
+import com.att.rosetta.Ladder;
+import com.att.rosetta.Marshal;
+import com.att.rosetta.ParseException;
+import com.att.rosetta.Parsed;
+
+/**
+ * Object Marshal
+ * Assumes has Fields and other Objects
+ * s
+ *
+ * @param <T>
+ */
+public abstract class ObjMarshal<T> extends Marshal<T> {
+ // Note: Not Using List or ArrayList, because there is no "Peek" concept in their iterator.
+ private Marshal<T>[] pml;
+ private int end=0;
+
+ /**
+ * @param pm
+ */
+ @SuppressWarnings("unchecked")
+ protected void add(Marshal<T> pm) {
+ if(pml==null) {
+ pml = new Marshal[Ladder.DEFAULT_INIT_SIZE];
+ } else if(end>pml.length) {
+ Object temp[] = pml;
+ pml = new Marshal[pml.length+Ladder.DEFAULT_INIT_SIZE];
+ System.arraycopy(temp, 0, pml, 0, pml.length);
+ }
+ pml[end]=pm;
+ ++end;
+ }
+
+ /* (non-Javadoc)
+ * @see com.att.rosetta.Parse#parse(java.lang.Object, com.att.rosetta.Parsed)
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public Parsed<State> parse(T in, Parsed<State> parsed) throws ParseException {
+ Ladder<Iterator<?>> ladder = parsed.state.ladder;
+ Iterator<Marshal<T>> iter = (Iterator<Marshal<T>>)ladder.peek();
+ if(iter==null) {
+ if(pml.length>0) {
+ ladder.push(new FieldsIterator());
+ parsed.event = START_OBJ;
+ } else {
+ ladder.push(DONE_ITERATOR);
+ }
+ } else if (DONE_ITERATOR.equals(iter)) {
+ } else {
+ FieldsIterator fields = (FieldsIterator)iter;
+ ladder.ascend(); // look at field info
+ Iterator<?> currFieldIter = ladder.peek();
+ Marshal<T> marshal;
+ if(currFieldIter==null) {
+ marshal=fields.next();
+ } else if(!DONE_ITERATOR.equals(currFieldIter)) {
+ marshal=fields.peek();
+ if(marshal==null && fields.hasNext())marshal=fields.next();
+ } else if(fields.hasNext()) {
+ marshal=fields.next();
+ ladder.push(null);
+ } else {
+ marshal=null;
+ }
+
+ if(marshal!=null)
+ parsed = marshal.parse(in, parsed);
+ ladder.descend();
+ if(marshal==null || parsed.event==NONE) {
+ parsed.event = END_OBJ;
+ ladder.push(DONE_ITERATOR);
+ }
+ }
+ return parsed; // if unchanged, then it will end process
+ }
+
+ private class FieldsIterator implements Iterator<Marshal<T>> {
+ private int idx = -1;
+
+ @Override
+ public boolean hasNext() {
+ return idx<end;
+ }
+
+ @Override
+ public Marshal<T> next() {
+ return pml[++idx];
+ }
+
+ public Marshal<T> peek() {
+ return idx<0?null:pml[idx];
+ }
+
+ @Override
+ public void remove() {
+ pml[idx]=null;
+ }
+
+ }
+
+}