5f1cfb8631a1ddf47fb67dde26faa2b3ac53f74c
[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 org.onap.dmaap.dbcapi.util.RandomInteger;
24
25 import java.util.ArrayList;
26 import java.util.List;
27 import java.util.Map;
28
29 import javax.ws.rs.core.Response.Status;
30
31 import org.apache.log4j.Logger;
32 import org.onap.dmaap.dbcapi.aaf.client.DrProvConnection;
33 import org.onap.dmaap.dbcapi.aaf.database.DatabaseClass;
34 import org.onap.dmaap.dbcapi.logging.BaseLoggingClass;
35 import org.onap.dmaap.dbcapi.model.ApiError;
36 import org.onap.dmaap.dbcapi.model.DR_Pub;
37 import org.onap.dmaap.dbcapi.model.DR_Sub;
38 import org.onap.dmaap.dbcapi.model.Feed;
39 import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status;
40 import org.onap.dmaap.dbcapi.util.DmaapConfig;
41
42 public class FeedService  extends BaseLoggingClass {
43         
44         private Map<String, Feed> feeds = DatabaseClass.getFeeds();
45         private DR_PubService pubService = new DR_PubService();
46         private DR_SubService subService = new DR_SubService();
47         private DcaeLocationService dcaeLocations = new DcaeLocationService();
48         private String deleteHandling;
49         private String unit_test;
50         
51         public FeedService() {
52                 logger.info( "new FeedService");
53                 DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig();
54                 deleteHandling = p.getProperty("Feed.deleteHandling", "DeleteOnDR");
55                 unit_test = p.getProperty( "UnitTest", "No" );
56
57         }
58         
59         public Map<String, Feed> getFeeds() {                   
60                 return feeds;
61         }
62         
63         private void getSubObjects( Feed f ) {
64                 ArrayList<DR_Pub> pubs = pubService.getDr_PubsByFeedId( f.getFeedId() );
65                 f.setPubs(pubs);
66                 ArrayList<DR_Sub> subs = subService.getDr_SubsByFeedId( f.getFeedId() );
67                 f.setSubs(subs);        
68         }
69                 
70         public List<Feed> getAllFeeds( String name, String ver, String match ) {
71                 logger.info( "getAllFeeds: name=" + name + " ver=" + ver + " match=" + match);
72                 ArrayList<Feed> fatFeeds = new ArrayList<Feed>();
73                 for( Feed f:  feeds.values() ) {
74                         boolean keep = true;
75                         if ( name != null ) {
76                                 if ( match != null && match.equals("startsWith") ) {
77                                         if ( ! f.getFeedName().startsWith( name ) ) {
78                                                 logger.info( "getAllFeeds: feedName=" + f.getFeedName() + " doesn't start with=" + name);
79                                                 keep = false;
80                                         }
81                                 } else if ( match != null && match.equals("contains") ) {
82                                         if ( ! f.getFeedName().contains( name ) ) {
83                                                 logger.info( "getAllFeeds: feedName=" + f.getFeedName() + " doesn't contain=" + name);
84                                                 keep = false;
85                                         }
86                                 } else {
87                                         if ( ! f.getFeedName().equals( name ) ) {
88                                                 logger.info( "getAllFeeds: feedName=" + f.getFeedName() + " doesn't equal=" + name);
89                                                 keep = false;
90                                         }
91                                 }
92
93                         }
94                         if ( keep && ver != null ) {
95                                 if ( ! f.getFeedVersion().equals(ver)) {
96                                         logger.info( "getAllFeeds: feedVersion=" + f.getFeedName() + " doesn't match " + ver);
97                                         keep = false;
98                                 } else {
99                                         logger.info( "getAllFeeds: feedVersion=" + f.getFeedName() + " matches " + ver);
100                                 }
101                         }
102                                         
103                         if (keep){
104                                 getSubObjects(f);
105                                 fatFeeds.add(f);
106                         }
107                 }
108                 return fatFeeds;
109         }
110         
111         
112         private Feed _getFeed( String key, ApiError err, boolean flag ) {
113                 Feed f = feeds.get( key );
114                 if ( f != null && ( flag || f.getStatus() != DmaapObject_Status.DELETED ) ) {
115                         getSubObjects( f );
116                 } else {
117                         err.setCode(Status.NOT_FOUND.getStatusCode());
118                         err.setMessage("feed not found");
119                         err.setFields("feedId=" + key );
120                         return null;
121                 }
122                 err.setCode(200);
123                 return f;
124         }
125         public Feed getFeed( String key, ApiError err ) {
126                 return _getFeed( key, err, false );
127         }
128         public Feed getFeedPure( String key, ApiError err ) {
129                 return _getFeed( key, err, true );
130         }
131         
132         public Feed getFeedByName( String name, String ver, ApiError err ) {
133                 for( Feed f:  feeds.values() ) {
134                         if ( f.getFeedName().equals( name ) && f.getFeedVersion().equals(ver) ) {
135                                 getSubObjects(f);
136                                 return f;
137                         }
138         
139                 }
140                 err.setCode(Status.NOT_FOUND.getStatusCode());
141                 err.setMessage("feed not found");
142                 err.setFields("feedName=" + name + " and ver=" + ver );
143                 return null;
144         
145         }
146
147         private boolean savePubs( Feed f ) {
148                 return savePubs( f, f );
149         }
150         // need to save the Pub objects independently and copy pubId from original request
151         private boolean savePubs( Feed fnew, Feed req ) {
152                 // save any pubs
153                 DR_PubService pubSvc = new DR_PubService();
154                 ArrayList<DR_Pub> reqPubs = req.getPubs();
155                 ArrayList<DR_Pub> newPubs = fnew.getPubs();
156                 
157
158                 
159                 int nSize = newPubs.size();
160                 int rSize = reqPubs.size();
161                 logger.info( "reqPubs size=" + rSize + " newPubs size=" + nSize );
162                 if ( nSize != rSize ) {
163                         errorLogger.error( "Resulting set of publishers do not match requested set of publishers " + nSize + " vs " + rSize );
164                         fnew.setStatus( DmaapObject_Status.INVALID);
165                         return false;
166                 }
167                 // NOTE: when i > 1 newPubs are in reverse order from reqPubs
168                 for( int i = 0; i < reqPubs.size(); i++ ) {
169                         DR_Pub reqPub = reqPubs.get(i); 
170                         ApiError err = new ApiError();
171                         if ( pubSvc.getDr_Pub( reqPub.getPubId(), err ) == null ) {
172                                 DR_Pub newPub = newPubs.get(nSize - i - 1);
173                                 reqPub.setPubId(newPub.getPubId());
174                                 reqPub.setFeedId(newPub.getFeedId());
175                                 reqPub.setStatus(DmaapObject_Status.VALID);
176                                 if ( reqPub.getDcaeLocationName() == null ) {
177                                         reqPub.setDcaeLocationName("notSpecified");
178                                 }
179                                 pubSvc.addDr_Pub( reqPub );
180                         }
181                         
182                 }
183                 
184                 fnew.setPubs(reqPubs);
185                 fnew.setStatus(DmaapObject_Status.VALID);
186                 return true;
187
188         }
189         
190         private boolean saveSubs( Feed f ) {
191                 return saveSubs( f, f );
192         }
193         // need to save the Sub objects independently
194         private boolean saveSubs( Feed fnew, Feed req ) {       
195                 ArrayList<DR_Sub> subs = req.getSubs();
196                 if ( subs.size() == 0 ) {
197                         logger.info( "No subs specified");
198                 } else {
199                         DR_SubService subSvc = new DR_SubService( fnew.getSubscribeURL() );
200                         ApiError err = new ApiError();
201                         for( int i = 0; i <  subs.size(); i++ ) {
202                                 DR_Sub sub = subs.get(i);
203                                 if ( subSvc.getDr_Sub( sub.getSubId(), err) == null ) {
204                                         subs.set( i,  subSvc.addDr_Sub(sub, err));
205                                         if ( ! err.is2xx())  {
206                                                 logger.error( "i=" + i + " url=" + sub.getDeliveryURL() + " err=" + err.getCode() );
207                                                 return false;
208                                         }
209                                 }
210                                 
211                         }
212                         fnew.setSubs(subs);
213                 }
214
215
216                 fnew.setStatus(DmaapObject_Status.VALID);
217                 return true;
218
219         }
220
221         public  Feed addFeed( Feed req, ApiError err ) {
222
223                 // at least 1 pub is required by DR, so create a default pub if none is specified
224                 if ( req.getPubs().size() == 0 ) {
225                         logger.info( "No pubs specified - creating tmp pub");
226                         ArrayList<DR_Pub> pubs = new ArrayList<DR_Pub>();
227                         pubs.add( new DR_Pub( dcaeLocations.getCentralLocation())
228                                                                 .setRandomUserName()
229                                                                 .setRandomPassword());
230                         req.setPubs(pubs);
231                 } 
232                 
233
234                 DrProvConnection prov = new DrProvConnection();
235                 prov.makeFeedConnection();      
236                 String resp = prov.doPostFeed( req, err );
237                 if ( unit_test.equals( "Yes" ) ) {
238                         // assume resp is null, so need to simulate it
239                         resp = simulateResp( req, "POST" );
240                 }
241                 logger.info( "resp=" + resp );
242                 if ( resp == null ) {
243                         switch( err.getCode() ) {
244                         case 400: 
245                                 err.setFields( "feedName=" + req.getFeedName() + " + feedVersion=" + req.getFeedVersion() );
246                                 break;
247                         case 403:
248                                 err.setCode(500);
249                                 err.setMessage("API deployment/configuration error - contact support");
250                                 err.setFields( "PROV_AUTH_ADDRESSES");
251                                 logger.error( "Prov response: 403. " + err.getMessage() + " regarding " + err.getFields() );
252                                 break;
253                         default:
254                                 err.setCode(500);
255                                 err.setMessage( "Unexpected response from DR backend" );
256                                 err.setFields("response");
257                         }
258                         return null;
259
260                 }
261
262
263                 Feed fnew = new Feed( resp );
264                 logger.info( "fnew status is:" + fnew.getStatus() );
265                 if ( ! fnew.isStatusValid()) {          
266                         err.setCode(500);
267                         err.setMessage( "Unexpected response from DR backend" );
268                         err.setFields("response");              
269                         return null;
270                 }
271                 
272                 //saveChildren( fnew, req );
273                 if ( ! savePubs( fnew, req ) || ! saveSubs( fnew, req ) ) {
274                         err.setCode(Status.BAD_REQUEST.getStatusCode());
275                         err.setMessage("Unable to save Pub or Sub objects");
276                         return null;
277                 }
278                 fnew.setFormatUuid(req.getFormatUuid());
279                 fnew.setLastMod();
280                 feeds.put( fnew.getFeedId(), fnew );
281                 return fnew;
282         }
283                 
284         public Feed updateFeed( Feed req, ApiError err ) {
285         
286                 // at least 1 pub is required by DR, so create a default pub if none is specified
287                 if ( req.getPubs().size() == 0 ) {
288                         logger.info( "No pubs specified - creating tmp pub");
289                         ArrayList<DR_Pub> pubs = new ArrayList<DR_Pub>();
290                         pubs.add( new DR_Pub( dcaeLocations.getCentralLocation())
291                                                                 .setRandomUserName()
292                                                                 .setRandomPassword());
293                         req.setPubs(pubs);
294                 } 
295                 
296                 DrProvConnection prov = new DrProvConnection();
297                 prov.makeFeedConnection( req.getFeedId() );
298                 String resp = prov.doPutFeed( req, err );
299                 if ( unit_test.equals( "Yes" ) ) {
300                         // assume resp is null, so need to simulate it
301                         resp = simulateResp( req, "PUT" );
302                 }
303                 logger.info( "resp=" + resp );
304                 if ( resp == null ) {
305                         switch( err.getCode() ) {
306                         case 400: 
307                                 err.setFields( "feedName=" + req.getFeedName() + " + feedVersion=" + req.getFeedVersion() );
308                                 break;
309                         case 403:
310                                 err.setCode(500);
311                                 err.setMessage("API deployment/configuration error - contact support");
312                                 err.setFields( "PROV_AUTH_ADDRESSES");
313                                 break;
314                         default:
315                                 err.setCode(500);
316                                 err.setMessage( "Unexpected response from DR backend" );
317                                 err.setFields("response");
318                         }
319                         return null;
320                 }
321
322
323                 Feed fnew = new Feed( resp );
324                 logger.info( "fnew status is:" + fnew.getStatus() );
325                 if ( ! fnew.isStatusValid()) {          
326                         err.setCode(500);
327                         err.setMessage( "Unexpected response from DR backend" );
328                         err.setFields("response");              
329                         return null;
330                 }
331
332                 if ( ! savePubs( fnew, req ) || ! saveSubs( fnew, req ) ) {
333                         err.setCode(Status.BAD_REQUEST.getStatusCode());
334                         err.setMessage("Unable to save Pub or Sub objects");
335                         return null;
336                 }
337                 fnew.setFormatUuid(req.getFormatUuid());
338                 fnew.setLastMod();
339                 feeds.put( fnew.getFeedId(), fnew );
340                 return fnew;
341         }
342         
343         
344         //
345         // DR does not actually delete a feed, so we provide two behaviors:
346         // 1) clean up the feed by removing all subs and pubs, mark it here as DELETED.
347         //    then client can add it back if desired.
348         // 2) Call the DR Delete function.  Feed with the same name and version can never be added again
349         //
350         public Feed removeFeed( Feed req, ApiError err ) {
351                 
352                 // strip pubs and subs from feed first no matter what
353                 ArrayList<DR_Pub> pubs = pubService.getDr_PubsByFeedId( req.getFeedId() );
354                 for( DR_Pub pub: pubs ) {
355                         pubService.removeDr_Pub(pub.getPubId(), err);
356                         if ( ! err.is2xx()) {
357                                 return req;
358                         }
359                 }
360                 ArrayList<DR_Sub> subs = subService.getDr_SubsByFeedId( req.getFeedId() );
361                 for ( DR_Sub sub: subs ) {
362                         subService.removeDr_Sub(sub.getSubId(), err);
363                         if ( ! err.is2xx()) {
364                                 return req;
365                         }
366                 }
367         
368                 if ( deleteHandling.equalsIgnoreCase("DeleteOnDR")) {
369                         DrProvConnection prov = new DrProvConnection();
370                         prov.makeFeedConnection( req.getFeedId() );
371                         String resp = prov.doDeleteFeed( req, err );
372                         if ( unit_test.equals( "Yes" ) ) {
373                                 // assume resp is null, so need to simulate it
374                                 resp = simulateDelResp( req );
375                         }
376                         logger.info( "resp=" + resp );
377                         if ( resp == null ) {
378                                 switch( err.getCode() ) {
379                                 case 400: 
380                                         err.setFields( "feedName=" + req.getFeedName() + " + feedVersion=" + req.getFeedVersion() );
381                                         break;
382                                 case 403:
383                                         err.setCode(500);
384                                         err.setMessage("API deployment/configuration error - contact support");
385                                         err.setFields( "PROV_AUTH_ADDRESSES");
386                                         break;
387                                 default:
388                                         err.setCode(500);
389                                         err.setMessage( "Unexpected response from DR backend" );
390                                         err.setFields("response");
391                                 }
392                                 return req;  // return back the requested feed - implies it wasn't removed
393                         }
394                         return feeds.remove(req.getFeedId());
395                 } else {
396                         req.setStatus(DmaapObject_Status.DELETED);
397                         req.setPubs(null);
398                         req.setSubs(null);
399                         req.setLastMod();
400                         feeds.put( req.getFeedId(), req );
401                         return null;
402                 }
403
404                 
405         }       
406
407         private String simulateResp( Feed f, String action ){
408                 String server = "localhost";
409                 String feedid;
410                 if ( action.equals( "POST" ) ) { 
411                         RandomInteger ran = new RandomInteger(10000);
412                         feedid = Integer.toString( ran.next() );
413                 } else if ( action.equals( "PUT" ) ) {
414                         feedid = f.getFeedId();
415                 } else {
416                         feedid = "99";
417                 }
418                 String ret = String.format( 
419 "{\"suspend\":false,\"groupid\":0,\"description\":\"%s\",\"version\":\"1.0\",\"authorization\":{\"endpoint_addrs\":[],\"classification\":\"unclassified\",\"endpoint_ids\":[{\"password\":\"topSecret123\",\"id\":\"sim\"}]},\"name\":\"%s\",\"business_description\":\"\",\"publisher\":\"sim\",\"links\":{\"subscribe\":\"https://%s/subscribe/%s\",\"log\":\"https://%s/feedlog/%s\",\"publish\":\"https://%s/publish/%s\",\"self\":\"https://%s/feed/%s\"}}",
420                 f.getFeedDescription(),
421                 f.getFeedName(),
422                 server, feedid,
423                 server, feedid,
424                 server, feedid,
425                 server, feedid
426
427                 );
428                 return ret;
429         }
430         private String simulateDelResp( Feed f ){
431                 String server = "localhost";
432                 String feedid = f.getFeedId();
433                 String ret = String.format( 
434 "{\"suspend\":true,\"groupid\":0,\"description\":\"%s\",\"version\":\"1.0\",\"authorization\":{\"endpoint_addrs\":[],\"classification\":\"unclassified\",\"endpoint_ids\":[{\"password\":\"topSecret123\",\"id\":\"sim\"}]},\"name\":\"%s\",\"business_description\":\"\",\"publisher\":\"sim\",\"links\":{\"subscribe\":\"https://%s/subscribe/%s\",\"log\":\"https://%s/feedlog/%s\",\"publish\":\"https://%s/publish/%s\",\"self\":\"https://%s/feed/%s\"}}",
435                 f.getFeedDescription(),
436                 f.getFeedName(),
437                 server, feedid,
438                 server, feedid,
439                 server, feedid,
440                 server, feedid
441
442                 );
443                 return ret;
444         }
445 }