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