Merge "Removing { } from NormalizedNodeJsonBodyWriter"
[controller.git] / opendaylight / netconf / netconf-testtool / src / main / java / org / opendaylight / controller / netconf / test / tool / rpc / SimulatedCreateSubscription.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.controller.netconf.test.tool.rpc;
10
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import java.io.File;
14 import java.io.IOException;
15 import java.text.SimpleDateFormat;
16 import java.util.Date;
17 import java.util.List;
18 import java.util.concurrent.Executors;
19 import java.util.concurrent.ScheduledExecutorService;
20 import java.util.concurrent.TimeUnit;
21 import javax.xml.bind.JAXBContext;
22 import javax.xml.bind.JAXBException;
23 import javax.xml.bind.Unmarshaller;
24 import javax.xml.bind.annotation.XmlRootElement;
25 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
26 import org.opendaylight.controller.netconf.api.NetconfMessage;
27 import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
28 import org.opendaylight.controller.netconf.impl.NetconfServerSession;
29 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultNetconfOperation;
30 import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation;
31 import org.opendaylight.controller.netconf.util.xml.XmlElement;
32 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
33 import org.w3c.dom.Document;
34 import org.w3c.dom.Element;
35 import org.xml.sax.SAXException;
36
37 public class SimulatedCreateSubscription extends AbstractLastNetconfOperation implements DefaultNetconfOperation {
38
39     private NetconfServerSession session;
40     private final Optional<Notifications> notifications;
41     private ScheduledExecutorService scheduledExecutorService;
42
43     public SimulatedCreateSubscription(final String id, final Optional<File> notificationsFile) {
44         super(id);
45         if(notificationsFile.isPresent()) {
46             notifications = Optional.of(loadNotifications(notificationsFile.get()));
47             scheduledExecutorService = Executors.newScheduledThreadPool(1);
48         } else {
49             notifications = Optional.absent();
50         }
51     }
52
53     private Notifications loadNotifications(final File file) {
54         try {
55             final JAXBContext jaxbContext = JAXBContext.newInstance(Notifications.class);
56             final Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
57             return (Notifications) jaxbUnmarshaller.unmarshal(file);
58         } catch (final JAXBException e) {
59             throw new IllegalArgumentException("Canot parse file " + file + " as a notifications file", e);
60         }
61     }
62
63     @Override
64     protected String getOperationName() {
65         return "create-subscription";
66     }
67
68     @Override
69     protected String getOperationNamespace() {
70         return "urn:ietf:params:xml:ns:netconf:notification:1.0";
71     }
72
73     @Override
74     protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement) throws NetconfDocumentedException {
75
76
77         if(notifications.isPresent()) {
78             long delayAggregator = 0;
79             System.console().writer().println("Scheduling notifications " + notifications.get());
80
81             for (final Notification notification : notifications.get().getNotificationList()) {
82                 for (int i = 0; i <= notification.getTimes(); i++) {
83
84                     delayAggregator += notification.getDelayInSeconds();
85
86                     System.console().writer().println("Times " + notification.getTimes());
87                     scheduledExecutorService.schedule(new Runnable() {
88                         @Override
89                         public void run() {
90                             try {
91                                 System.console().writer().println("Sending actual notification " + notification);
92                                 Preconditions.checkState(session != null, "Session is not set, cannot process notifications");
93                                 session.sendMessage(parseNetconfNotification(notification.getContent()));
94                             } catch (IOException | SAXException e) {
95                                 throw new IllegalStateException("Unable to process notification " + notification, e);
96                             }
97                         }
98                     }, delayAggregator, TimeUnit.SECONDS);
99                 }
100             }
101         }
102         return XmlUtil.createElement(document, XmlNetconfConstants.OK, Optional.<String>absent());
103     }
104
105     private static NetconfMessage parseNetconfNotification(String content) throws IOException, SAXException {
106         final int startEventTime = content.indexOf("<eventTime>") + "<eventTime>".length();
107         final int endEventTime = content.indexOf("</eventTime>");
108         final String eventTime = content.substring(startEventTime, endEventTime);
109         if(eventTime.equals("XXXX")) {
110             content = content.replace(eventTime, new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").format(new Date()));
111         }
112
113         return new NetconfMessage(XmlUtil.readXmlToDocument(content));
114     }
115
116     @Override
117     public void setNetconfSession(final NetconfServerSession s) {
118         this.session = s;
119     }
120
121     @XmlRootElement(name = "notifications")
122     public static final class Notifications {
123
124         @javax.xml.bind.annotation.XmlElement(nillable =  false, name = "notification", required = true)
125         private List<Notification> notificationList;
126
127         public List<Notification> getNotificationList() {
128             return notificationList;
129         }
130
131         @Override
132         public String toString() {
133             final StringBuffer sb = new StringBuffer("Notifications{");
134             sb.append("notificationList=").append(notificationList);
135             sb.append('}');
136             return sb.toString();
137         }
138     }
139
140     public static final class Notification {
141
142         @javax.xml.bind.annotation.XmlElement(nillable = false, name = "delay")
143         private long delayInSeconds;
144
145         @javax.xml.bind.annotation.XmlElement(nillable = false, name = "times")
146         private long times;
147
148         @javax.xml.bind.annotation.XmlElement(nillable = false, name = "content", required = true)
149         private String content;
150
151         public long getDelayInSeconds() {
152             return delayInSeconds;
153         }
154
155         public long getTimes() {
156             return times;
157         }
158
159         public String getContent() {
160             return content;
161         }
162
163         @Override
164         public String toString() {
165             final StringBuffer sb = new StringBuffer("Notification{");
166             sb.append("delayInSeconds=").append(delayInSeconds);
167             sb.append(", times=").append(times);
168             sb.append(", content='").append(content).append('\'');
169             sb.append('}');
170             return sb.toString();
171         }
172     }
173 }