update deprecated transform and addCallback methods
[groupbasedpolicy.git] / sxp-integration / sxp-ep-provider / src / main / java / org / opendaylight / groupbasedpolicy / sxp / ep / provider / impl / dao / EPPolicyTemplateDaoFacadeImpl.java
1 /*
2  * Copyright (c) 2016 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.groupbasedpolicy.sxp.ep.provider.impl.dao;
10
11 import com.google.common.base.Function;
12 import com.google.common.base.Optional;
13 import com.google.common.util.concurrent.AsyncFunction;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.ListenableFuture;
16 import com.google.common.util.concurrent.MoreExecutors;
17
18 import java.util.Collection;
19 import java.util.Collections;
20 import javax.annotation.Nonnull;
21 import javax.annotation.Nullable;
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.api.EPPolicyTemplateDaoFacade;
26 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.api.EPPolicyTemplateProvider;
27 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SgtGeneratorImpl;
28 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ep.provider.model.rev160302.SxpEpMapper;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ep.provider.model.rev160302.TemplateGenerated;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgtBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgtKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 /**
40  * Purpose: add template provider fallback to {@link EPPolicyTemplateDaoImpl}
41  */
42 public class EPPolicyTemplateDaoFacadeImpl implements EPPolicyTemplateDaoFacade {
43
44     private static final Logger LOG = LoggerFactory.getLogger(EPPolicyTemplateDaoFacadeImpl.class);
45
46     private final EPPolicyTemplateDaoImpl epPolicyTemplateDao;
47     private final SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> epPolicyTemplateCachedDao;
48     private final SgtGeneratorImpl sgtGenerator;
49     private final DataBroker dataBroker;
50
51     private EPPolicyTemplateProvider templateProvider;
52
53     public EPPolicyTemplateDaoFacadeImpl(final DataBroker dataBroker, final EPPolicyTemplateDaoImpl epPolicyTemplateDao,
54                                          final SimpleCachedDao<Sgt, EndpointPolicyTemplateBySgt> epPolicyTemplateCachedDao,
55                                          final SgtGeneratorImpl sgtGenerator) {
56         this.dataBroker = dataBroker;
57         this.epPolicyTemplateDao = epPolicyTemplateDao;
58         this.epPolicyTemplateCachedDao = epPolicyTemplateCachedDao;
59         this.sgtGenerator = sgtGenerator;
60     }
61
62     @Override
63     public void setTemplateProvider(final EPPolicyTemplateProvider templateProvider) {
64         this.templateProvider = templateProvider;
65     }
66
67
68     @Override
69     public ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> read(@Nonnull final Sgt key) {
70         // read from delegate
71         final ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> templateFu = epPolicyTemplateDao.read(key);
72
73         // involve fallback if template is absent
74         return Futures.transformAsync(templateFu, new AsyncFunction<Optional<EndpointPolicyTemplateBySgt>, Optional<EndpointPolicyTemplateBySgt>>() {
75             @Override
76             public ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> apply(
77                     @Nonnull final Optional<EndpointPolicyTemplateBySgt> templateOpt) throws Exception {
78
79                 return templateOpt.transform(template -> Futures.immediateFuture(templateOpt))
80                         // failed to read template -> invoke fallback if available
81                         .or(() -> java.util.Optional.ofNullable(templateProvider)
82                                 .map(provider -> templateProvider.provideTemplate(key))
83                                 .map(template -> rewrapOptionalToGuavaOptional(template))
84                                 .orElse(Futures.immediateFuture(Optional.absent()))
85                         );
86             }
87         }, MoreExecutors.directExecutor());
88     }
89
90     private <T> ListenableFuture<Optional<T>> rewrapOptionalToGuavaOptional(final ListenableFuture<java.util.Optional<T>> templateFu) {
91         return Futures.transform(templateFu, new Function<java.util.Optional<T>, Optional<T>>() {
92                     @Nullable
93                     @Override
94                     public Optional<T> apply(@Nullable final java.util.Optional<T> input) {
95                         return java.util.Optional.ofNullable(input)
96                                 .map(origNonnullInput -> Optional.fromNullable(origNonnullInput.orElse(null)))
97                                 .orElse(Optional.absent());
98                     }
99                 },
100             MoreExecutors.directExecutor());
101     }
102
103
104     private Function<Void, Collection<EndpointPolicyTemplateBySgt>> createStoreOutcomeHandlerToCollection(final EndpointPolicyTemplateBySgt template) {
105         return new Function<Void, Collection<EndpointPolicyTemplateBySgt>>() {
106             @Nullable
107             @Override
108             public Collection<EndpointPolicyTemplateBySgt> apply(@Nullable final Void aVoid) {
109                 return Collections.singletonList(template);
110             }
111         };
112     }
113
114     @Override
115     public ListenableFuture<Collection<EndpointPolicyTemplateBySgt>> readBy(@Nonnull final EpPolicyTemplateValueKey templateLookupKey) {
116         //TODO: expose to ios-xe renderer,
117         final Collection<EndpointPolicyTemplateBySgt> templatesFromDao = epPolicyTemplateDao.readBy(templateLookupKey);
118         final ListenableFuture<Collection<EndpointPolicyTemplateBySgt>> result;
119         if (!templatesFromDao.isEmpty()) {
120             result = Futures.immediateFuture(templatesFromDao);
121         } else {
122             // generate
123             result = sgtGenerator.generateNextSgt(epPolicyTemplateCachedDao)
124                     // build ep-policy-template
125                     .map(sgt -> buildEpPolicyTemplate(templateLookupKey, sgt))
126                     // store the template
127                     .map(this::storeTemplate)
128                     .orElse(Futures.immediateFuture(Collections.emptyList()));
129         }
130         return result;
131     }
132
133     private ListenableFuture<Collection<EndpointPolicyTemplateBySgt>> storeTemplate(final EndpointPolicyTemplateBySgt template) {
134         final WriteTransaction wTx = dataBroker.newWriteOnlyTransaction();
135         // store ep-policy-template
136         final Sgt sgt = template.getSgt();
137         LOG.trace("storing generated epPolicyTemplate: {}", sgt.getValue());
138         final InstanceIdentifier<EndpointPolicyTemplateBySgt> epPolicyTemplatePath = InstanceIdentifier
139                 .create(SxpEpMapper.class)
140                 .child(EndpointPolicyTemplateBySgt.class, new EndpointPolicyTemplateBySgtKey(sgt));
141         wTx.put(LogicalDatastoreType.CONFIGURATION, epPolicyTemplatePath, template, true);
142
143         return Futures.transform(wTx.submit(), createStoreOutcomeHandlerToCollection(template),
144             MoreExecutors.directExecutor());
145     }
146
147     private EndpointPolicyTemplateBySgt buildEpPolicyTemplate(final EpPolicyTemplateValueKey templateLookupKey, final Sgt sgt) {
148         return new EndpointPolicyTemplateBySgtBuilder()
149                 .setOrigin(TemplateGenerated.class)
150                 .setTenant(templateLookupKey.getTenantId())
151                 .setSgt(sgt)
152                 .setEndpointGroups(templateLookupKey.getEpgId())
153                 .setConditions(templateLookupKey.getConditionName())
154                 .build();
155     }
156 }