d36adc4553627a5a8ac6d963cd10845dbfe410fa
[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( String name, String ver, String match ) {
67                 logger.info( "getAllFeeds: name=" + name + " ver=" + ver + " match=" + match);
68                 ArrayList<Feed> fatFeeds = new ArrayList<Feed>();
69                 for( Feed f:  feeds.values() ) {
70                         boolean keep = true;
71                         if ( name != null ) {
72                                 if ( match != null && match.equals("startsWith") ) {
73                                         if ( ! f.getFeedName().startsWith( name ) ) {
74                                                 logger.info( "getAllFeeds: feedName=" + f.getFeedName() + " doesn't start with=" + name);
75                                                 keep = false;
76                                         }
77                                 } else if ( match != null && match.equals("contains") ) {
78                                         if ( ! f.getFeedName().contains( name ) ) {
79                                                 logger.info( "getAllFeeds: feedName=" + f.getFeedName() + " doesn't contain=" + name);
80                                                 keep = false;
81                                         }
82                                 } else {
83                                         if ( ! f.getFeedName().equals( name ) ) {
84                                                 logger.info( "getAllFeeds: feedName=" + f.getFeedName() + " doesn't equal=" + name);
85                                                 keep = false;
86                                         }
87                                 }
88
89                         }
90                         if ( keep && ver != null ) {
91                                 if ( ! f.getFeedVersion().equals(ver)) {
92                                         logger.info( "getAllFeeds: feedVersion=" + f.getFeedName() + " doesn't match " + ver);
93                                         keep = false;
94                                 } else {
95                                         logger.info( "getAllFeeds: feedVersion=" + f.getFeedName() + " matches " + ver);
96                                 }
97                         }
98                                         
99                         if (keep){
100                                 getSubObjects(f);
101                                 fatFeeds.add(f);
102                         }
103                 }
104                 return fatFeeds;
105         }
106         
107         
108         private Feed _getFeed( String key, ApiError err, boolean flag ) {
109                 Feed f = feeds.get( key );
110                 if ( f != null && ( flag || f.getStatus() != DmaapObject_Status.DELETED ) ) {
111                         getSubObjects( f );
112                 } else {
113                         err.setCode(Status.NOT_FOUND.getStatusCode());
114                         err.setMessage("feed not found");
115                         err.setFields("feedId=" + key );
116                         return null;
117                 }
118                 err.setCode(200);
119                 return f;
120         }
121         public Feed getFeed( String key, ApiError err ) {
122                 return _getFeed( key, err, false );
123         }
124         public Feed getFeedPure( String key, ApiError err ) {
125                 return _getFeed( key, err, true );
126         }
127         
128         public Feed getFeedByName( String name, String ver, ApiError err ) {
129                 for( Feed f:  feeds.values() ) {
130                         if ( f.getFeedName().equals( name ) && f.getFeedVersion().equals(ver) ) {
131                                 getSubObjects(f);
132                                 return f;
133                         }
134         
135                 }
136                 err.setCode(Status.NOT_FOUND.getStatusCode());
137                 err.setMessage("feed not found");
138                 err.setFields("feedName=" + name + " and ver=" + ver );
139                 return null;
140         
141         }
142
143         private boolean savePubs( Feed f ) {
144                 return savePubs( f, f );
145         }
146         // need to save the Pub objects independently and copy pubId from original request
147         private boolean savePubs( Feed fnew, Feed req ) {
148                 // save any pubs
149                 DR_PubService pubSvc = new DR_PubService();
150                 ArrayList<DR_Pub> reqPubs = req.getPubs();
151                 ArrayList<DR_Pub> newPubs = fnew.getPubs();
152                 
153
154                 
155                 int nSize = newPubs.size();
156                 int rSize = reqPubs.size();
157                 logger.info( "reqPubs size=" + rSize + " newPubs size=" + nSize );
158                 if ( nSize != rSize ) {
159                         errorLogger.error( "Resulting set of publishers do not match requested set of publishers " + nSize + " vs " + rSize );
160                         fnew.setStatus( DmaapObject_Status.INVALID);
161                         return false;
162                 }
163                 // NOTE: when i > 1 newPubs are in reverse order from reqPubs
164                 for( int i = 0; i < reqPubs.size(); i++ ) {
165                         DR_Pub reqPub = reqPubs.get(i); 
166                         ApiError err = new ApiError();
167                         if ( pubSvc.getDr_Pub( reqPub.getPubId(), err ) == null ) {
168                                 DR_Pub newPub = newPubs.get(nSize - i - 1);
169                                 reqPub.setPubId(newPub.getPubId());
170                                 reqPub.setFeedId(newPub.getFeedId());
171                                 reqPub.setStatus(DmaapObject_Status.VALID);
172                                 if ( reqPub.getDcaeLocationName() == null ) {
173                                         reqPub.setDcaeLocationName("notSpecified");
174                                 }
175                                 pubSvc.addDr_Pub( reqPub );
176                         }
177                         
178                 }
179                 
180                 fnew.setPubs(reqPubs);
181                 fnew.setStatus(DmaapObject_Status.VALID);
182                 return true;
183
184         }
185         
186         private boolean saveSubs( Feed f ) {
187                 return saveSubs( f, f );
188         }
189         // need to save the Sub objects independently
190         private boolean saveSubs( Feed fnew, Feed req ) {       
191                 ArrayList<DR_Sub> subs = req.getSubs();
192                 if ( subs.size() == 0 ) {
193                         logger.info( "No subs specified");
194                 } else {
195                         DR_SubService subSvc = new DR_SubService( fnew.getSubscribeURL() );
196                         ApiError err = new ApiError();
197                         for( int i = 0; i <  subs.size(); i++ ) {
198                                 DR_Sub sub = subs.get(i);
199                                 if ( subSvc.getDr_Sub( sub.getSubId(), err) == null ) {
200                                         subs.set( i,  subSvc.addDr_Sub(sub, err));
201                                         if ( ! err.is2xx())  {
202                                                 logger.error( "i=" + i + " url=" + sub.getDeliveryURL() + " err=" + err.getCode() );
203                                                 return false;
204                                         }
205                                 }
206                                 
207                         }
208                         fnew.setSubs(subs);
209                 }
210
211
212                 fnew.setStatus(DmaapObject_Status.VALID);
213                 return true;
214
215         }
216
217         public  Feed addFeed( Feed req, ApiError err ) {
218
219                 // at least 1 pub is required by DR, so create a default pub if none is specified
220                 if ( req.getPubs().size() == 0 ) {
221                         logger.info( "No pubs specified - creating tmp pub");
222                         ArrayList<DR_Pub> pubs = new ArrayList<DR_Pub>();
223                         pubs.add( new DR_Pub( dcaeLocations.getCentralLocation())
224                                                                 .setRandomUserName()
225                                                                 .setRandomPassword());
226                         req.setPubs(pubs);
227                 } 
228                 
229
230                 DrProvConnection prov = new DrProvConnection();
231                 prov.makeFeedConnection();      
232                 String resp = prov.doPostFeed( req, err );
233                 logger.info( "resp=" + resp );
234                 if ( resp == null ) {
235                         switch( err.getCode() ) {
236                         case 400: 
237                                 err.setFields( "feedName=" + req.getFeedName() + " + feedVersion=" + req.getFeedVersion() );
238                                 break;
239                         case 403:
240                                 err.setCode(500);
241                                 err.setMessage("API deployment/configuration error - contact support");
242                                 err.setFields( "PROV_AUTH_ADDRESSES");
243                                 logger.error( "Prov response: 403. " + err.getMessage() + " regarding " + err.getFields() );
244                                 break;
245                         default:
246                                 err.setCode(500);
247                                 err.setMessage( "Unexpected response from DR backend" );
248                                 err.setFields("response");
249                         }
250                         return null;
251
252                 }
253
254
255                 Feed fnew = new Feed( resp );
256                 logger.info( "fnew status is:" + fnew.getStatus() );
257                 if ( ! fnew.isStatusValid()) {          
258                         err.setCode(500);
259                         err.setMessage( "Unexpected response from DR backend" );
260                         err.setFields("response");              
261                         return null;
262                 }
263                 
264                 //saveChildren( fnew, req );
265                 if ( ! savePubs( fnew, req ) || ! saveSubs( fnew, req ) ) {
266                         err.setCode(Status.BAD_REQUEST.getStatusCode());
267                         err.setMessage("Unable to save Pub or Sub objects");
268                         return null;
269                 }
270                 fnew.setFormatUuid(req.getFormatUuid());
271                 fnew.setLastMod();
272                 feeds.put( fnew.getFeedId(), fnew );
273                 return fnew;
274         }
275                 
276         public Feed updateFeed( Feed req, ApiError err ) {
277         
278                 // at least 1 pub is required by DR, so create a default pub if none is specified
279                 if ( req.getPubs().size() == 0 ) {
280                         logger.info( "No pubs specified - creating tmp pub");
281                         ArrayList<DR_Pub> pubs = new ArrayList<DR_Pub>();
282                         pubs.add( new DR_Pub( dcaeLocations.getCentralLocation())
283                                                                 .setRandomUserName()
284                                                                 .setRandomPassword());
285                         req.setPubs(pubs);
286                 } 
287                 
288                 DrProvConnection prov = new DrProvConnection();
289                 prov.makeFeedConnection( req.getFeedId() );
290                 String resp = prov.doPutFeed( req, err );
291                 logger.info( "resp=" + resp );
292                 if ( resp == null ) {
293                         switch( err.getCode() ) {
294                         case 400: 
295                                 err.setFields( "feedName=" + req.getFeedName() + " + feedVersion=" + req.getFeedVersion() );
296                                 break;
297                         case 403:
298                                 err.setCode(500);
299                                 err.setMessage("API deployment/configuration error - contact support");
300                                 err.setFields( "PROV_AUTH_ADDRESSES");
301                                 break;
302                         default:
303                                 err.setCode(500);
304                                 err.setMessage( "Unexpected response from DR backend" );
305                                 err.setFields("response");
306                         }
307                         return null;
308                 }
309
310
311                 Feed fnew = new Feed( resp );
312                 logger.info( "fnew status is:" + fnew.getStatus() );
313                 if ( ! fnew.isStatusValid()) {          
314                         err.setCode(500);
315                         err.setMessage( "Unexpected response from DR backend" );
316                         err.setFields("response");              
317                         return null;
318                 }
319
320                 if ( ! savePubs( fnew, req ) || ! saveSubs( fnew, req ) ) {
321                         err.setCode(Status.BAD_REQUEST.getStatusCode());
322                         err.setMessage("Unable to save Pub or Sub objects");
323                         return null;
324                 }
325                 fnew.setFormatUuid(req.getFormatUuid());
326                 fnew.setLastMod();
327                 feeds.put( fnew.getFeedId(), fnew );
328                 return fnew;
329         }
330         
331         
332         //
333         // DR does not actually delete a feed, so we provide two behaviors:
334         // 1) clean up the feed by removing all subs and pubs, mark it here as DELETED.
335         //    then client can add it back if desired.
336         // 2) Call the DR Delete function.  Feed with the same name and version can never be added again
337         //
338         public Feed removeFeed( Feed req, ApiError err ) {
339                 
340                 // strip pubs and subs from feed first no matter what
341                 ArrayList<DR_Pub> pubs = pubService.getDr_PubsByFeedId( req.getFeedId() );
342                 for( DR_Pub pub: pubs ) {
343                         pubService.removeDr_Pub(pub.getPubId(), err);
344                         if ( ! err.is2xx()) {
345                                 return req;
346                         }
347                 }
348                 ArrayList<DR_Sub> subs = subService.getDr_SubsByFeedId( req.getFeedId() );
349                 for ( DR_Sub sub: subs ) {
350                         subService.removeDr_Sub(sub.getSubId(), err);
351                         if ( ! err.is2xx()) {
352                                 return req;
353                         }
354                 }
355         
356                 if ( deleteHandling.equalsIgnoreCase("DeleteOnDR")) {
357                         DrProvConnection prov = new DrProvConnection();
358                         prov.makeFeedConnection( req.getFeedId() );
359                         String resp = prov.doDeleteFeed( req, err );
360                         logger.info( "resp=" + resp );
361                         if ( resp == null ) {
362                                 switch( err.getCode() ) {
363                                 case 400: 
364                                         err.setFields( "feedName=" + req.getFeedName() + " + feedVersion=" + req.getFeedVersion() );
365                                         break;
366                                 case 403:
367                                         err.setCode(500);
368                                         err.setMessage("API deployment/configuration error - contact support");
369                                         err.setFields( "PROV_AUTH_ADDRESSES");
370                                         break;
371                                 default:
372                                         err.setCode(500);
373                                         err.setMessage( "Unexpected response from DR backend" );
374                                         err.setFields("response");
375                                 }
376                                 return req;  // return back the requested feed - implies it wasn't removed
377                         }
378                         return feeds.remove(req.getFeedId());
379                 } else {
380                         req.setStatus(DmaapObject_Status.DELETED);
381                         req.setPubs(null);
382                         req.setSubs(null);
383                         req.setLastMod();
384                         feeds.put( req.getFeedId(), req );
385                         return null;
386                 }
387
388                 
389         }       
390
391 }