Network topology and inventory init
[transportpce.git] / inventory / src / main / java / org / opendaylight / transportpce / inventory / listener / ServiceListener.java
1 /*
2  * Copyright © 2017 AT&T 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 package org.opendaylight.transportpce.inventory.listener;
9
10 import java.sql.Connection;
11 import java.sql.PreparedStatement;
12 import java.sql.SQLException;
13 import java.util.Collection;
14 import java.util.List;
15 import java.util.stream.Collectors;
16 import javax.sql.DataSource;
17 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
18 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
19 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
20 import org.opendaylight.transportpce.inventory.query.Queries;
21 import org.opendaylight.transportpce.inventory.query.QueryUtils;
22 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceList;
23 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.service.list.Services;
24 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 /**
29  * {@link ServiceListener} listens on {@link ServiceList} changes.
30  *
31  */
32 public class ServiceListener implements DataTreeChangeListener<ServiceList> {
33
34     private static final Logger LOG = LoggerFactory.getLogger(ServiceListener.class);
35     public static final InstanceIdentifier<ServiceList> SERVICES_II =
36             InstanceIdentifier.create(ServiceList.class);
37     /**
38      * Implementation for the {@link ChangeHandler} stores a newly added {@link Services}.
39      */
40     private static final ChangeHandler CREATE_HANDLER = (services, connection) -> {
41         try (PreparedStatement stmt = connection.prepareStatement(Queries.getQuery().serviceCreate().get())) {
42             QueryUtils.setCreateServiceParameters(stmt, services);
43             stmt.executeUpdate();
44             stmt.clearParameters();
45         } catch (SQLException e) {
46             LOG.error("Could not insert service path {}", services);
47         }
48     };
49
50     /**
51      * Implementation for the {@link ChangeHandler} removes the deleted {@link Services}.
52      */
53     private static final ChangeHandler DELETE_HANDLER = (services, connection) -> {
54         try (PreparedStatement stmt = connection.prepareStatement(Queries.getQuery().serviceDelete().get())) {
55             stmt.setString(1, services.getServiceName());
56             stmt.executeUpdate();
57             stmt.clearParameters();
58         } catch (SQLException e) {
59             LOG.error("Could not delete service path {}", services);
60             LOG.error(e.getMessage(), e);
61         }
62     };
63
64     private final DataSource dataSource;
65
66     /**
67      * Default constructor invoked by bluprint injects all required dependencies.
68      *
69      * @param dataSource reference for {@link DataSource}
70      */
71     public ServiceListener(DataSource dataSource) {
72         this.dataSource = dataSource;
73     }
74
75     @Override
76     public void onDataTreeChanged(Collection<DataTreeModification<ServiceList>> changes) {
77         LOG.debug("Service path list changed ...");
78         List<DataTreeModification<ServiceList>> createItems =
79                 changes.stream().filter(ServiceListener::writeFilter).collect(Collectors.toList());
80         List<DataTreeModification<ServiceList>> deleteItems =
81                 changes.stream().filter(ServiceListener::deleteFilter).collect(Collectors.toList());
82         try (Connection connection = dataSource.getConnection()) {
83             handleModification(createItems, CREATE_HANDLER, connection);
84             handleModification(deleteItems, DELETE_HANDLER, connection);
85         } catch (SQLException e) {
86             LOG.error(e.getMessage(), e);
87         }
88     }
89
90     /**
91      * Handles the change with {@link ChangeHandler}.
92      *
93      * @param changeList list of modifications
94      * @param handleChange concrete implementation of {@link ChangeHandler}
95      * @param connection {@link DataSource} we don't want to create each time a new connection
96      */
97     private void handleModification(List<DataTreeModification<ServiceList>> changeList, ChangeHandler handleChange,
98             Connection connection) {
99         for (DataTreeModification<ServiceList> change : changeList) {
100             ServiceList serviceList = change.getRootNode().getDataAfter();
101             for (Services service : serviceList.getServices()) {
102                 handleChange.handleChange(service, connection);
103             }
104         }
105     }
106
107     /**
108      * Returns the filter for {@link ModificationType#WRITE} type change.
109      *
110      * @see #buildFilter(DataTreeModification, ModificationType)
111      * @param modification write modification object
112      * @return if the object was created
113      */
114     private static boolean writeFilter(DataTreeModification<ServiceList> modification) {
115         return buildFilter(modification, ModificationType.WRITE);
116     }
117
118     /**
119      * Returns the filter for {@link ModificationType#DELETE} type change.
120      *
121      * @see #deleteFilter(DataTreeModification)
122      * @param modification delete modification
123      * @return if the object was deleted
124      */
125     private static boolean deleteFilter(DataTreeModification<ServiceList> modification) {
126         return buildFilter(modification, ModificationType.DELETE);
127     }
128
129     /**
130      * Generalizes the creation of filter used in
131      * {@link #onDataTreeChanged(Collection)} method.
132      *
133      * @param modification a modification
134      * @param modificationType a modification type
135      * @return boolean modification status
136      */
137     private static boolean buildFilter(DataTreeModification<ServiceList> modification,
138             ModificationType modificationType) {
139         return (modification.getRootNode().getDataAfter() != null
140                 && modificationType.equals(modification.getRootNode().getModificationType()));
141     }
142
143     /**
144      * ChangeHandler interface is responsible for inserts or deletes in the DB based
145      * on the implementation.
146      *
147      */
148     private interface ChangeHandler {
149
150         /**
151          * Method will handle the changed {@link Services}.
152          *
153          * @param services changed object
154          * @param connection {@link Connection} should be created in the caller method and
155          *        not closed in the implementation
156          */
157         void handleChange(Services services, Connection connection);
158     }
159
160 }