View Javadoc
1   /**
2    *
3    */
4   package fr.paris.lutece.plugins.dila.service.impl;
5   
6   import fr.paris.lutece.plugins.dila.business.enums.AudienceCategoryEnum;
7   import fr.paris.lutece.plugins.dila.business.enums.ContentTypeEnum;
8   import fr.paris.lutece.plugins.dila.business.enums.ResourceTypeEnum;
9   import fr.paris.lutece.plugins.dila.business.fichelocale.dto.XmlDTO;
10  import fr.paris.lutece.plugins.dila.business.stylesheet.dto.DilaStyleSheet;
11  import fr.paris.lutece.plugins.dila.service.IDilaCacheService;
12  import fr.paris.lutece.plugins.dila.service.IDilaComplementaryDataService;
13  import fr.paris.lutece.plugins.dila.service.IDilaLocalCardService;
14  import fr.paris.lutece.plugins.dila.service.IDilaLocalFolderService;
15  import fr.paris.lutece.plugins.dila.service.IDilaLocalService;
16  import fr.paris.lutece.plugins.dila.service.IDilaPivotLocalService;
17  import fr.paris.lutece.plugins.dila.service.IDilaStyleSheetService;
18  import fr.paris.lutece.plugins.dila.service.IDilaXmlService;
19  import fr.paris.lutece.plugins.dila.utils.CacheKeyUtils;
20  import fr.paris.lutece.plugins.dila.utils.constants.DilaConstants;
21  import fr.paris.lutece.portal.service.cache.AbstractCacheableService;
22  import fr.paris.lutece.portal.service.html.XmlTransformerService;
23  import fr.paris.lutece.portal.service.util.AppLogService;
24  import fr.paris.lutece.portal.service.util.AppPathService;
25  import fr.paris.lutece.portal.service.util.AppPropertiesService;
26  
27  import java.io.ByteArrayInputStream;
28  import java.io.File;
29  import java.io.IOException;
30  import java.io.InputStream;
31  import java.io.Serializable;
32  import java.io.StringWriter;
33  import java.util.HashMap;
34  import java.util.List;
35  import java.util.Locale;
36  import java.util.Map;
37  
38  import javax.inject.Inject;
39  import javax.inject.Named;
40  import javax.xml.parsers.DocumentBuilder;
41  import javax.xml.parsers.DocumentBuilderFactory;
42  import javax.xml.parsers.ParserConfigurationException;
43  import javax.xml.transform.Transformer;
44  import javax.xml.transform.TransformerConfigurationException;
45  import javax.xml.transform.TransformerException;
46  import javax.xml.transform.TransformerFactory;
47  import javax.xml.transform.dom.DOMSource;
48  import javax.xml.transform.stream.StreamResult;
49  import javax.xml.transform.stream.StreamSource;
50  
51  import org.apache.commons.collections.CollectionUtils;
52  import org.apache.commons.lang.StringUtils;
53  import org.w3c.dom.Document;
54  import org.xml.sax.SAXException;
55  
56  
57  /**
58   * Class managing Dila cache
59   */
60  public class DilaCacheService extends AbstractCacheableService implements IDilaCacheService, Serializable
61  {
62      private static final String ERROR = "Error";
63      private static final String ASSOCIATIONS_THEMES_ID = "N20";
64  
65      /** Serial ID */
66      private static final long serialVersionUID = -8869528327826773129L;
67      private static final String SERVICE_NAME = "Dila Cache Service";
68      @Inject
69      @Named( "dilaPivotLocalService" )
70      private IDilaPivotLocalService _dilaPivotLocalService;
71      @Inject
72      @Named( "dilaXmlService" )
73      private IDilaXmlService _dilaXmlService;
74      @Inject
75      @Named( "dilaStyleSheetService" )
76      private IDilaStyleSheetService _dilaStyleSheetService;
77      @Inject
78      @Named( "dilaLocalCardService" )
79      private IDilaLocalCardService _dilaLocalCardService;
80      @Inject
81      @Named( "dilaLocalFolderService" )
82      private IDilaLocalFolderService _dilaLocalFolderService;
83      @Inject
84      @Named( "dilaLocalService" )
85      private IDilaLocalService _dilaLocalService;
86      @Inject
87      @Named( "dilaComplementaryDataService" )
88      private IDilaComplementaryDataService _dilaComplementaryDataService;
89  
90      /**
91       * Default constructor
92       */
93      public DilaCacheService( )
94      {
95          initCache( );
96      }
97  
98      @Override
99      public String getName( )
100     {
101         return SERVICE_NAME;
102     }
103 
104     /**
105      * {@inheritDoc}
106      */
107     public String getRessource( String strCacheKey, Locale locale )
108     {
109         String dilaPage = (String) getFromCache( strCacheKey );
110 
111         if ( dilaPage == null )
112         {
113             dilaPage = buildDilaPage( strCacheKey, locale );
114             putInCache( strCacheKey, dilaPage );
115         }
116 
117         return dilaPage;
118     }
119 
120     /**
121      * Build HTML code for given key
122      * @param strCacheKey the dila cache key
123      * @param locale the locale
124      * @return the HTML code to display
125      */
126     private String buildDilaPage( String strCacheKey, Locale locale )
127     {
128         Long categoryId = CacheKeyUtils.getCategoryFromCacheKey( strCacheKey );
129         AudienceCategoryEnum audienceEnum = AudienceCategoryEnum.fromId( categoryId );
130         String cardId = CacheKeyUtils.getCardIdFromCacheKey( strCacheKey );
131         String xmlDirectory = null;
132 
133         switch ( audienceEnum )
134         {
135         case ASSOCIATIONS:
136             xmlDirectory = AppPropertiesService.getProperty( DilaConstants.PROPERTY_XML_DIRECTORY_ASSO );
137 
138             break;
139 
140         case INDIVIDUALS:
141             xmlDirectory = AppPropertiesService.getProperty( DilaConstants.PROPERTY_XML_DIRECTORY_INDIVIDUALS );
142 
143             break;
144 
145         case PROFESSIONNALS:
146             xmlDirectory = AppPropertiesService.getProperty( DilaConstants.PROPERTY_XML_DIRECTORY_PROFESSIONALS );
147 
148             break;
149 
150         default:
151             xmlDirectory = AppPropertiesService.getProperty( DilaConstants.PROPERTY_XML_DIRECTORY );
152 
153             break;
154         }
155 
156         String resourceType = null;
157         String xslName = null;
158         File xmlFile = null;
159         InputStream xmlStream = null;
160         String htmlCode = null;
161         Long contentType = null;
162 
163         // if fiche id is numeric, it is a local card
164         if ( StringUtils.isNumeric( cardId ) )
165         {
166             String xml = _dilaLocalService.findXmlById( Long.valueOf( cardId ) );
167             xmlStream = new ByteArrayInputStream( xml.getBytes( ) );
168             contentType = ContentTypeEnum.LOCAL.getId( );
169         }
170         else
171         {
172             String individualDefault = AppPropertiesService.getProperty( DilaConstants.INDIVIDUAL_PREFIX
173                     + DilaConstants.PROPERTY_HOME_CARD );
174             String associationDefault = AppPropertiesService.getProperty( DilaConstants.ASSOCIATION_PREFIX
175                     + DilaConstants.PROPERTY_HOME_CARD );
176             String professionalDefault = AppPropertiesService.getProperty( DilaConstants.PROFESSIONAL_PREFIX
177                     + DilaConstants.PROPERTY_HOME_CARD );
178             if ( individualDefault.equals( cardId ) || associationDefault.equals( cardId )
179                     || professionalDefault.equals( cardId ) )
180             {
181                 if ( audienceEnum.equals( AudienceCategoryEnum.PROFESSIONNALS ) )
182                 {
183                     contentType = ContentTypeEnum.PROFESSIONAL_THEMES.getId( );
184                 }
185                 else
186                 {
187                     contentType = ContentTypeEnum.THEMES.getId( );
188                 }
189             }
190             else
191             {
192                 resourceType = _dilaXmlService.findResourceTypeByIdXMLAndAudience( cardId, categoryId );
193 
194                 if ( resourceType == null )
195                 {
196                     return htmlCode;
197                 }
198 
199                 ResourceTypeEnum resourceTypeEnum = ResourceTypeEnum.fromLabel( resourceType );
200                 contentType = resourceTypeEnum.getContentType( );
201             }
202 
203             xmlFile = new File( xmlDirectory + cardId + DilaConstants.XML_EXTENSION );
204         }
205 
206         List<DilaStyleSheet> dilaStyleSheets = _dilaStyleSheetService.getDilaStyleSheetList( contentType.intValue( ),
207                 null );
208 
209         if ( CollectionUtils.isNotEmpty( dilaStyleSheets ) )
210         {
211             xslName = dilaStyleSheets.get( 0 ).getFile( );
212         }
213 
214         File styleSheet = new File( AppPathService.getPath( DilaConstants.PROPERTY_PATH_XSL ) + xslName );
215         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance( );
216 
217         try
218         {
219             DocumentBuilder builder = factory.newDocumentBuilder( );
220             Document document = null;
221 
222             if ( xmlFile != null )
223             {
224                 document = builder.parse( xmlFile );
225             }
226             else
227             {
228                 document = builder.parse( xmlStream );
229             }
230 
231             document.getDocumentElement( ).normalize( );
232             document = _dilaPivotLocalService.insertPivots( builder, document );
233 
234             switch ( ContentTypeEnum.fromId( contentType ) )
235             {
236             case NODE:
237                 document = _dilaLocalCardService.insertCardLinks( cardId, builder, document );
238                 document = _dilaLocalFolderService.insertFolderLinks( cardId, builder, document );
239 
240                 if ( AudienceCategoryEnum.ASSOCIATIONS.equals( audienceEnum ) && ASSOCIATIONS_THEMES_ID.equals( cardId ) )
241                 {
242                     document = _dilaLocalService.insertLastCardsLinks( categoryId, builder, document );
243                 }
244 
245                 break;
246 
247             case THEMES:
248             case PROFESSIONAL_THEMES:
249                 document = _dilaXmlService.insertHowToLinks( categoryId, builder, document );
250                 document = _dilaLocalService.insertLastCardsLinks( categoryId, builder, document );
251 
252                 break;
253 
254             case CARD:
255 
256                 if ( !StringUtils.isNumeric( cardId ) )
257                 {
258                     Long cardTechnicalId = _dilaXmlService.findIdByXmlAndAudience( cardId, categoryId );
259                     document = _dilaComplementaryDataService.insertComplementaryData( cardTechnicalId, categoryId,
260                             builder, document );
261                 }
262 
263                 break;
264 
265             default:
266                 break;
267             }
268 
269             // Get RSS data for national cards
270             if ( !StringUtils.isNumeric( cardId ) )
271             {
272                 document = _dilaXmlService.insertRssLinks( builder, document, locale );
273             }
274 
275             // Use a Transformer for output
276             TransformerFactory tFactory = TransformerFactory.newInstance( );
277             Transformer transformer = tFactory.newTransformer( );
278             DOMSource source = new DOMSource( document );
279             StringWriter writer = new StringWriter( );
280             StreamResult result = new StreamResult( writer );
281             transformer.transform( source, result );
282             htmlCode = writer.toString( );
283 
284             Map<String, String> params = new HashMap<String, String>( );
285             params.put( DilaConstants.MARK_XMLURL_PARAM, xmlDirectory );
286             params.put( DilaConstants.MARK_CATEGORY_PARAM, audienceEnum.getLabel( ).toLowerCase( ) );
287 
288             StringBuilder referer = new StringBuilder( );
289             referer.append( DilaConstants.XPAGE_REFERER );
290             referer.append( audienceEnum.getLabel( ).toLowerCase( ) );
291             referer.append( DilaConstants.XPAGE_REFERER_XMLFILE );
292             params.put( DilaConstants.MARK_REFERER_PARAM, referer.toString( ) );
293             params.put( DilaConstants.MARK_CARDID_PARAM, cardId );
294 
295             // Set parameters for "how to ..." section link
296             XmlDTO homeHowTo = _dilaXmlService.findHomeHowTo( categoryId );
297 
298             if ( homeHowTo != null )
299             {
300                 params.put( DilaConstants.MARK_HOW_TO_ID_PARAM, homeHowTo.getIdXml( ) );
301                 params.put( DilaConstants.MARK_HOW_TO_TITLE_PARAM, homeHowTo.getTitle( ) );
302             }
303 
304             StreamSource xslSource = new StreamSource( styleSheet );
305             XmlTransformerService trans = new XmlTransformerService( );
306             htmlCode = trans.transformBySourceWithXslCache( htmlCode, xslSource, xslName, params, null );
307 
308             if ( htmlCode.startsWith( ERROR ) )
309             {
310                 return null;
311             }
312         }
313         catch ( ParserConfigurationException ex )
314         {
315             AppLogService.error( ex );
316         }
317         catch ( SAXException e )
318         {
319             AppLogService.error( e );
320         }
321         catch ( IOException e )
322         {
323             AppLogService.error( e );
324         }
325         catch ( TransformerConfigurationException e )
326         {
327             AppLogService.error( e );
328         }
329         catch ( TransformerException e )
330         {
331             AppLogService.error( e );
332         }
333 
334         return htmlCode;
335     }
336 }