[AAF-23] Initial code import
[aaf/inno.git] / rosetta / src / main / java / com / att / rosetta / Saved.java
1 /*******************************************************************************\r
2  * ============LICENSE_START====================================================\r
3  * * org.onap.aai\r
4  * * ===========================================================================\r
5  * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
6  * * Copyright © 2017 Amdocs\r
7  * * ===========================================================================\r
8  * * Licensed under the Apache License, Version 2.0 (the "License");\r
9  * * you may not use this file except in compliance with the License.\r
10  * * You may obtain a copy of the License at\r
11  * * \r
12  *  *      http://www.apache.org/licenses/LICENSE-2.0\r
13  * * \r
14  *  * Unless required by applicable law or agreed to in writing, software\r
15  * * distributed under the License is distributed on an "AS IS" BASIS,\r
16  * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
17  * * See the License for the specific language governing permissions and\r
18  * * limitations under the License.\r
19  * * ============LICENSE_END====================================================\r
20  * *\r
21  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
22  * *\r
23  ******************************************************************************/\r
24 package com.att.rosetta;\r
25 \r
26 import java.io.IOException;\r
27 import java.io.Reader;\r
28 import java.io.Writer;\r
29 import java.util.List;\r
30 \r
31 import com.att.inno.env.Env;\r
32 import com.att.inno.env.TimeTaken;\r
33 import com.att.rosetta.Saved.State;\r
34 \r
35 /**\r
36  * An Out Object that will save off produced Parsed Stream and \r
37  * a Parse (In) Object that will reproduce Parsed Stream on demand\r
38  *  \r
39  *\r
40  */\r
41 public class Saved extends Out implements Parse<Reader, State>{\r
42         private static final String ROSETTA_SAVED = "Rosetta Saved";\r
43         private final static int INIT_SIZE=128;\r
44         private Content content[];\r
45         private int idx;\r
46         private boolean append = false;\r
47         \r
48         /**\r
49          * Read from Parsed Stream and save\r
50          */\r
51         // @Override\r
52         public<IN,S> void extract(IN in, Writer ignore, Parse<IN,S> parser, boolean ... options) throws IOException, ParseException {\r
53                 Parsed<S> p = parser.newParsed();\r
54                 if(!append) {\r
55                         // reuse array  if not too big\r
56                         if(content==null||content.length>INIT_SIZE*3) {\r
57                                 content = new Content[INIT_SIZE];\r
58                                 idx = -1;\r
59                         } else do {\r
60                                 content[idx]=null;\r
61                         } while(--idx>=0);\r
62                 }\r
63                 \r
64                 // Note: idx needs to be -1 on initialization and no appendages\r
65                 while((p = parser.parse(in,p.reuse())).valid()) {\r
66                         if(!(append && (p.event==START_DOC || p.event==END_DOC))) { // skip any start/end of document in appendages\r
67                                 if(++idx>=content.length) {\r
68                                         Content temp[] = new Content[content.length*2];\r
69                                         System.arraycopy(content, 0, temp, 0, idx);\r
70                                         content = temp;\r
71                                 }\r
72                                 content[idx]= new Content(p);\r
73                         }\r
74                 }\r
75         }\r
76         \r
77         // @Override\r
78         public Parsed<State> parse(Reader ignore, Parsed<State> parsed) throws ParseException {\r
79                 int i;\r
80                 if((i=parsed.state.count++)<=idx) \r
81                         content[i].load(parsed);\r
82                 else \r
83                         parsed.event = Parse.NONE; \r
84                 return parsed;\r
85         }\r
86 \r
87         public Content[] cut(char event, int count) {\r
88                 append = true;\r
89                 for(int i=idx;i>=0;--i) {\r
90                         if(content[i].event==event) count--;\r
91                         if(count==0) {\r
92                                 Content[] appended = new Content[idx-i+1];\r
93                                 System.arraycopy(content, i, appended, 0, appended.length);\r
94                                 idx = i-1;\r
95                                 return appended;\r
96                         }\r
97                 }\r
98                 return new Content[0];\r
99         }\r
100 \r
101         public void paste(Content[] appended) {\r
102                 if(appended!=null) {\r
103                         if(idx+appended.length>content.length) {\r
104                                 Content temp[] = new Content[content.length*2];\r
105                                 System.arraycopy(content, 0, temp, 0, idx);\r
106                                 content = temp;\r
107                         }\r
108                         System.arraycopy(appended,0,content,idx+1,appended.length);\r
109                         idx+=appended.length;\r
110                 }\r
111                 this.append = false;\r
112         }\r
113 \r
114         public static class State {\r
115                 public int count = 0;\r
116         }\r
117         \r
118         public static class Content {\r
119                 private boolean isString;\r
120                 private char event;\r
121                 private String name;\r
122                 private List<Prop> props;\r
123                 private String str;\r
124                 \r
125                 public Content(Parsed<?> p) {\r
126                         isString = p.isString;\r
127                         event = p.event;\r
128                         name = p.name;\r
129                         // avoid copying, because most elements don't have content\r
130                         // Cannot set to "equals", because sb ends up being cleared (and reused)\r
131                         str = p.sb.length()==0?null:p.sb.toString();\r
132                 }\r
133 \r
134                 public void load(Parsed<State> p) {\r
135                         p.isString = isString;\r
136                         p.event = event;\r
137                         p.name = name;\r
138                         if(str!=null)\r
139                                 p.sb.append(str);\r
140                 }\r
141                 \r
142                 public String toString() {\r
143                         StringBuilder sb = new StringBuilder();\r
144                         sb.append(event);\r
145                         sb.append(" - ");\r
146                         sb.append(name);\r
147                         sb.append(": ");\r
148                         if(isString)sb.append('"');\r
149                         sb.append(str);\r
150                         if(isString)sb.append('"');\r
151                         sb.append(' ');\r
152                         if(props!=null) {\r
153                                 boolean comma = false;\r
154                                 for(Prop prop : props) {\r
155                                         if(comma)sb.append(',');\r
156                                         else comma = true;\r
157                                         sb.append(prop.tag);\r
158                                         sb.append('=');\r
159                                         sb.append(prop.value);\r
160                                 }\r
161                         }\r
162                         return sb.toString();\r
163                 }\r
164         }\r
165         \r
166         //// @Override\r
167         public Parsed<State> newParsed() {\r
168                 Parsed<State> ps = new Parsed<State>(new State());\r
169                 return ps;\r
170         }\r
171 \r
172         /**\r
173          * Convenience function\r
174          * @param rdr\r
175          * @param in\r
176          * @throws IOException\r
177          * @throws ParseException\r
178          */\r
179         public<IN,S> void load(IN in, Parse<IN, S> parser) throws IOException, ParseException {\r
180                 extract(in,(Writer)null, parser);\r
181         }\r
182 \r
183 \r
184         // @Override\r
185         public TimeTaken start(Env env) {\r
186                 return env.start(ROSETTA_SAVED, 0);\r
187         }\r
188         \r
189         @Override\r
190         public String logName() {\r
191                 return ROSETTA_SAVED;\r
192         }\r
193 \r
194 \r
195 }\r