Commented out dead/unreachable code (maybe some error in control logic?)
[aaf/authz.git] / misc / rosetta / src / main / java / org / onap / aaf / misc / rosetta / OutJson.java
1 /**
2  * ============LICENSE_START====================================================
3  * org.onap.aaf
4  * ===========================================================================
5  * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
6  * ===========================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END====================================================
19  *
20  */
21
22 package org.onap.aaf.misc.rosetta;
23
24 import java.io.IOException;
25 import java.io.Writer;
26 import java.util.Stack;
27
28 import org.onap.aaf.misc.env.util.IndentPrintWriter;
29
30 public class OutJson extends Out {
31
32     @Override
33     public<IN,S> void extract(IN in, Writer writer, Parse<IN, S> prs, boolean ... options) throws IOException, ParseException {
34         Parsed<S> p = prs.newParsed();
35         IndentPrintWriter ipw;
36         if (options.length>0 && options[0]) { // is Pretty
37             ipw = writer instanceof IndentPrintWriter?(IndentPrintWriter)writer:new IndentPrintWriter(writer);
38             writer = ipw;
39         } else {
40             ipw = null;
41         }
42
43         // If it's a fragment, print first Object Name.  If root Object, skip first name
44         Stack<LevelStack> jsonLevel = new Stack<LevelStack>();
45         jsonLevel.push(new LevelStack(options.length>1 && options[1]));
46         boolean print = true, hadData=false;
47         char afterName=0, beforeName=0, maybe = 0, prev=0;
48
49         int count = 0;
50         while ((p = prs.parse(in,p.reuse())).valid()) {
51             ++count;
52             switch(p.event) {
53                 case 1: 
54                     continue;
55                 case 2:
56                     if (count==2) { // it's empty, write open/close on it's own
57                         writer.append('{');
58                         writer.append('}');
59                     }
60                     writer.flush();
61                     return;
62                 case '{':
63                     afterName = '{';
64                     if (jsonLevel.peek().printObjectName) {
65                         print = true;
66                     } else { // don't print names on first
67                         print=false; 
68                     }
69                     maybe=jsonLevel.peek().listItem();
70                     jsonLevel.push(new LevelStack(true));
71                     break;
72                 case '}':
73                     if (p.hasData()) { // if we have data, we print that, so may need to prepend a comma.
74                         maybe = jsonLevel.peek().listItem();
75                     } else { // No data means just print, 
76                         p.name = ""; // XML tags come through with names, but no data
77                     } 
78                     print = true;
79                     jsonLevel.pop();
80                     afterName = p.event;
81                     break;
82                 case '[':
83                     afterName = p.event;
84                     if ((prev==',' && !hadData) || prev==']')maybe=',';
85                     else maybe = jsonLevel.peek().listItem();
86
87                     jsonLevel.push(new LevelStack(false));
88                     print=true;
89                     break;
90                 case ']':
91                     afterName = p.event;
92                     if (p.hasData()) {
93                         if (prev==',' && !hadData)maybe=',';
94                         else maybe = jsonLevel.peek().listItem();
95                     } else {
96                         p.name = ""; // XML tags come through with names, but no data
97                     } 
98                     jsonLevel.pop();
99
100                     print = true;
101                     break;
102                 case   3:
103                 case ',':
104                     if (!p.hasData()) {
105                         p.isString=false;
106                         print=false;
107                     } else {
108                         maybe=jsonLevel.peek().listItem();
109                         print = true;
110                     }
111                     break;
112                 default:
113                     print = true;
114             }
115
116             if (maybe!=0) {
117                 if (ipw==null)writer.append(maybe); 
118                 else ipw.println(maybe);
119                 maybe = 0;
120             }
121
122             // commented out unreachable code (as it is, beforeName is never
123             // assigned any value except 0
124             //if (beforeName!=0) {
125             //    if (ipw==null)writer.append(beforeName);
126             //    else ipw.println(beforeName);
127             //    beforeName = 0;
128             //}
129             if (print) {
130                 if (p.hasName()) {
131                     writer.append('"');
132                     if (p.event==3)writer.append("__");
133                     writer.append(p.name);
134                     writer.append("\":");
135                 } 
136                 if (p.hasData()) {
137                     if (p.isString) {
138                         writer.append('"');
139                         escapedWrite(writer, p.sb);
140                         writer.append('"');
141                     } else if (p.sb.length()>0) {
142                         writer.append(p.sb);
143                     }
144                 }
145             }
146             if (afterName!=0) {
147                 if (ipw==null)writer.append(afterName);
148                 else {
149                     switch(afterName) {
150                         case '{':
151                             ipw.println(afterName);
152                             ipw.inc();
153                             break;
154                         case '}':
155                             ipw.dec();
156                             ipw.println();
157                             ipw.print(afterName);
158                             break;
159                         case ']':
160                             if (prev=='}' || prev==',')ipw.println();
161                             ipw.dec();
162                             ipw.print(afterName);
163                             break;
164
165                         case ',':
166                             ipw.println(afterName);
167                             break;
168                         default:
169                             ipw.print(afterName);
170                     }
171                 }
172                 afterName = 0;
173             }
174             
175             if (ipw!=null) {
176                 switch(p.event) {
177                     case '[':
178                         ipw.inc();
179                         ipw.println();
180                         break;
181                 }
182             }
183             prev = p.event;
184             hadData = p.hasData();
185
186         }
187         writer.flush();
188     }
189
190     private void escapedWrite(Writer writer, StringBuilder sb) throws IOException {
191         char c;
192         for (int i=0;i<sb.length();++i) {
193             switch(c=sb.charAt(i)) {
194                 case '\\':
195                     writer.append(c);
196                     if (i<sb.length()) {
197                         c=sb.charAt(++i);
198                         writer.append(c);
199                     }
200                     break;
201                 case '"':
202                     writer.append('\\');
203                     // Passthrough on purpose
204                 default:
205                     writer.append(c);
206             }
207         }
208
209         
210     }
211
212     @Override
213     public String logName() {
214         return "Rosetta JSON";
215     }
216
217     private static class LevelStack {
218         public boolean printObjectName=false;
219         private boolean first_n_List=true;
220         
221         public LevelStack(boolean printObjectName) {
222             this.printObjectName = printObjectName;
223         }
224         
225         public char listItem() {
226             if (first_n_List) {
227                 first_n_List=false;
228                 return 0;
229             } else {
230                 return ',';
231             }
232         }
233     }
234 }