1 /*
2 * Copyright (c) 2002-2025, City of Paris
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice
10 * and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice
13 * and the following disclaimer in the documentation and/or other materials
14 * provided with the distribution.
15 *
16 * 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 *
32 * License 1.0
33 */
34 /*
35 * To change this license header, choose License Headers in Project Properties.
36 * To change this template file, choose Tools | Templates
37 * and open the template in the editor.
38 */
39 package fr.paris.lutece.portal.service.progressmanager;
40
41 import fr.paris.lutece.portal.business.progressmanager.ProgressFeed;
42 import java.util.ArrayList;
43 import java.util.Arrays;
44 import java.util.HashMap;
45 import java.util.List;
46 import java.util.Map;
47 import java.util.UUID;
48
49 /**
50 *
51 * @author sleridon
52 */
53 public final class ProgressManagerService
54 {
55
56 private static ProgressManagerService _singleton;
57 private static Map<String, ProgressFeed> _progressFeeds;
58
59 /**
60 * Private constructor
61 */
62 private ProgressManagerService( )
63 {
64 }
65
66 /**
67 * Returns the unique instance of the service
68 *
69 * @return The instance of the service
70 */
71 public static synchronized ProgressManagerService getInstance( )
72 {
73 if ( _singleton == null )
74 {
75 _singleton = new ProgressManagerService( );
76 _progressFeeds = new HashMap<>( );
77 }
78 return _singleton;
79 }
80
81 /**
82 * ge progress feeds
83 *
84 * @return the progress feeds
85 */
86 public Map<String, ProgressFeed> getProgressFeeds( )
87 {
88 Map<String, ProgressFeed> feedMap = new HashMap<>( );
89 feedMap.putAll( _progressFeeds );
90
91 return feedMap;
92 }
93
94 /**
95 * register new progress feed returns a generated token to identify the feed for rest webservice
96 *
97 * @param strProgressFeedName
98 * @param nTotalItems
99 * @return the generated token
100 */
101 public String registerFeed( String strProgressFeedName, int nTotalItems )
102 {
103 ProgressFeediness/progressmanager/ProgressFeed.html#ProgressFeed">ProgressFeed feed = new ProgressFeed( );
104 feed.setId( strProgressFeedName );
105 feed.setNbItemTotal( nTotalItems );
106
107 String strToken = UUID.randomUUID( ).toString( );
108 feed.setToken( strToken );
109
110 _progressFeeds.put( strToken, feed );
111
112 return feed.getToken( );
113 }
114
115 /**
116 * unregister progress feed
117 *
118 * @param strFeedToken
119 */
120 public void unRegisterFeed( String strFeedToken )
121 {
122 _progressFeeds.remove( strFeedToken );
123 }
124
125 /**
126 * register new progress feed
127 *
128 * @param strFeedToken
129 * @return
130 */
131 public boolean isRegistred( String strFeedToken )
132 {
133 return ( _progressFeeds.get( strFeedToken ) != null );
134 }
135
136 /**
137 * increment nb of success items
138 *
139 * @param strFeedToken
140 * @param nSuccessItems
141 */
142 public synchronized void incrementSuccess( String strFeedToken, int nSuccessItems )
143 {
144 if ( _progressFeeds.get( strFeedToken ) != null )
145 {
146 _progressFeeds.get( strFeedToken ).addSuccessItems( nSuccessItems );
147 }
148 }
149
150 /**
151 * increment nb of success items
152 *
153 * @param strFeedToken
154 * @param nFailureItems
155 */
156 public synchronized void incrementFailure( String strFeedToken, int nFailureItems )
157 {
158 if ( _progressFeeds.get( strFeedToken ) != null )
159 {
160 _progressFeeds.get( strFeedToken ).addFailureItems( nFailureItems );
161 }
162 }
163
164 /**
165 * add report line
166 *
167 * @param strFeedToken
168 * @param strReportLine
169 */
170 public void addReport( String strFeedToken, String strReportLine )
171 {
172 if ( _progressFeeds.get( strFeedToken ) != null )
173 {
174 _progressFeeds.get( strFeedToken ).addReport( strReportLine );
175 }
176 }
177
178 /**
179 * get the progress status in pourcent
180 *
181 * @param strFeedToken
182 * @return
183 */
184 public int getProgressStatus( String strFeedToken )
185 {
186 if ( _progressFeeds.get( strFeedToken ) != null )
187 {
188 ProgressFeed feed = _progressFeeds.get( strFeedToken );
189 if ( feed.getNbItemTotal( ) > 0 )
190 {
191 if ( feed.getNbItemTotal( ) <= feed.getNbItemSuccess( ) + feed.getNbItemFailure( ) )
192 {
193 return 100;
194 }
195 else
196 {
197 return (int) ( ( feed.getNbItemSuccess( ) + feed.getNbItemFailure( ) ) * 100.0 / feed.getNbItemTotal( ) + 0.5 );
198 }
199 }
200 }
201
202 return -1;
203 }
204
205 /**
206 * get the success nb
207 *
208 * @param strFeedToken
209 * @return the success nb
210 */
211 public int getSuccessNb( String strFeedToken )
212 {
213 if ( _progressFeeds.get( strFeedToken ) != null )
214 {
215 return _progressFeeds.get( strFeedToken ).getNbItemSuccess( );
216 }
217
218 return -1;
219 }
220
221 /**
222 * get the failure nb
223 *
224 * @param strFeedToken
225 * @return the failure nb
226 */
227 public int getFailureNb( String strFeedToken )
228 {
229 if ( _progressFeeds.get( strFeedToken ) != null )
230 {
231 return _progressFeeds.get( strFeedToken ).getNbItemFailure( );
232 }
233
234 return -1;
235 }
236
237 /**
238 * get the report list
239 *
240 * @param strFeedToken
241 * @return the failure nb
242 */
243 public List<String> getReport( String strFeedToken )
244 {
245 return getReport( strFeedToken, -1 );
246 }
247
248 /**
249 * get the report list
250 *
251 * @param strFeedToken
252 * @param iFromLine
253 * @return the failure nb
254 */
255 public List<String> getReport( String strFeedToken, int iFromLine )
256 {
257 if ( _progressFeeds.get( strFeedToken ) != null )
258 {
259 List<String> reportList = _progressFeeds.get( strFeedToken ).getReportList( );
260
261 if ( iFromLine > 0 && iFromLine < reportList.size( ) )
262 {
263 // clone to avoid ConcurrentModificationException
264 ArrayList<String> clonedReport = (ArrayList<String>) ( (ArrayList<String>) reportList ).clone( );
265 return clonedReport.subList( iFromLine - 1, clonedReport.size( ) - 1 );
266 }
267 else
268 if ( iFromLine >= reportList.size( ) )
269 {
270 return new ArrayList<String>( );
271 }
272 else
273 {
274 return reportList;
275 }
276 }
277
278 return null;
279 }
280
281 /**
282 * update feed total item number
283 *
284 * @param strFeedToken
285 * @param nTotalItems
286 * @return true if the feed exists
287 */
288 public boolean initFeed( String strFeedToken, int nTotalItems )
289 {
290 if ( _progressFeeds.get( strFeedToken ) != null )
291 {
292 _progressFeeds.get( strFeedToken ).setNbItemTotal( nTotalItems );
293 return true;
294 }
295 else
296 {
297 return false;
298 }
299 }
300 }