View Javadoc
1   /*
2    * Copyright (c) 2002-2014, 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.directory.modules.rest.service.formatters;
35  
36  import fr.paris.lutece.plugins.directory.business.Directory;
37  import fr.paris.lutece.plugins.directory.business.Field;
38  import fr.paris.lutece.plugins.directory.business.IEntry;
39  import fr.paris.lutece.plugins.directory.business.Record;
40  import fr.paris.lutece.plugins.directory.business.RecordField;
41  import fr.paris.lutece.plugins.directory.modules.rest.service.IDirectoryRestService;
42  import fr.paris.lutece.plugins.directory.modules.rest.util.constants.DirectoryRestConstants;
43  import fr.paris.lutece.plugins.directory.utils.DirectoryUtils;
44  import fr.paris.lutece.plugins.rest.business.resourceinfo.IResourceInfo;
45  import fr.paris.lutece.plugins.rest.service.formatters.IFormatter;
46  import fr.paris.lutece.plugins.rest.service.resourceinfo.ResourceInfoManager;
47  import fr.paris.lutece.plugins.rest.util.json.JSONUtil;
48  import fr.paris.lutece.portal.service.i18n.I18nService;
49  import fr.paris.lutece.portal.service.util.AppLogService;
50  
51  import net.sf.json.JSONArray;
52  import net.sf.json.JSONObject;
53  
54  import org.apache.commons.lang.StringUtils;
55  
56  import java.util.HashMap;
57  import java.util.List;
58  import java.util.Locale;
59  import java.util.Map;
60  
61  import javax.inject.Inject;
62  
63  
64  /**
65   *
66   * Format record output to the JSON format
67   * Example of a formatted record JSON :
68   * <br />
69   * <code>
70   * [
71   *         {
72   *                 "Id":1,
73   *                 "state":
74   *                 {
75   *                         "id-state":1,
76   *                         "name":"state1",
77   *                         "description":"State 1",
78   *                         "id-workflow":"1",
79   *                         "is-initial-state":"true",
80   *                         "is-required-workgroup-assigned":"false"
81   *                 },
82   *                 "RecordFields":
83   *                 [
84   *                         {
85   *                                 "group1":
86   *                                 {
87   *                                         "recordFieldTitle1":"recordFieldValue1"
88   *                                 },
89   *                                 {
90   *                                         "recordFieldTitle2":
91   *                                         {
92   *                                                                                                "choiceTitle2":"choiceValue2",
93   *                                               "choiceTitle3":"choiceValue3"
94   *                                        }
95   *                                 }
96   *                         },
97   *                         {
98   *                                 "recordFieldTitle3":"recordFieldValue3"
99   *                         },
100  *                         {
101  *                                 "recordFieldTitle4":
102  *                                 {
103  *                                                                                "choiceTitle4":"choiceValue4",
104  *                                                                                "choiceTitle5":"choiceValue5"
105  *                                }
106  *                         }
107  *
108  *                 ]
109  *         }
110  *         {
111  *                 "Id:2,
112  *                 ...
113  *  }
114  * ]
115  * </code>
116  */
117 public class RecordFormatterJson implements IFormatter<Record>
118 {
119     @Inject
120     private IDirectoryRestService _directoryRestService;
121     private Locale _locale = I18nService.getDefaultLocale(  );
122 
123     /**
124      * {@inheritDoc }
125      */
126     @Override
127     public String formatError( String strCode, String strMessage )
128     {
129         return JSONUtil.formatError( strMessage, DirectoryUtils.convertStringToInt( strCode ) );
130     }
131 
132     /**
133      * {@inheritDoc }
134      */
135     @Override
136     public String format( Record record )
137     {
138         JSONObject jsonObject = new JSONObject(  );
139 
140         // Put the ID record
141         jsonObject.element( DirectoryRestConstants.TAG_ID, record.getIdRecord(  ) );
142 
143         // Put the resource info
144         formatResourceInfo( jsonObject, record );
145 
146         // Put the entry info
147 
148         /*
149         List<IEntry> listEntries = _directoryRestService.getEntries( record.getDirectory(  ).getIdDirectory(  ) );
150         Map<String, List<RecordField>> mapIdsEntryListRecordFields = DirectoryUtils.getMapIdEntryListRecordField( listEntries,
151                 record.getIdRecord(  ), pluginDirectory );
152         */
153         List<IEntry> listEntries = _directoryRestService.getEntries( record );
154         Map<String, List<RecordField>> mapIdsEntryListRecordFields = _directoryRestService.getMapIdEntryListRecordField( record );
155 
156         JSONArray jsonRecordField = new JSONArray(  );
157 
158         for ( IEntry entry : listEntries )
159         {
160             if ( entry.getEntryType(  ).getGroup(  ) )
161             {
162                 if ( ( entry.getChildren(  ) != null ) && !entry.getChildren(  ).isEmpty(  ) )
163                 {
164                     for ( IEntry entryChild : entry.getChildren(  ) )
165                     {
166                         JSONObject jsonEntry = new JSONObject(  );
167                         formatEntry( jsonEntry, entryChild, mapIdsEntryListRecordFields );
168 
169                         if ( !jsonEntry.isEmpty(  ) )
170                         {
171                             jsonRecordField.element( jsonEntry );
172                         }
173                     }
174                 }
175             }
176             else
177             {
178                 JSONObject jsonEntry = new JSONObject(  );
179                 formatEntry( jsonEntry, entry, mapIdsEntryListRecordFields );
180 
181                 if ( !jsonEntry.isEmpty(  ) )
182                 {
183                     jsonRecordField.element( jsonEntry );
184                 }
185             }
186         }
187 
188         jsonObject.element( DirectoryRestConstants.TAG_RECORD_FIELDS, jsonRecordField );
189 
190         return jsonObject.toString(  );
191     }
192 
193     /**
194      * {@inheritDoc}
195      */
196     @Override
197     public String format( List<Record> listRecords )
198     {
199         JSONArray jsonArray = new JSONArray(  );
200 
201         for ( Record record : listRecords )
202         {
203             jsonArray.element( format( record ) );
204         }
205 
206         return jsonArray.toString(  );
207     }
208 
209     /**
210      * Format the entry
211      * Example of a formatted entry type Image/File/CheckBox/Select/RadioButton/Geolocation JSON :
212      * <br />
213      * <code>
214      * {
215      *                 "recordFieldTitle":
216      *                 {
217      *                                                 "choiceTitle1":"choiceValue1",
218      *                      "choiceTitle2":"choiceValue2"
219      *                }
220      * }
221      * </code>
222      * <br />
223      * Example of a formatted JSON for other entry types :
224      * <br />
225      * <code>
226      * {
227      *                 "recordFieldTitle":"recordFieldValue"
228      * }
229      * </code>
230      * @param jsonObject the json object
231      * @param entry the entry
232      * @param mapIdsEntryListRecordFields the map ids entry - list record fields
233      */
234     private void formatEntry( JSONObject jsonObject, IEntry entry,
235         Map<String, List<RecordField>> mapIdsEntryListRecordFields )
236     {
237         if ( entry != null )
238         {
239             List<RecordField> listRecordFields = mapIdsEntryListRecordFields.get( Integer.toString( 
240                         entry.getIdEntry(  ) ) );
241 
242             if ( ( listRecordFields != null ) && !listRecordFields.isEmpty(  ) )
243             {
244                 String strTag = fr.paris.lutece.util.string.StringUtil.replaceAccent( entry.getTitle(  ) );
245 
246                 if ( entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeImg ||
247                         entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeFile ||
248                         entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeCheckBox ||
249                         entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeSelect ||
250                         entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeRadioButton ||
251                         entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeGeolocation )
252                 {
253                     JSONObject json = new JSONObject(  );
254 
255                     for ( RecordField recordField : listRecordFields )
256                     {
257                         formatRecordField( json, entry, recordField );
258                     }
259 
260                     jsonObject.accumulate( strTag, json );
261                 }
262                 else
263                 {
264                     for ( RecordField recordField : listRecordFields )
265                     {
266                         jsonObject.accumulate( strTag,
267                             entry.convertRecordFieldValueToString( recordField, _locale, false, false ) );
268                     }
269                 }
270             }
271         }
272     }
273 
274     /**
275      * Format the record field
276      * Example of the formatted record field JSON for entry type Image
277      * (display the ID of the file) :
278      * <br />
279      * <code>
280      * {
281      *                 "Id":1,
282      *                 "Width":100,
283      *                 "Height":100
284      * }
285      * </code>
286      * <br />
287      * Example of the formatted record field JSON for entry type File
288      * (display the ID of the file) :
289      * <br />
290      * <code>
291      * {
292      *                 "Id":2
293      * }
294      * </code>
295      * <br />
296      * Example of the formatted record field JSON for other entry types :
297      * <br />
298      * <code>
299      * {
300      *                 "choiceTitle1":"choiceValue1"
301      * }
302      * </code>
303      * @param jsonObject the json object
304      * @param entry the entry
305      * @param recordField the record field
306      */
307     private void formatRecordField( JSONObject jsonObject, IEntry entry, RecordField recordField )
308     {
309         if ( ( recordField != null ) && ( recordField.getField(  ) != null ) )
310         {
311             Field field = recordField.getField(  );
312 
313             if ( entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeImg &&
314                     StringUtils.isNotBlank( field.getValue(  ) ) )
315             {
316                 JSONObject jsonField = new JSONObject(  );
317 
318                 if ( recordField.getFile(  ) != null )
319                 {
320                     jsonField.element( DirectoryRestConstants.TAG_ID, recordField.getFile(  ).getIdFile(  ) );
321                 }
322 
323                 if ( ( field.getWidth(  ) != 0 ) && ( field.getHeight(  ) != 0 ) )
324                 {
325                     jsonField.element( DirectoryRestConstants.TAG_WIDTH, field.getWidth(  ) );
326                     jsonField.element( DirectoryRestConstants.TAG_HEIGHT, field.getHeight(  ) );
327                 }
328 
329                 jsonObject.accumulate( field.getValue(  ), jsonField );
330             }
331             else if ( entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeFile &&
332                     StringUtils.isNotBlank( field.getValue(  ) ) && ( recordField.getFile(  ) != null ) )
333             {
334                 JSONObject jsonField = new JSONObject(  );
335                 jsonField.element( DirectoryRestConstants.TAG_ID, recordField.getFile(  ).getIdFile(  ) );
336                 jsonObject.accumulate( field.getValue(  ), jsonField );
337             }
338             else if ( ( entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeCheckBox ||
339                     entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeSelect ||
340                     entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeRadioButton ) &&
341                     StringUtils.isNotBlank( field.getValue(  ) ) )
342             {
343                 jsonObject.element( field.getValue(  ),
344                     entry.convertRecordFieldTitleToString( recordField, _locale, false ) );
345             }
346             else if ( entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeGeolocation &&
347                     StringUtils.isNotBlank( field.getTitle(  ) ) )
348             {
349                 jsonObject.element( field.getTitle(  ),
350                     entry.convertRecordFieldTitleToString( recordField, _locale, false ) );
351             }
352             else
353             {
354                 if ( StringUtils.isNotBlank( field.getValue(  ) ) )
355                 {
356                     jsonObject.element( field.getValue(  ),
357                         entry.convertRecordFieldValueToString( recordField, _locale, false, false ) );
358                 }
359             }
360         }
361         else
362         {
363             if ( AppLogService.isDebugEnabled(  ) )
364             {
365                 AppLogService.debug( "Record field is null for entry " + entry.getTitle(  ) + " (" +
366                     entry.getIdEntry(  ) + ")" );
367             }
368         }
369     }
370 
371     /**
372      * Format the resource info
373      * Example of the JSON :
374      * <br />
375      * <code>
376      * [
377      *         {
378      *                 "state":
379      *                 {
380      *                         "id-state":1,
381      *                         "name":"state1",
382      *                         "description":"State 1",
383      *                         "id-workflow":"1",
384      *                         "is-initial-state":"true",
385      *                         "is-required-workgroup-assigned":"false"
386      *                 }
387      *         },
388      *         {
389      *                 "resourceInfo2":
390      *                 {
391      *                         "id-resource-info-2":2,
392      *                         "data":"somedata"
393      *                 }
394      *         }
395      * ]
396      * </code>
397      * @param jsonObject the json
398      * @param record the record
399      */
400     private void formatResourceInfo( JSONObject jsonObject, Record record )
401     {
402         Directory directory = _directoryRestService.getDirectory( record.getDirectory(  ).getIdDirectory(  ) );
403         Map<String, String> mapParams = new HashMap<String, String>(  );
404         mapParams.put( DirectoryRestConstants.PARAMETER_ID_RESOURCE, Integer.toString( record.getIdRecord(  ) ) );
405         mapParams.put( DirectoryRestConstants.PARAMETER_RESOURCE_TYPE, Record.WORKFLOW_RESOURCE_TYPE );
406         mapParams.put( DirectoryRestConstants.PARAMETER_ID_WORKFLOW, Integer.toString( directory.getIdWorkflow(  ) ) );
407 
408         List<IResourceInfo> listResourceInfos = ResourceInfoManager.getResourceInfo( mapParams );
409 
410         if ( ( listResourceInfos != null ) && !listResourceInfos.isEmpty(  ) )
411         {
412             for ( IResourceInfo resourceInfo : listResourceInfos )
413             {
414                 formatResourceInfo( jsonObject, resourceInfo );
415             }
416         }
417     }
418 
419     /**
420      * Format the resource info
421      * Example of the JSON :
422      * <br />
423      * <code>
424      * {
425      *         "state":
426      *         {
427      *                 "id-state":1,
428      *                 "name":"state1",
429      *                 "description":"State 1",
430      *                 "id-workflow":"1",
431      *                 "is-initial-state":"true",
432      *                 "is-required-workgroup-assigned":"false"
433      *         }
434      * }
435      * </code>
436      * @param jsonObject the json
437      * @param resourceInfo the resource info
438      */
439     private void formatResourceInfo( JSONObject jsonObject, IResourceInfo resourceInfo )
440     {
441         if ( resourceInfo != null )
442         {
443             if ( resourceInfo.hasChildren(  ) )
444             {
445                 JSONObject jsonResourceInfo = new JSONObject(  );
446 
447                 for ( IResourceInfo child : resourceInfo.getListChildren(  ) )
448                 {
449                     formatResourceInfo( jsonResourceInfo, child );
450                 }
451 
452                 jsonObject.element( resourceInfo.getKey(  ), jsonResourceInfo );
453             }
454             else
455             {
456                 jsonObject.element( resourceInfo.getKey(  ), resourceInfo.getValue(  ) );
457             }
458         }
459     }
460 }