DMAAP-83 Initial code import
[dmaap/dbcapi.git] / src / main / java / org / onap / dmaap / dbcapi / service / FeedService.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * org.onap.dmaap
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.dmaap.dbcapi.service;
22
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.Map;
26
27 import javax.ws.rs.core.Response.Status;
28
29 import org.apache.log4j.Logger;
30 import org.onap.dmaap.dbcapi.aaf.client.DrProvConnection;
31 import org.onap.dmaap.dbcapi.aaf.database.DatabaseClass;
32 import org.onap.dmaap.dbcapi.logging.BaseLoggingClass;
33 import org.onap.dmaap.dbcapi.model.ApiError;
34 import org.onap.dmaap.dbcapi.model.DR_Pub;
35 import org.onap.dmaap.dbcapi.model.DR_Sub;
36 import org.onap.dmaap.dbcapi.model.Feed;
37 import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status;
38 import org.onap.dmaap.dbcapi.util.DmaapConfig;
39
40 public class FeedService  extends BaseLoggingClass {
41         
42         private Map<String, Feed> feeds = DatabaseClass.getFeeds();
43         private DR_PubService pubService = new DR_PubService();
44         private DR_SubService subService = new DR_SubService();
45         private DcaeLocationService dcaeLocations = new DcaeLocationService();
46         private String deleteHandling;
47         
48         public FeedService() {
49                 logger.info( "new FeedService");
50                 DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig();
51                 deleteHandling = p.getProperty("Feed.deleteHandling", "DeleteOnDR");
52
53         }
54         
55         public Map<String, Feed> getFeeds() {                   
56                 return feeds;
57         }
58         
59         private void getSubObjects( Feed f ) {
60                 ArrayList<DR_Pub> pubs = pubService.getDr_PubsByFeedId( f.getFeedId() );
61                 f.setPubs(pubs);
62                 ArrayList<DR_Sub> subs = subService.getDr_SubsByFeedId( f.getFeedId() );
63                 f.setSubs(subs);        
64         }
65                 
66         public List<Feed> getAllFeeds() {
67                 ArrayList<Feed> fatFeeds = new ArrayList<Feed>();
68                 for( Feed f:  feeds.values() ) {
69                         getSubObjects(f);
70                         fatFeeds.add(f);
71                 }
72                 return fatFeeds;
73         }
74         
75         
76         private Feed _getFeed( String key, ApiError err, boolean flag ) {
77                 Feed f = feeds.get( key );
78                 if ( f != null && ( flag || f.getStatus() != DmaapObject_Status.DELETED ) ) {
79                         getSubObjects( f );
80                 } else {
81                         err.setCode(Status.NOT_FOUND.getStatusCode());
82                         err.setMessage("feed not found");
83                         err.setFields("feedId=" + key );
84                         return null;
85                 }
86                 err.setCode(200);
87                 return f;
88         }
89         public Feed getFeed( String key, ApiError err ) {
90                 return _getFeed( key, err, false );
91         }
92         public Feed getFeedPure( String key, ApiError err ) {
93                 return _getFeed( key, err, true );
94         }
95         
96         public Feed getFeedByName( String name, String ver, ApiError err ) {
97                 for( Feed f:  feeds.values() ) {
98                         if ( f.getFeedName().equals( name ) && f.getFeedVersion().equals(ver) ) {
99                                 getSubObjects(f);
100                                 return f;
101                         }
102         
103                 }
104                 err.setCode(Status.NOT_FOUND.getStatusCode());
105                 err.setMessage("feed not found");
106                 err.setFields("feedName=" + name + " and ver=" + ver );
107                 return null;
108         
109         }
110
111         private boolean savePubs( Feed f ) {
112                 return savePubs( f, f );
113         }
114         // need to save the Pub objects independently and copy pubId from original request
115         private boolean savePubs( Feed fnew, Feed req ) {
116                 // save any pubs
117                 DR_PubService pubSvc = new DR_PubService();
118                 ArrayList<DR_Pub> reqPubs = req.getPubs();
119                 ArrayList<DR_Pub> newPubs = fnew.getPubs();
120                 
121
122                 
123                 int nSize = newPubs.size();
124                 int rSize = reqPubs.size();
125                 logger.info( "reqPubs size=" + rSize + " newPubs size=" + nSize );
126                 if ( nSize != rSize ) {
127                         errorLogger.error( "Resulting set of publishers do not match requested set of publishers " + nSize + " vs " + rSize );
128                         fnew.setStatus( DmaapObject_Status.INVALID);
129                         return false;
130                 }
131                 // NOTE: when i > 1 newPubs are in reverse order from reqPubs
132                 for( int i = 0; i < reqPubs.size(); i++ ) {
133                         DR_Pub reqPub = reqPubs.get(i); 
134                         ApiError err = new ApiError();
135                         if ( pubSvc.getDr_Pub( reqPub.getPubId(), err ) == null ) {
136                                 DR_Pub newPub = newPubs.get(nSize - i - 1);
137                                 reqPub.setPubId(newPub.getPubId());
138                                 reqPub.setFeedId(newPub.getFeedId());
139                                 reqPub.setStatus(DmaapObject_Status.VALID);
140                                 if ( reqPub.getDcaeLocationName() == null ) {
141                                         reqPub.setDcaeLocationName("notSpecified");
142                                 }
143                                 pubSvc.addDr_Pub( reqPub );
144                         }
145                         
146                 }
147                 
148                 fnew.setPubs(reqPubs);
149                 fnew.setStatus(DmaapObject_Status.VALID);
150                 return true;
151
152         }
153         
154         private boolean saveSubs( Feed f ) {
155                 return saveSubs( f, f );
156         }
157         // need to save the Sub objects independently
158         private boolean saveSubs( Feed fnew, Feed req ) {       
159                 ArrayList<DR_Sub> subs = req.getSubs();
160                 if ( subs.size() == 0 ) {
161                         logger.info( "No subs specified");
162                 } else {
163                         DR_SubService subSvc = new DR_SubService( fnew.getSubscribeURL() );
164                         ApiError err = new ApiError();
165                         for( int i = 0; i <  subs.size(); i++ ) {
166                                 DR_Sub sub = subs.get(i);
167                                 if ( subSvc.getDr_Sub( sub.getSubId(), err) == null ) {
168                                         subs.set( i,  subSvc.addDr_Sub(sub, err));
169                                         if ( ! err.is2xx())  {
170                                                 logger.error( "i=" + i + " url=" + sub.getDeliveryURL() + " err=" + err.getCode() );
171                                                 return false;
172                                         }
173                                 }
174                                 
175                         }
176                         fnew.setSubs(subs);
177                 }
178
179
180                 fnew.setStatus(DmaapObject_Status.VALID);
181                 return true;
182
183         }
184
185         public  Feed addFeed( Feed req, ApiError err ) {
186
187                 // at least 1 pub is required by DR, so create a default pub if none is specified
188                 if ( req.getPubs().size() == 0 ) {
189                         logger.info( "No pubs specified - creating tmp pub");
190                         ArrayList<DR_Pub> pubs = new ArrayList<DR_Pub>();
191                         pubs.add( new DR_Pub( dcaeLocations.getCentralLocation())
192                                                                 .setRandomUserName()
193                                                                 .setRandomPassword());
194                         req.setPubs(pubs);
195                 } 
196                 
197
198                 DrProvConnection prov = new DrProvConnection();
199                 prov.makeFeedConnection();      
200                 String resp = prov.doPostFeed( req, err );
201                 logger.info( "resp=" + resp );
202                 if ( resp == null ) {
203                         switch( err.getCode() ) {
204                         case 400: 
205                                 err.setFields( "feedName=" + req.getFeedName() + " + feedVersion=" + req.getFeedVersion() );
206                                 break;
207                         case 403:
208                                 err.setCode(500);
209                                 err.setMessage("API deployment/configuration error - contact support");
210                                 err.setFields( "PROV_AUTH_ADDRESSES");
211                                 logger.error( "Prov response: 403. " + err.getMessage() + " regarding " + err.getFields() );
212                                 break;
213                         default:
214                                 err.setCode(500);
215                                 err.setMessage( "Unexpected response from DR backend" );
216                                 err.setFields("response");
217                         }
218                         return null;
219
220                 }
221
222
223                 Feed fnew = new Feed( resp );
224                 logger.info( "fnew status is:" + fnew.getStatus() );
225                 if ( ! fnew.isStatusValid()) {          
226                         err.setCode(500);
227                         err.setMessage( "Unexpected response from DR backend" );
228                         err.setFields("response");              
229                         return null;
230                 }
231                 
232                 //saveChildren( fnew, req );
233                 if ( ! savePubs( fnew, req ) || ! saveSubs( fnew, req ) ) {
234                         err.setCode(Status.BAD_REQUEST.getStatusCode());
235                         err.setMessage("Unable to save Pub or Sub objects");
236                         return null;
237                 }
238                 fnew.setFormatUuid(req.getFormatUuid());
239                 fnew.setLastMod();
240                 feeds.put( fnew.getFeedId(), fnew );
241                 return fnew;
242         }
243                 
244         public Feed updateFeed( Feed req, ApiError err ) {
245         
246                 // at least 1 pub is required by DR, so create a default pub if none is specified
247                 if ( req.getPubs().size() == 0 ) {
248                         logger.info( "No pubs specified - creating tmp pub");
249                         ArrayList<DR_Pub> pubs = new ArrayList<DR_Pub>();
250                         pubs.add( new DR_Pub( dcaeLocations.getCentralLocation())
251                                                                 .setRandomUserName()
252                                                                 .setRandomPassword());
253                         req.setPubs(pubs);
254                 } 
255                 
256                 DrProvConnection prov = new DrProvConnection();
257                 prov.makeFeedConnection( req.getFeedId() );
258                 String resp = prov.doPutFeed( req, err );
259                 logger.info( "resp=" + resp );
260                 if ( resp == null ) {
261                         switch( err.getCode() ) {
262                         case 400: 
263                                 err.setFields( "feedName=" + req.getFeedName() + " + feedVersion=" + req.getFeedVersion() );
264                                 break;
265                         case 403:
266                                 err.setCode(500);
267                                 err.setMessage("API deployment/configuration error - contact support");
268                                 err.setFields( "PROV_AUTH_ADDRESSES");
269                                 break;
270                         default:
271                                 err.setCode(500);
272                                 err.setMessage( "Unexpected response from DR backend" );
273                                 err.setFields("response");
274                         }
275                         return null;
276                 }
277
278
279                 Feed fnew = new Feed( resp );
280                 logger.info( "fnew status is:" + fnew.getStatus() );
281                 if ( ! fnew.isStatusValid()) {          
282                         err.setCode(500);
283                         err.setMessage( "Unexpected response from DR backend" );
284                         err.setFields("response");              
285                         return null;
286                 }
287
288                 if ( ! savePubs( fnew, req ) || ! saveSubs( fnew, req ) ) {
289                         err.setCode(Status.BAD_REQUEST.getStatusCode());
290                         err.setMessage("Unable to save Pub or Sub objects");
291                         return null;
292                 }
293                 fnew.setFormatUuid(req.getFormatUuid());
294                 fnew.setLastMod();
295                 feeds.put( fnew.getFeedId(), fnew );
296                 return fnew;
297         }
298         
299         
300         //
301         // DR does not actually delete a feed, so we provide two behaviors:
302         // 1) clean up the feed by removing all subs and pubs, mark it here as DELETED.
303         //    then client can add it back if desired.
304         // 2) Call the DR Delete function.  Feed with the same name and version can never be added again
305         //
306         public Feed removeFeed( Feed req, ApiError err ) {
307                 
308                 // strip pubs and subs from feed first no matter what
309                 ArrayList<DR_Pub> pubs = pubService.getDr_PubsByFeedId( req.getFeedId() );
310                 for( DR_Pub pub: pubs ) {
311                         pubService.removeDr_Pub(pub.getPubId(), err);
312                         if ( ! err.is2xx()) {
313                                 return req;
314                         }
315                 }
316                 ArrayList<DR_Sub> subs = subService.getDr_SubsByFeedId( req.getFeedId() );
317                 for ( DR_Sub sub: subs ) {
318                         subService.removeDr_Sub(sub.getSubId(), err);
319                         if ( ! err.is2xx()) {
320                                 return req;
321                         }
322                 }
323         
324                 if ( deleteHandling.equalsIgnoreCase("DeleteOnDR")) {
325                         DrProvConnection prov = new DrProvConnection();
326                         prov.makeFeedConnection( req.getFeedId() );
327                         String resp = prov.doDeleteFeed( req, err );
328                         logger.info( "resp=" + resp );
329                         if ( resp == null ) {
330                                 switch( err.getCode() ) {
331                                 case 400: 
332                                         err.setFields( "feedName=" + req.getFeedName() + " + feedVersion=" + req.getFeedVersion() );
333                                         break;
334                                 case 403:
335                                         err.setCode(500);
336                                         err.setMessage("API deployment/configuration error - contact support");
337                                         err.setFields( "PROV_AUTH_ADDRESSES");
338                                         break;
339                                 default:
340                                         err.setCode(500);
341                                         err.setMessage( "Unexpected response from DR backend" );
342                                         err.setFields("response");
343                                 }
344                                 return req;  // return back the requested feed - implies it wasn't removed
345                         }
346                         return feeds.remove(req.getFeedId());
347                 } else {
348                         req.setStatus(DmaapObject_Status.DELETED);
349                         req.setPubs(null);
350                         req.setSubs(null);
351                         req.setLastMod();
352                         feeds.put( req.getFeedId(), req );
353                         return null;
354                 }
355
356                 
357         }       
358
359 }