2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.netconf.test.tool.customrpc;
11 import com.google.common.collect.ArrayListMultimap;
12 import com.google.common.collect.Multimap;
14 import java.util.Collection;
15 import java.util.Iterator;
16 import java.util.List;
18 import java.util.Optional;
19 import java.util.stream.Stream;
20 import javax.xml.bind.JAXB;
21 import org.opendaylight.controller.config.util.xml.DocumentedException;
22 import org.opendaylight.controller.config.util.xml.XmlElement;
23 import org.opendaylight.controller.config.util.xml.XmlUtil;
24 import org.w3c.dom.Attr;
25 import org.w3c.dom.Document;
28 * Mapping between RPCs and responses.
32 private final Multimap<Request, Document> requestToResponseMap = ArrayListMultimap.create();
35 * Creates new mapping from file.
37 * @param config config file
39 RpcMapping(final File config) {
40 final Rpcs rpcs = JAXB.unmarshal(config, Rpcs.class);
41 for (final Rpc rpc : rpcs.getRpcs()) {
42 final Stream<Document> stream = rpc.getOutput().stream()
43 .map(XmlData::getData);
44 final XmlElement element = XmlElement.fromDomDocument(rpc.getInput().getData());
45 requestToResponseMap.putAll(new Request(element), stream::iterator);
50 * Returns response matching given input. If multiple responses are configured for the same
51 * request, every invocation of this method returns next response as they are defined in the config file.
52 * Last configured response is used, when number of invocations is higher than number of configured responses
55 * @param input request
56 * @return response document, or absent if mapping is not defined
58 Optional<Document> getResponse(final XmlElement input) {
59 final Collection<Document> responses = requestToResponseMap.get(new Request(input));
60 final Iterator<Document> iterator = responses.iterator();
61 if (iterator.hasNext()) {
62 final Document response = iterator.next();
63 if (iterator.hasNext()) {
66 return Optional.of(response);
68 return Optional.empty();
72 * Rpc input wrapper. Needed because of custom {@link Request#equals(Object)}
73 * and {@link Request#hashCode()} implementations.
75 private static class Request {
76 private final XmlElement xmlElement;
77 private final int hashCode;
79 private Request(final XmlElement element) {
80 this.xmlElement = element;
81 hashCode = XmlUtil.toString(element)
82 .replaceAll("message-id=.*(>| )", "") //message id is variable, remove it
83 .replaceAll("\\s+", "") //remove whitespaces
88 public boolean equals(final Object o) {
92 if (o == null || getClass() != o.getClass()) {
95 final Request request = (Request) o;
96 return documentEquals(this.xmlElement, request.xmlElement);
100 public int hashCode() {
104 private static boolean documentEquals(final XmlElement e1, final XmlElement e2) {
105 if (!e1.getNamespaceOptionally().equals(e2.getNamespaceOptionally())) {
108 if (!e1.getName().equals(e2.getName())) {
111 if (attributesNotEquals(e1, e2)) {
115 final List<XmlElement> e1Children = e1.getChildElements();
116 final List<XmlElement> e2Children = e2.getChildElements();
117 if (e1Children.size() != e2Children.size()) {
120 final Iterator<XmlElement> e1Iterator = e1Children.iterator();
121 final Iterator<XmlElement> e2Iterator = e2Children.iterator();
122 while (e1Iterator.hasNext() && e2Iterator.hasNext()) {
123 if (!documentEquals(e1Iterator.next(), e2Iterator.next())) {
128 if (e1Children.isEmpty() && e1Children.isEmpty()) {
130 return e1.getTextContent().equals(e2.getTextContent());
131 } catch (final DocumentedException e) {
138 private static boolean attributesNotEquals(final XmlElement e1, final XmlElement e2) {
139 final Map<String, Attr> e1Attrs = e1.getAttributes();
140 final Map<String, Attr> e2Attrs = e2.getAttributes();
141 final Iterator<Map.Entry<String, Attr>> e1AttrIt = e1Attrs.entrySet().iterator();
142 final Iterator<Map.Entry<String, Attr>> e2AttrIt = e2Attrs.entrySet().iterator();
143 while (e1AttrIt.hasNext() && e2AttrIt.hasNext()) {
144 final Map.Entry<String, Attr> e1Next = e1AttrIt.next();
145 final Map.Entry<String, Attr> e2Next = e2AttrIt.next();
146 if (e1Next.getKey().equals("message-id") && e2Next.getKey().equals("message-id")) {
149 if (e1Next.getKey().equals("xmlns") && e2Next.getKey().equals("xmlns")) {
152 if (!e1Next.getKey().equals(e2Next.getKey())) {
155 if (!e1Next.getValue().getValue().equals(e2Next.getValue().getValue())) {