View Javadoc
1   /*
2    * Copyright (c) 2002-2019, Mairie de 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  package fr.paris.lutece.plugins.appcenter.service;
35  
36  import java.io.IOException;
37  import java.lang.reflect.InvocationTargetException;
38  import java.lang.reflect.Method;
39  import java.util.Locale;
40  import java.util.Map;
41  import java.util.function.Function;
42  import java.util.logging.Level;
43  import java.util.logging.Logger;
44  import java.util.stream.Collectors;
45  
46  import org.apache.commons.collections.CollectionUtils;
47  
48  import com.fasterxml.jackson.databind.JsonNode;
49  import com.fasterxml.jackson.databind.ObjectMapper;
50  import com.fasterxml.jackson.databind.node.ObjectNode;
51  
52  import fr.paris.lutece.plugins.appcenter.business.Application;
53  import fr.paris.lutece.plugins.appcenter.business.ApplicationData;
54  import fr.paris.lutece.plugins.appcenter.business.ApplicationDatas;
55  import fr.paris.lutece.plugins.appcenter.business.ApplicationHome;
56  import fr.paris.lutece.plugins.appcenter.business.Demand;
57  import fr.paris.lutece.plugins.appcenter.business.DemandHome;
58  import fr.paris.lutece.plugins.appcenter.util.AppCenterUtils;
59  import fr.paris.lutece.portal.service.workflow.WorkflowService;
60  import fr.paris.lutece.util.ReferenceList;
61  import java.util.ArrayList;
62  import java.util.List;
63  
64  /**
65   * Application Service
66   */
67  public class ApplicationService
68  {
69      private static ObjectMapper _mapper = new ObjectMapper( );
70  
71      /**
72       * Save a data subset into the global JSON data of an application
73       * 
74       * @param application
75       *            The application
76       * @param dataSubset
77       *            The data subset
78       */
79      public static void saveApplicationData( Application application, DataSubset dataSubset )
80      {
81          try
82          {
83              String strUpdatedJson = getApplicationData( application, dataSubset );
84              ApplicationHome.updateData( application.getId( ), strUpdatedJson );
85          }
86          catch( IOException ex )
87          {
88              Logger.getLogger( ApplicationService.class.getName( ) ).log( Level.SEVERE, null, ex );
89          }
90      }
91  
92      /**
93       * Load a datasubset from the global JSON
94       * 
95       * @param <T>
96       *            The datasubset type
97       * @param application
98       *            The application
99       * @param strDataSubsetName
100      *            The subset name
101      * @param valueType
102      *            The class of the data subset
103      * @return The data subset as an object
104      */
105     public static <R extends ApplicationData, T extends ApplicationDatas<R>> T loadApplicationDataSubset( Application application,
106             Class<T> applicationDatasClass )
107     {
108         try
109         {
110             Method mGetDataSetName = applicationDatasClass.getMethod( "getName" );
111             String strDataSetName = (String) mGetDataSetName.invoke( applicationDatasClass.newInstance( ), null );
112             String strApplicationJson = application.getApplicationData( );
113             return getDataSubset( strApplicationJson, strDataSetName, applicationDatasClass );
114         }
115         catch( IOException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
116                 | InstantiationException ex )
117         {
118             Logger.getLogger( ApplicationService.class.getName( ) ).log( Level.SEVERE, null, ex );
119         }
120         return null;
121     }
122 
123     /**
124      * Load a datasubset from the global JSON
125      * 
126      * @param <T>
127      *            The datasubset type
128      * @param application
129      *            The application
130      * @param strDataSubsetName
131      *            The subset name
132      * @param valueType
133      *            The class of the data subset
134      * @return The data subset as an object
135      */
136     public static <T> T loadApplicationDataSubset( Application application, String strDataSubsetName, Class<T> valueType )
137     {
138         try
139         {
140             String strApplicationJson = application.getApplicationData( );
141             return getDataSubset( strApplicationJson, strDataSubsetName, valueType );
142         }
143         catch( IOException ex )
144         {
145             Logger.getLogger( ApplicationService.class.getName( ) ).log( Level.SEVERE, null, ex );
146         }
147         return null;
148     }
149 
150     /**
151      * Build a global JSON data of an application by adding or replacing a data subset
152      * 
153      * @param application
154      *            The application
155      * @param dataSubset
156      *            The data subset
157      * @return The JSON
158      * @throws IOException
159      *             if an error occurs
160      */
161     static String getApplicationData( Application application, DataSubset dataSubset ) throws IOException
162     {
163         String strApplicationJson = application.getApplicationData( );
164         JsonNode nodeApplication = _mapper.readTree( strApplicationJson );
165         JsonNode nodeData = nodeApplication.get( dataSubset.getName( ) );
166         if ( nodeData != null )
167         {
168             ( (ObjectNode) nodeApplication ).replace( dataSubset.getName( ), _mapper.valueToTree( dataSubset ) );
169         }
170         else
171         {
172             ( (ObjectNode) nodeApplication ).set( dataSubset.getName( ), _mapper.valueToTree( dataSubset ) );
173         }
174         return nodeApplication.toString( );
175     }
176 
177     /**
178      * Get the pretty print JSON data of an application
179      * 
180      * @param application
181      *            The application
182      * @return The pretty printed JSON
183      * @throws IOException
184      *             if an error occurs
185      */
186     public static String getPrettyPrintApplicationData( Application application )
187     {
188         String strApplicationJson = application.getApplicationData( );
189         try
190         {
191             Object dataApplication = _mapper.readTree( strApplicationJson );
192             if ( dataApplication != null )
193             {
194                 strApplicationJson = _mapper.writerWithDefaultPrettyPrinter( ).writeValueAsString( dataApplication );
195             }
196         }
197         catch( IOException ex )
198         {
199             Logger.getLogger( ApplicationService.class.getName( ) ).log( Level.WARNING, null, ex );
200         }
201 
202         return strApplicationJson;
203     }
204 
205     /**
206      * Load a datasubset from the global JSON
207      * 
208      * @param <T>
209      *            The datasubset type
210      * @param strApplicationJson
211      *            The global JSON of the application
212      * @param strDataSubsetName
213      *            The subset name
214      * @param valueType
215      *            The class of the data subset
216      * @return The data subset as an object
217      */
218     static <T> T getDataSubset( String strApplicationJson, String strDataSubsetName, Class<T> valueType ) throws IOException
219     {
220         JsonNode nodeApplication = _mapper.readTree( strApplicationJson );
221         JsonNode nodeData = nodeApplication.get( strDataSubsetName );
222         if ( nodeData != null )
223         {
224             return _mapper.treeToValue( nodeData, valueType );
225         }
226         return null;
227 
228     }
229 
230     /**
231      * Get application data by id application data
232      * 
233      * @param application
234      *            The application
235      * @param dataSubset
236      *            The data subset
237      * @return The JSON
238      * @throws IOException
239      *             if an error occurs
240      */
241     public static <AD extends ApplicationData, ADS extends ApplicationDatas<AD>> ApplicationData loadApplicationDataById( Integer nIdApplicationData,
242             Application application, Class<ADS> valueType ) throws IOException
243     {
244 
245         ADS ads = loadApplicationDataSubset( application, valueType );
246         if ( ads != null && ads.getListData( ) != null )
247         {
248             return ads.getListData( ).stream( ).filter( x -> x.getIdApplicationData( ) == nIdApplicationData ).findFirst( ).orElse( null );
249 
250         }
251         return null;
252     }
253 
254     public static <AD extends ApplicationData, ADS extends ApplicationDatas<AD>> ReferenceList getRefLisApplicationDatas( Application application,
255             Class<ADS> classAds, Locale locale, boolean bWithEmptyFile, Function<AD, String> functionRefItemCode, Function<AD, String> functionRefItemName )
256     {
257 
258         ADS ads = ApplicationService.loadApplicationDataSubset( application, classAds );
259         ReferenceList referenceList = null;
260         if ( ads != null && ads.getListData( ) != null && !CollectionUtils.isEmpty( ads.getListData( ) ) )
261         {
262             Map<String, String> mapReferenceItem = ads.getListData( ).stream( )
263                     .collect( Collectors.toMap( functionRefItemCode, functionRefItemName, ( f, s ) -> f ) );
264             referenceList = ReferenceList.convert( mapReferenceItem );
265         }
266         else
267         {
268             referenceList = new ReferenceList( );
269         }
270 
271         if ( bWithEmptyFile )
272         {
273             AppCenterUtils.addEmptyItem( referenceList, locale );
274         }
275 
276         return referenceList;
277 
278     }
279 
280     /**
281      * Remove the application whose identifier is specified in parameter with its dependencies
282      * 
283      * @param nId
284      *            The application Id
285      */
286     public static void remove( int nId )
287     {
288         List<Demand> demandList = DemandHome.getDemandsListByApplication( nId );
289 
290         for ( Demand demand : demandList )
291         {
292             List<Integer> idResourceList = new ArrayList<Integer>( );
293             idResourceList.add( demand.getId( ) );
294             int nIdWorkflow = DemandTypeService.getIdWorkflow( demand.getDemandType( ) );
295             WorkflowService.getInstance( ).doRemoveWorkFlowResourceByListId( idResourceList, Demand.WORKFLOW_RESOURCE_TYPE, nIdWorkflow );
296             DemandHome.remove( demand.getId( ) );
297         }
298 
299         ApplicationHome.remove( nId );
300     }
301 }