AT&T 2.0.19 Code drop, stage 1
[aaf/authz.git] / misc / env / src / main / java / org / onap / aaf / misc / env / jaxb / JAXBData.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.env.jaxb;
23
24 import java.io.ByteArrayInputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.OutputStream;
28 import java.io.Reader;
29 import java.io.Writer;
30
31 import javax.xml.bind.JAXBException;
32
33 import org.onap.aaf.misc.env.APIException;
34 import org.onap.aaf.misc.env.Data;
35 import org.onap.aaf.misc.env.Env;
36 import org.onap.aaf.misc.env.EnvJAXB;
37 import org.onap.aaf.misc.env.old.IOStringifier;
38 import org.onap.aaf.misc.env.old.Objectifier;
39 import org.onap.aaf.misc.env.old.Stringifier;
40 /**
41  * <H1>Data</H1>
42  * <i>Data</i> facilitates lazy marshaling of data with a pre-determined
43  * marshaling mechanism.<p>
44  * 
45  * It stores either Object (defined by Generic {@literal <T>}) or String.<p>  
46  * 
47  * On asking for Object of type {@literal <T>}, it will respond with the object
48  * if it exists, or unmarshal the string and pass the result back.<p>
49  * 
50  * On asking for String, it will respond with the String
51  * if it exists, or marshal the String and pass the result back.<p>
52  * 
53  * @author Jonathan
54  *
55  * @param <T>
56  */
57 public final class JAXBData<T> implements Data<T>{
58         private Stringifier<T> stringifier;
59         private Objectifier<T> objectifier;
60         private String dataAsString;
61         private T dataAsObject;
62         private Class<T> tclass;
63         private JAXBDF<T> df;
64         private Env creatingEnv;
65         private boolean options[] = new boolean[] {false, false};
66         
67         /**
68          * Construct a Data Object with an appropriate Stringifier, Objectifier and Class to support
69          * 
70          * @param env
71          * @param strfr
72          * @param objfr
73          * @param text
74          * @param typeClass
75          */
76         JAXBData(Env env, JAXBDF<T> df, Stringifier<T> strfr, Objectifier<T> objfr, String text, Class<T> typeClass) {
77                 dataAsString = text;
78                 dataAsObject = null;
79                 stringifier = strfr;
80                 objectifier = objfr;
81                 tclass = typeClass;
82                 creatingEnv = env;
83                 this.df = df;
84         }
85         
86         
87         /**
88          * Construct a Data Object with an appropriate Stringifier, Objectifier and Object (which will
89          * yield it's class)
90          * 
91          * @param env
92          * @param strfr
93          * @param objfr
94          * @param object
95          */
96         @SuppressWarnings("unchecked")
97         JAXBData(Env env, JAXBDF<T> df, Stringifier<T> strfr, Objectifier<T> objfr, T object) {
98                 dataAsString = null;
99                 dataAsObject = object;
100                 stringifier = strfr;
101                 objectifier = objfr;
102                 tclass = (Class<T>) object.getClass();
103                 creatingEnv = env;
104                 this.df = df;
105         }
106
107         /**
108          * Respond with the String if it exists, or marshal the String and pass the result back.<p>
109          * 
110          * Explicitly use a specific Env for logging purposes
111          * 
112          * @param env
113          * @return String
114          * @throws APIException
115          */
116         public String asString(EnvJAXB env) throws APIException {
117                 if(dataAsString!=null) {
118                         return dataAsString;
119                 } else {
120                         return dataAsString = stringifier.stringify(env, dataAsObject);
121                 }
122         }
123
124         /**
125          * Respond with the String if it exists, or marshal the String and pass the result back.
126          * 
127          * However, use the Env the Data Object was created with.
128          * 
129          * @return String
130          * @throws APIException
131          */
132         // @Override
133         public String asString() throws APIException {
134                 if(dataAsString!=null) {
135                         return dataAsString;
136                 } else {
137                         return dataAsString = stringifier.stringify(creatingEnv, dataAsObject,options);
138                 }
139         }
140         
141         public Data<T> to(OutputStream os) throws APIException, IOException {
142                 if(dataAsString!=null) {
143                         os.write(dataAsString.getBytes());
144                 } else if (stringifier instanceof IOStringifier){
145                         ((IOStringifier<T>)stringifier).stringify(creatingEnv, dataAsObject, os, options);
146                 } else {
147                         dataAsString = stringifier.stringify(creatingEnv, dataAsObject, options);
148                         os.write(dataAsString.getBytes());
149                 }
150                 return this;
151         }
152
153
154         // @Override
155         public JAXBData<T> to(Writer writer) throws APIException, IOException {
156                 if(dataAsString!=null) {
157                         writer.write(dataAsString);
158                 } else if (stringifier instanceof IOStringifier){
159                         ((IOStringifier<T>)stringifier).stringify(creatingEnv, dataAsObject, writer, options);
160                 } else {
161                         dataAsString = stringifier.stringify(creatingEnv, dataAsObject, options);
162                         writer.write(dataAsString);
163                 }
164                 return this;
165         }
166
167
168         public InputStream getInputStream() throws APIException {
169                 if(dataAsString==null) {
170                         dataAsString = stringifier.stringify(creatingEnv,dataAsObject,options);
171                 }
172                 return new ByteArrayInputStream(dataAsString.getBytes());
173         }
174         
175         /**
176          * Respond with the Object of type {@literal <T>} if it exists, or unmarshal from String 
177          * and pass the result back.<p>
178          * 
179          * Explicitly use a specific Env for logging purposes
180          * 
181          * @param env
182          * @return T
183          * @throws APIException
184          */
185
186         public T asObject(EnvJAXB env) throws APIException {
187                 if(dataAsObject !=null) {
188                         return dataAsObject;
189                 } else {
190                         // Some Java compilers need two statements here
191                         dataAsObject = objectifier.objectify(env, dataAsString);
192                         return dataAsObject;
193                 }
194         }
195
196         /**
197          * Respond with the Object of type {@literal <T>} if it exists, or unmarshal from String 
198          * and pass the result back.<p>
199          *
200          * However, use the Env the Data Object was created with.
201          * 
202          * @return T
203          * @throws APIException
204          */
205         // @Override
206         public T asObject() throws APIException {
207                 if(dataAsObject !=null) {
208                         return dataAsObject;
209                 } else {
210                         // Some Java compilers need two statements here
211                         dataAsObject = objectifier.objectify(creatingEnv, dataAsString);
212                         return dataAsObject;
213                 }
214         }
215         
216
217         /**
218          * Return the Class Type supported by this DataObject
219          * 
220          * @return {@literal Class<T>}
221          */
222         // @Override
223         public Class<T> getTypeClass() {
224                 return tclass;
225         }
226         
227         
228         /**
229          * For Debugging Convenience, we marshal to String if possible.
230          * 
231          * Behavior is essentially the same as asString(), except asString() throws
232          * an APIException.  <p>
233          * Since toString() must not throw exceptions, the function just catches and prints an
234          * error, which is probably not the behavior desired.<p>
235          *  
236          * Therefore, use "asString()" where possible in actual Transactional code. 
237          * 
238          * @see java.lang.Object#toString()
239          */
240         // @Override
241         public String toString() {
242                 if(dataAsString!=null) {
243                         return dataAsString;
244                 } else {
245                         try {
246                                 return dataAsString = stringifier.stringify(creatingEnv, dataAsObject);
247                         } catch (APIException e) {
248                                 return "ERROR - Can't Stringify from Object " + e.getLocalizedMessage();
249                         }
250                 }
251         }
252
253         public Data<T> load(T t) throws APIException {
254                 dataAsObject = t;
255                 dataAsString = null;
256                 return this;
257         }
258
259
260         public Data<T> load(String str) throws APIException {
261                 dataAsObject = null;
262                 dataAsString = str;
263                 return this;
264         }
265
266
267         public Data<T> load(InputStream is) throws APIException {
268                 try {
269                         dataAsObject = df.jumar.unmarshal(creatingEnv.debug(),is);
270                         dataAsString = null;
271                 } catch (JAXBException e) {
272                         throw new APIException(e);
273                 }
274                 return this;
275         }
276
277
278         public Data<T> load(Reader rdr) throws APIException {
279                 try {
280                         dataAsObject = df.jumar.unmarshal(creatingEnv.debug(),rdr);
281                         dataAsString = null;
282                 } catch (JAXBException e) {
283                         throw new APIException(e);
284                 }
285                 return this;
286         }
287
288
289         // @Override
290         public void direct(InputStream input, OutputStream output) throws APIException, IOException {
291                 byte b[] = new byte[128];
292                 int count;
293                 do {
294                         count = input.read(b);
295                         if(count>0)output.write(b, 0, count);
296                 } while(count>=0);
297         }
298
299
300         // @Override
301         public Data<T> out(TYPE type) {
302                 // it's going to be XML regardless...
303                 return this;
304         }
305
306
307         // @Override
308         public Data<T> in(TYPE type) {
309                 // Not Supported... will still be XML
310                 return this;
311         }
312
313
314         // @Override
315         public Data<T> option(int option) {
316                 options[0] = (option&Data.PRETTY)==Data.PRETTY;
317                 options[1] = (option&Data.FRAGMENT)==Data.FRAGMENT;
318                 return this;
319         }
320         
321 }