summaryrefslogtreecommitdiffstats
path: root/rosetta/src/main/java/org/onap/aaf/rosetta/InJson.java
blob: 22e72a5c69870fbb6fdb51053b27e21845e62c9b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*******************************************************************************
 * ============LICENSE_START====================================================
 * * org.onap.aaf
 * * ===========================================================================
 * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
 * * ===========================================================================
 * * 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 org.onap.aaf.rosetta;

import java.io.IOException;
import java.io.Reader;

import org.onap.aaf.inno.env.Env;
import org.onap.aaf.inno.env.TimeTaken;
import org.onap.aaf.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);
	}
}