Updated champ-lib to use the correct logger
[aai/champ.git] / champ-lib / champ-core / src / main / java / org / onap / aai / champcore / ie / GraphMLImporterExporter.java
1 /**
2  * ============LICENSE_START==========================================
3  * org.onap.aai
4  * ===================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * Copyright © 2017-2018 Amdocs
7  * ===================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *        http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END============================================
20  */
21 package org.onap.aai.champcore.ie;
22
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.OutputStream;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.LinkedList;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Map.Entry;
34 import java.util.Optional;
35 import java.util.Set;
36 import java.util.concurrent.atomic.AtomicInteger;
37
38 import javax.xml.parsers.DocumentBuilder;
39 import javax.xml.parsers.DocumentBuilderFactory;
40 import javax.xml.parsers.ParserConfigurationException;
41 import javax.xml.stream.XMLOutputFactory;
42 import javax.xml.stream.XMLStreamException;
43 import javax.xml.stream.XMLStreamWriter;
44
45 import org.onap.aai.champcore.ChampAPI;
46 import org.onap.aai.champcore.ChampCoreMsgs;
47 import org.onap.aai.champcore.ChampGraph;
48 import org.onap.aai.champcore.exceptions.ChampMarshallingException;
49 import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException;
50 import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException;
51 import org.onap.aai.champcore.exceptions.ChampSchemaViolationException;
52 import org.onap.aai.champcore.exceptions.ChampTransactionException;
53 import org.onap.aai.champcore.exceptions.ChampUnmarshallingException;
54 import org.onap.aai.champcore.model.ChampObject;
55 import org.onap.aai.champcore.model.ChampObjectIndex;
56 import org.onap.aai.champcore.model.ChampRelationship;
57 import org.onap.aai.cl.api.Logger;
58 import org.onap.aai.cl.eelf.LoggerFactory;
59 import org.w3c.dom.Document;
60 import org.w3c.dom.NamedNodeMap;
61 import org.w3c.dom.Node;
62 import org.w3c.dom.NodeList;
63 import org.xml.sax.InputSource;
64 import org.xml.sax.SAXException;
65
66 public class GraphMLImporterExporter implements Importer, Exporter {
67
68         private static final Logger LOGGER = LoggerFactory.getInstance().getLogger(GraphMLImporterExporter.class);
69
70         private static class GraphMLKey {
71                 private final String id;
72                 private final String attrName;
73                 private final String attrType;
74
75                 public GraphMLKey(String id, String attrName, Class<?> attrType) {
76                         this.id = id;
77                         this.attrName = attrName;
78
79                         if (attrType.equals(Boolean.class)) {
80                                 this.attrType = "boolean";
81                         } else if (attrType.equals(Integer.class)) {
82                                 this.attrType = "int";
83                         } else if (attrType.equals(Long.class)) {
84                                 this.attrType = "long";
85                         } else if (attrType.equals(Float.class)) {
86                                 this.attrType = "float";
87                         } else if (attrType.equals(Double.class)) {
88                                 this.attrType = "double";
89                         } else if (attrType.equals(String.class)) {
90                                 this.attrType = "string";
91                         } else {
92                                 throw new RuntimeException("Cannot handle type " + attrType + " in GraphML");
93                         }
94                 }
95         }
96
97         public void importData(ChampAPI api, InputStream is) {
98
99                 try {
100                         final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
101                         factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); 
102                         final DocumentBuilder builder = factory.newDocumentBuilder();
103                         final InputSource inputSource = new InputSource(is);
104                     final Document doc = builder.parse(inputSource);
105
106                         final Map<String, Map<String, String>> nodePropertyDefinitions = new HashMap<String, Map<String, String>> ();
107                         final Map<String, Map<String, String>> edgePropertyDefinitions = new HashMap<String, Map<String, String>> ();
108                         final Set<Map<String, String>> nodeDefaults = new HashSet<Map<String, String>> ();
109                         final Set<Map<String, String>> edgeDefaults = new HashSet<Map<String, String>> ();
110
111                         final NodeList keys = doc.getElementsByTagName("key");
112
113                         for (int i = 0; i < keys.getLength(); i++) {
114                                 final Node key = keys.item(i);
115                                 final String id = key.getAttributes().getNamedItem("id").getNodeValue();
116                                 final String attrName = key.getAttributes().getNamedItem("attr.name").getNodeValue();
117                                 final String attrType = key.getAttributes().getNamedItem("attr.type").getNodeValue();
118                                 final String elementType = key.getAttributes().getNamedItem("for").getNodeValue();
119                                 final Map<String, String> propertyDefinitions = new HashMap<String, String> ();
120
121                                 propertyDefinitions.put("attr.name", attrName);
122                                 propertyDefinitions.put("attr.type",  attrType);
123
124                                 final NodeList keyChildren = key.getChildNodes();
125
126                                 for (int j = 0; j < keyChildren.getLength(); j++) {
127                                         final Node keyChild = keyChildren.item(j);
128
129                                         if (keyChild.getNodeType() != Node.ELEMENT_NODE) continue;
130
131                                         if (keyChild.getNodeName().equals("default")) {
132                                                 propertyDefinitions.put("default", keyChild.getFirstChild().getNodeValue());
133
134                                                 if (elementType.equals("node")) nodeDefaults.add(propertyDefinitions);
135                                                 else if (elementType.equals("edge")) edgeDefaults.add(propertyDefinitions);
136                                         }
137                                 }
138
139                                 if (elementType.equals("node")) {
140                                         nodePropertyDefinitions.put(id, propertyDefinitions);
141                                 } else if (elementType.equals("edge")) {
142                                         edgePropertyDefinitions.put(id, propertyDefinitions);
143                                 } else {
144                                         LOGGER.warn(ChampCoreMsgs.CHAMPCORE_GRAPH_ML_IMPORTER_EXPORTER_WARN,
145                                             String.format("Unknown element type %s, skipping", elementType));
146                                 }
147                         }
148
149                         final NodeList graphs = doc.getElementsByTagName("graph");
150
151                         for (int i = 0; i < graphs.getLength(); i++) {
152                                 final Node graph = graphs.item(i);
153                                 final String graphName = graph.getAttributes().getNamedItem("id").getNodeValue();
154                                 final NodeList nodesAndEdges = graph.getChildNodes();
155
156                                 List<String> fields = new ArrayList<String>();
157                             fields.add("importAssignedId");     
158                                 api.getGraph(graphName).storeObjectIndex(ChampObjectIndex.create()
159                                                                                                                                                         .ofName("importAssignedId")
160                                                                                                                                                         .onAnyType()
161                                                                                                                                                         .forFields(fields)
162                                                                                                                                                         .build());
163
164                                 for (int j = 0; j < nodesAndEdges.getLength(); j++) {
165                                         final Node nodeOrEdge = nodesAndEdges.item(j);
166
167                                         if (nodeOrEdge.getNodeType() != Node.ELEMENT_NODE) continue;
168
169                                         if (nodeOrEdge.getNodeName().equals("node")) {
170                                                 writeNode(api.getGraph(graphName), nodeOrEdge, nodePropertyDefinitions, nodeDefaults);
171                                         } else if (nodeOrEdge.getNodeName().equals("edge")) {
172                                                 writeEdge(api.getGraph(graphName), nodeOrEdge, edgePropertyDefinitions, edgeDefaults);
173                                         } else {
174                                                 LOGGER.warn(ChampCoreMsgs.CHAMPCORE_GRAPH_ML_IMPORTER_EXPORTER_WARN,
175                                                     String.format("Unknown object %s found in graphML, skipping", nodeOrEdge.getNodeName()));
176                                         }
177                                 }
178                         }
179                 } catch (ParserConfigurationException e) {
180                         throw new RuntimeException("Failed to setup DocumentBuilder", e);
181                 } catch (SAXException e) {
182                         throw new RuntimeException("Failed to parse input stream", e);
183                 } catch (IOException e) {
184                         throw new RuntimeException("Failed to parse input stream", e);
185                 }
186         }
187
188         private void writeEdge(ChampGraph graph, Node edge, Map<String, Map<String, String>> edgePropertyDefinitions, Set<Map<String, String>> edgeDefaults) {
189                 final NamedNodeMap edgeAttributes = edge.getAttributes();
190                 final NodeList data = edge.getChildNodes();
191                 final Object sourceKey = edgeAttributes.getNamedItem("source").getNodeValue();
192                 final Object targetKey = edgeAttributes.getNamedItem("target").getNodeValue();
193                 ChampObject sourceObject=null;
194                 ChampObject targetObject=null;
195                 
196                 try {
197                         final Optional<ChampObject> source = graph.queryObjects(Collections.singletonMap("importAssignedId", sourceKey), Optional.empty()).findFirst();
198                         final Optional<ChampObject> target = graph.queryObjects(Collections.singletonMap("importAssignedId", targetKey), Optional.empty()).findFirst();
199
200                         if (!source.isPresent()) {
201                                 sourceObject = graph.storeObject(ChampObject.create()
202                                                                                                                 .ofType("undefined")
203                                                                                                                 .withoutKey()
204                                                                                                                 .build(),
205                                                                                                  Optional.empty());
206                         } else sourceObject = source.get();
207         
208                         if (!target.isPresent()) {
209                                 targetObject = graph.storeObject(ChampObject.create()
210                                                                                                                 .ofType("undefined")
211                                                                                                                 .withoutKey()
212                                                                                                                 .build(),
213                                                                                                  Optional.empty());
214                         } else targetObject = target.get();
215
216                 } catch (ChampMarshallingException e) {
217                         LOGGER.error(ChampCoreMsgs.CHAMPCORE_GRAPH_ML_IMPORTER_EXPORTER_ERROR,
218                             "Failed to marshall object to backend type, skipping this edge. " + e.getMessage());
219                         return;
220                 } catch (ChampSchemaViolationException e) {
221                         LOGGER.error(ChampCoreMsgs.CHAMPCORE_GRAPH_ML_IMPORTER_EXPORTER_ERROR,
222                             "Source/target object violates schema constraint(s). " + e.getMessage());
223                         return;
224                 } catch (ChampObjectNotExistsException e) {
225                         LOGGER.error(ChampCoreMsgs.CHAMPCORE_GRAPH_ML_IMPORTER_EXPORTER_ERROR,
226                             "Failed to update existing source/target ChampObject. " + e.getMessage());
227                         return;
228                 } catch (ChampTransactionException e) {
229             LOGGER.error(ChampCoreMsgs.CHAMPCORE_GRAPH_ML_IMPORTER_EXPORTER_ERROR,
230                 "Failed to commit or rollback transaction. " + e.getMessage());
231                 }
232
233                 final ChampRelationship.Builder champRelBuilder = new ChampRelationship.Builder(sourceObject, targetObject, "undefined");
234
235                 for (Map<String, String> defaultProperty : edgeDefaults) {
236                         champRelBuilder.property(defaultProperty.get("attr.name"), defaultProperty.get("default"));
237                 }
238
239                 for (int k = 0; k < data.getLength(); k++) {
240                         final Node datum = data.item(k);
241
242                         if (datum.getNodeType() != Node.ELEMENT_NODE) continue;
243
244                         final String nodeProperty = datum.getAttributes().getNamedItem("key").getNodeValue();
245                         final Map<String, String> nodePropertyDefinition = edgePropertyDefinitions.get(nodeProperty);
246
247                         switch (nodePropertyDefinition.get("attr.type")) {
248                         case "boolean":
249                                 champRelBuilder.property(nodePropertyDefinition.get("attr.name"), Boolean.valueOf(datum.getFirstChild().getNodeValue()));
250                                 break;
251                         case "int":
252                                 champRelBuilder.property(nodePropertyDefinition.get("attr.name"), Integer.valueOf(datum.getFirstChild().getNodeValue()));
253                                 break;
254                         case "long":
255                                 champRelBuilder.property(nodePropertyDefinition.get("attr.name"), Long.valueOf(datum.getFirstChild().getNodeValue()));
256                                 break;
257                         case "float":
258                                 champRelBuilder.property(nodePropertyDefinition.get("attr.name"), Float.valueOf(datum.getFirstChild().getNodeValue()));
259                                 break;
260                         case "double":
261                                 champRelBuilder.property(nodePropertyDefinition.get("attr.name"), Double.valueOf(datum.getFirstChild().getNodeValue()));
262                                 break;
263                         case "string":
264                                 champRelBuilder.property(nodePropertyDefinition.get("attr.name"), datum.getFirstChild().getNodeValue());
265                                 break;
266                         default:
267                                 throw new RuntimeException("Unknown node property attr.type " + nodePropertyDefinition.get("attr.type"));
268                         }
269                 }
270
271                 final ChampRelationship relToStore = champRelBuilder.build();
272
273                 try {
274                         graph.storeRelationship(relToStore, Optional.empty());
275                 } catch (ChampMarshallingException e) {
276                         LOGGER.warn(ChampCoreMsgs.CHAMPCORE_GRAPH_ML_IMPORTER_EXPORTER_WARN,
277                             "Failed to marshall ChampObject to backend type. " + e.getMessage());
278                 } catch (ChampSchemaViolationException e) {
279                         LOGGER.error(ChampCoreMsgs.CHAMPCORE_GRAPH_ML_IMPORTER_EXPORTER_ERROR,
280                             "Failed to store object (schema violated): " + relToStore + " " + e.getMessage());
281                 } catch (ChampRelationshipNotExistsException e) {
282                         LOGGER.error(ChampCoreMsgs.CHAMPCORE_GRAPH_ML_IMPORTER_EXPORTER_ERROR,
283                             "Failed to update existing ChampRelationship. " + e.getMessage());
284                 } catch (ChampObjectNotExistsException e) {
285                         LOGGER.error(ChampCoreMsgs.CHAMPCORE_GRAPH_ML_IMPORTER_EXPORTER_ERROR,
286                             "Objects bound to relationship do not exist (should never happen)");
287                 } catch (ChampUnmarshallingException e) {
288                         LOGGER.error(ChampCoreMsgs.CHAMPCORE_GRAPH_ML_IMPORTER_EXPORTER_ERROR,
289                             "Failed to unmarshall ChampObject to backend type");
290                 } catch (ChampTransactionException e) {
291                     LOGGER.error(ChampCoreMsgs.CHAMPCORE_GRAPH_ML_IMPORTER_EXPORTER_ERROR,
292                         "Failed to commit or rollback transaction");
293                 }
294                 
295         }
296
297         private void writeNode(ChampGraph graph, Node node, Map<String, Map<String, String>> nodePropertyDefinitions, Set<Map<String, String>> nodeDefaults) {
298                 final NamedNodeMap nodeAttributes = node.getAttributes();
299                 final Object importAssignedId = nodeAttributes.getNamedItem("id").getNodeValue();
300                 final NodeList data = node.getChildNodes();
301                 final Map<String, Object> properties = new HashMap<String, Object> ();
302
303                 for (int k = 0; k < data.getLength(); k++) {
304                         final Node datum = data.item(k);
305
306                         if (datum.getNodeType() != Node.ELEMENT_NODE) continue;
307
308                         final String nodeProperty = datum.getAttributes().getNamedItem("key").getNodeValue();
309                         final Map<String, String> nodePropertyDefinition = nodePropertyDefinitions.get(nodeProperty);
310
311                         switch (nodePropertyDefinition.get("attr.type")) {
312                         case "boolean":
313                                 properties.put(nodePropertyDefinition.get("attr.name"), Boolean.valueOf(datum.getFirstChild().getNodeValue()));
314                                 break;
315                         case "int":
316                                 properties.put(nodePropertyDefinition.get("attr.name"), Integer.valueOf(datum.getFirstChild().getNodeValue()));
317                                 break;
318                         case "long":
319                                 properties.put(nodePropertyDefinition.get("attr.name"), Long.valueOf(datum.getFirstChild().getNodeValue()));
320                                 break;
321                         case "float":
322                                 properties.put(nodePropertyDefinition.get("attr.name"), Float.valueOf(datum.getFirstChild().getNodeValue()));
323                                 break;
324                         case "double":
325                                 properties.put(nodePropertyDefinition.get("attr.name"), Double.valueOf(datum.getFirstChild().getNodeValue()));
326                                 break;
327                         case "string":
328                                 properties.put(nodePropertyDefinition.get("attr.name"), datum.getFirstChild().getNodeValue());
329                                 break;
330                         default:
331                                 throw new RuntimeException("Unknown node property attr.type " + nodePropertyDefinition.get("attr.type"));
332                         }
333                 }
334
335                 if (!properties.containsKey("type")) throw new RuntimeException("No type provided for object (was this GraphML exported by Champ?)");
336
337                 final ChampObject.Builder champObjBuilder = new ChampObject.Builder((String) properties.get("type"));
338
339                 for (Map<String, String> defaultProperty : nodeDefaults) {
340                         champObjBuilder.property(defaultProperty.get("attr.name"), defaultProperty.get("default"));
341                 }
342
343                 properties.remove("type");
344
345                 champObjBuilder.properties(properties)
346                                                 .property("importAssignedId", importAssignedId);
347
348                 final ChampObject objectToStore = champObjBuilder.build();
349
350                 try {  
351                   graph.storeObject(objectToStore, Optional.empty());
352                 } catch (ChampMarshallingException e) {
353                         LOGGER.warn(ChampCoreMsgs.CHAMPCORE_GRAPH_ML_IMPORTER_EXPORTER_WARN,
354                             "Failed to marshall ChampObject to backend type. " + e.getMessage());
355                 } catch (ChampSchemaViolationException e) {
356                         LOGGER.error(ChampCoreMsgs.CHAMPCORE_GRAPH_ML_IMPORTER_EXPORTER_ERROR,
357                             "Failed to store object (schema violated): " + objectToStore + " " + e.getMessage());
358                 } catch (ChampObjectNotExistsException e) {
359                         LOGGER.error(ChampCoreMsgs.CHAMPCORE_GRAPH_ML_IMPORTER_EXPORTER_ERROR,
360                             "Failed to update existing ChampObject. " + e.getMessage());
361                 } catch (ChampTransactionException e) {
362           LOGGER.error(ChampCoreMsgs.CHAMPCORE_GRAPH_ML_IMPORTER_EXPORTER_ERROR,
363               "Failed to commit or rollback transaction");
364         }
365         }
366
367         @Override
368         public void exportData(ChampGraph graph, OutputStream os) {
369
370                 final XMLOutputFactory output = XMLOutputFactory.newInstance();
371
372                 try {
373                         final XMLStreamWriter writer = output.createXMLStreamWriter(os);
374
375                         writer.writeStartDocument();
376                         writer.writeStartElement("graphml");
377                         writer.writeDefaultNamespace("http://graphml.graphdrawing.org/xmlns");
378                         writer.writeNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
379                         writer.writeAttribute("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation", "http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd");
380
381                         final List<ChampObject> nodes = new LinkedList<ChampObject> ();
382                         final List<ChampRelationship> edges = new LinkedList<ChampRelationship> ();
383                         final Map<String, GraphMLKey> nodeKeys = new HashMap<String, GraphMLKey> ();
384                         final Map<String, GraphMLKey> edgeKeys = new HashMap<String, GraphMLKey> ();
385                         final AtomicInteger elementCount = new AtomicInteger();
386
387                         graph.queryObjects(Collections.emptyMap(), Optional.empty()).forEach(object -> {
388                                 nodes.add(object);
389
390                                 for (Map.Entry<String, Object> property : object.getProperties().entrySet()) {
391                                         if (nodeKeys.containsKey(property.getKey())) continue;
392
393                                         nodeKeys.put(property.getKey(), new GraphMLKey("d" + elementCount.incrementAndGet(), property.getKey(), property.getValue().getClass()));
394                                 }
395
396                                 nodeKeys.put("type", new GraphMLKey("d" + elementCount.incrementAndGet(), "type", String.class));
397                         });
398
399                         graph.queryRelationships(Collections.emptyMap(), Optional.empty()).forEach(relationship -> {
400                                 edges.add(relationship);
401
402                                 for (Map.Entry<String, Object> property : relationship.getProperties().entrySet()) {
403                                         if (nodeKeys.containsKey(property.getKey())) continue;
404
405                                         edgeKeys.put(property.getKey(), new GraphMLKey("d" + elementCount.incrementAndGet(), property.getKey(), property.getValue().getClass()));
406                                 }
407
408                                 edgeKeys.put("type", new GraphMLKey("d" + elementCount.incrementAndGet(), "type", String.class));
409                         });
410
411                         for (Entry<String, GraphMLKey> nodeKey : nodeKeys.entrySet()) {
412                                 final GraphMLKey graphMlKey = nodeKey.getValue();
413
414                                 writer.writeStartElement("key");
415                                 writer.writeAttribute("id", graphMlKey.id);
416                                 writer.writeAttribute("for", "node");
417                                 writer.writeAttribute("attr.name", graphMlKey.attrName);
418                                 writer.writeAttribute("attr.type", graphMlKey.attrType);
419                                 writer.writeEndElement();
420                         }
421
422                         for (Entry<String, GraphMLKey> edgeKey : edgeKeys.entrySet()) {
423                                 final GraphMLKey graphMlKey = edgeKey.getValue();
424
425                                 writer.writeStartElement("key");
426                                 writer.writeAttribute("id", graphMlKey.id);
427                                 writer.writeAttribute("for", "edge");
428                                 writer.writeAttribute("attr.name", graphMlKey.attrName);
429                                 writer.writeAttribute("attr.type", graphMlKey.attrType);
430                                 writer.writeEndElement();
431                         }
432
433                         for (ChampObject object : nodes) {
434                                 try {
435                                         writer.writeStartElement("node");
436                                         writer.writeAttribute("id", String.valueOf(object.getKey().get()));
437
438                                         writer.writeStartElement("data");
439                                         writer.writeAttribute("key", nodeKeys.get("type").id);
440                                         writer.writeCharacters(object.getType());
441                                         writer.writeEndElement();
442
443                                         for (Entry<String, Object> property : object.getProperties().entrySet()) {
444                                                 final GraphMLKey key = nodeKeys.get(property.getKey());
445
446                                                 writer.writeStartElement("data");
447                                                 writer.writeAttribute("key", key.id);
448                                                 writer.writeCharacters(String.valueOf(property.getValue()));
449                                                 writer.writeEndElement();
450                                         }
451
452                                         writer.writeEndElement();
453                                 } catch (XMLStreamException e) {
454                                         throw new RuntimeException("Failed to write edge to output stream", e);
455                                 }
456                         }
457
458                         for (ChampRelationship relationship : edges) {
459                                 try {
460                                         writer.writeStartElement("edge");
461                                         writer.writeAttribute("id", String.valueOf(relationship.getKey().get()));
462
463                                         writer.writeStartElement("data");
464                                         writer.writeAttribute("key", edgeKeys.get("type").id);
465                                         writer.writeCharacters(relationship.getType());
466                                         writer.writeEndElement();
467
468                                         for (Entry<String, Object> property : relationship.getProperties().entrySet()) {
469                                                 final GraphMLKey key = edgeKeys.get(property.getKey());
470
471                                                 writer.writeStartElement("data");
472                                                 writer.writeAttribute("key", key.id);
473                                                 writer.writeCharacters(String.valueOf(property.getValue()));
474                                                 writer.writeEndElement();
475                                         }
476
477                                         writer.writeEndElement();
478                                 } catch (XMLStreamException e) {
479                                         throw new RuntimeException("Failed to write edge to output stream", e);
480                                 }
481                         }
482
483                         writer.writeEndElement();
484                         writer.writeEndDocument();
485                         writer.flush();
486                 } catch (XMLStreamException | ChampTransactionException e) {
487                         throw new RuntimeException(e);
488                 }
489         }
490 }