1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.plugins.appointment.modules.solr.service;
35
36 import java.io.IOException;
37 import java.util.ArrayList;
38 import java.util.HashSet;
39 import java.util.List;
40 import java.util.Queue;
41 import java.util.Set;
42 import java.util.concurrent.ConcurrentHashMap;
43 import java.util.concurrent.ConcurrentMap;
44 import org.apache.commons.lang3.StringUtils;
45 import org.apache.solr.client.solrj.SolrServerException;
46 import org.apache.solr.client.solrj.response.UpdateResponse;
47 import org.apache.solr.client.solrj.util.ClientUtils;
48 import fr.paris.lutece.plugins.appointment.business.slot.Slot;
49 import fr.paris.lutece.plugins.appointment.service.FormService;
50 import fr.paris.lutece.plugins.appointment.web.dto.AppointmentFormDTO;
51 import fr.paris.lutece.plugins.search.solr.business.SolrServerService;
52 import fr.paris.lutece.plugins.search.solr.business.field.Field;
53 import fr.paris.lutece.plugins.search.solr.indexer.SolrIndexer;
54 import fr.paris.lutece.plugins.search.solr.indexer.SolrIndexerService;
55 import fr.paris.lutece.plugins.search.solr.indexer.SolrItem;
56 import fr.paris.lutece.portal.service.search.SearchItem;
57 import fr.paris.lutece.portal.service.util.AppLogService;
58 import fr.paris.lutece.portal.service.util.AppPropertiesService;
59
60
61
62
63
64
65
66 public class SolrAppointmentIndexer implements SolrIndexer
67 {
68
69 public static final String BEAN_NAME = "appointment-solr.solrAppointmentIndexer";
70
71 private static ConcurrentMap<String, Object> _lockIndexer = new ConcurrentHashMap<>( );
72
73 @Override
74 public List<String> indexDocuments( )
75 {
76 List<String> errors = new ArrayList<>( );
77 for ( AppointmentFormDTO appointmentForm : FormService.buildAllActiveAppointmentForm( ) )
78 {
79 try
80 {
81 writeFormAndListSlots( appointmentForm );
82 }
83 catch( IOException e )
84 {
85 AppLogService.error( "Error indexing AppointmentForm" + appointmentForm.getIdForm( ), e );
86 errors.add( e.toString( ) );
87 }
88 }
89 return errors;
90 }
91
92 @Override
93 public String getResourceUid( String strResourceId, String strResourceType )
94 {
95 StringBuilder stringBuilder = new StringBuilder( strResourceId );
96 if ( Utilities.RESOURCE_TYPE_SLOT.equals( strResourceType ) )
97 {
98 stringBuilder.append( '_' ).append( Utilities.SHORT_NAME_SLOT );
99 }
100 else
101 if ( Utilities.RESOURCE_TYPE_APPOINTMENT.equals( strResourceType ) )
102 {
103 stringBuilder.append( '_' ).append( Utilities.SHORT_NAME_APPOINTMENT );
104 }
105 else
106 {
107 AppLogService.error( "SolrAppointmentIndexer, unknown resourceType: " + strResourceType );
108 return null;
109 }
110 return stringBuilder.toString( );
111 }
112
113 @Override
114 public List<Field> getAdditionalFields( )
115 {
116 return new ArrayList<>( );
117 }
118
119 @Override
120 public String getDescription( )
121 {
122 return Utilities.APPOINTMENT_DESCRIPTION;
123 }
124
125 @Override
126 public List<SolrItem> getDocuments( String arg0 )
127 {
128 return new ArrayList<>( );
129 }
130
131 @Override
132 public String getName( )
133 {
134 return Utilities.APPOINTMENT_FORM_NAME;
135 }
136
137 @Override
138 public List<String> getResourcesName( )
139 {
140 return new ArrayList<>( );
141 }
142
143 @Override
144 public String getVersion( )
145 {
146 return Utilities.APPOINTMENT_VERSION;
147 }
148
149 @Override
150 public boolean isEnable( )
151 {
152 return Boolean.valueOf( AppPropertiesService.getProperty( Utilities.PROPERTY_INDEXER_ENABLE ) );
153 }
154
155
156
157
158
159
160
161
162 public void writeFormAndListSlots( AppointmentFormDTO appointmentForm ) throws IOException
163 {
164 writeFormAndListSlots( appointmentForm, SolrIndexerService.getSbLogs( ) );
165 }
166
167
168
169
170
171
172
173
174
175
176 public void writeFormAndListSlots( AppointmentFormDTO appointmentForm, StringBuilder sbLogs ) throws IOException
177 {
178 Object lock = getLock( Utilities.buildResourceUid( Integer.toString( appointmentForm.getIdForm( ) ), Utilities.RESOURCE_TYPE_APPOINTMENT ) );
179 synchronized( lock )
180 {
181 List<Slot> listAllSlots = SlotUtil.getAllSlots( appointmentForm );
182 SolrIndexerService.write( FormUtil.getFormItem( appointmentForm, listAllSlots ), sbLogs );
183 List<SolrItem> listItems = new ArrayList<>( );
184 for ( Slot appointmentSlot : listAllSlots )
185 {
186 listItems.add( SlotUtil.getSlotItem( appointmentForm, appointmentSlot, listAllSlots ) );
187 }
188 SolrIndexerService.write( listItems, sbLogs );
189 }
190 }
191
192
193
194
195
196
197
198
199 public void writeSlotAndForm( Slot slot ) throws IOException
200 {
201 writeSlotAndForm( slot, SolrIndexerService.getSbLogs( ) );
202 }
203
204
205
206
207
208
209
210
211 public void writeSlotAndForm( Slot slot, StringBuilder sbLogs ) throws IOException
212 {
213 writeSlotAndForm( slot, sbLogs, null );
214 }
215
216
217
218
219
220
221
222
223
224
225 public void writeSlotAndForm( Slot slot, StringBuilder sbLogs, Queue<Slot> listSlotToIndex ) throws IOException
226 {
227 Object lock = getLock( SlotUtil.getSlotUid( slot ) );
228 synchronized( lock )
229 {
230 Set<Slot> listSlotAdded = new HashSet<>( );
231 Set<SolrItem> listItems = new HashSet<>( );
232 AppointmentFormDTO appointmentForm = FormService.buildAppointmentFormWithoutReservationRule( slot.getIdForm( ) );
233 if ( appointmentForm.getIsActive( ) )
234 {
235
236 List<Slot> listAllSlots = SlotUtil.getAllSlots( appointmentForm );
237 if ( listAllSlots.stream( ).anyMatch( p -> p.getStartingDateTime( ).equals( slot.getStartingDateTime( ) ) ) )
238 {
239 listItems.add( SlotUtil.getSlotItem( appointmentForm, slot, listAllSlots ) );
240 }
241 if ( listSlotToIndex != null )
242 {
243
244 while ( !listSlotToIndex.isEmpty( ) )
245 {
246
247 Slot slt = listSlotToIndex.poll( );
248 if ( listAllSlots.stream( ).anyMatch( p -> p.getStartingDateTime( ).equals( slt.getStartingDateTime( ) ) ) )
249 {
250 SolrItem item = SlotUtil.getSlotItem( appointmentForm, slt, listAllSlots );
251 listItems.removeIf( p -> p.getUid( ).equals( item.getUid( ) ) );
252 listItems.add( item );
253 listAllSlots.removeIf( p -> p.getStartingDateTime( ).isEqual( slt.getStartingDateTime( ) ) );
254 listAllSlots.add( slt );
255 listSlotAdded.add( slt );
256 }
257 }
258 }
259
260 for ( Slot otherSlot : listAllSlots )
261 {
262 if ( ( otherSlot.getDate( ).equals( slot.getDate( ) ) && otherSlot.getStartingDateTime( ).isBefore( slot.getStartingDateTime( ) ) )
263 || listSlotAdded.stream( ).anyMatch( slt -> slt.getDate( ).equals( otherSlot.getDate( ) )
264 && otherSlot.getStartingDateTime( ).isBefore( slt.getStartingDateTime( ) ) ) )
265 {
266 SolrItem item = SlotUtil.getSlotItem( appointmentForm, otherSlot, listAllSlots );
267 listItems.removeIf( p -> p.getUid( ).equals( item.getUid( ) ) );
268 listItems.add( item );
269 }
270 }
271 if ( !listItems.isEmpty( ) )
272 {
273 SolrIndexerService.write( FormUtil.getFormItem( appointmentForm, listAllSlots ), sbLogs );
274 SolrIndexerService.write( listItems, sbLogs );
275 }
276 }
277 }
278 }
279
280
281
282
283
284
285
286
287
288
289
290 public void deleteFormAndListSlots( int nIdForm, StringBuilder sbLogs ) throws SolrServerException, IOException
291 {
292 Object lock = getLock( Utilities.buildResourceUid( Integer.toString( nIdForm ), Utilities.RESOURCE_TYPE_APPOINTMENT ) );
293 synchronized( lock )
294 {
295
296 StringBuffer sbAppointmentFormUidEscaped = new StringBuffer( ClientUtils.escapeQueryChars( SolrIndexerService.getWebAppName( ) ) );
297 sbAppointmentFormUidEscaped.append( Utilities.UNDERSCORE )
298 .append( getResourceUid( Integer.toString( nIdForm ), Utilities.RESOURCE_TYPE_APPOINTMENT ) );
299 StringBuffer sbQuery = new StringBuffer( SearchItem.FIELD_UID ).append( ":" ).append( sbAppointmentFormUidEscaped ).append( " OR uid_form_string:" )
300 .append( sbAppointmentFormUidEscaped );
301 sbLogs.append( "Delete by query: " ).append( sbQuery ).append( StringUtils.CR ).append( StringUtils.LF );
302 UpdateResponse update = SolrServerService.getInstance( ).getSolrServer( ).deleteByQuery( sbQuery.toString( ), 1000 );
303 sbLogs.append( "Server response: " ).append( update ).append( StringUtils.CR ).append( StringUtils.LF );
304 }
305 }
306
307
308
309
310
311
312
313
314
315
316
317 public void deleteSlot( Slot slot, StringBuilder sbLogs ) throws SolrServerException, IOException
318 {
319 Object lock = getLock( SlotUtil.getSlotUid( slot ) );
320 synchronized( lock )
321 {
322 StringBuffer sbSlotUidEscaped = new StringBuffer( ClientUtils.escapeQueryChars( SolrIndexerService.getWebAppName( ) ) )
323 .append( Utilities.UNDERSCORE ).append( getResourceUid( SlotUtil.getSlotUid( slot ), Utilities.RESOURCE_TYPE_SLOT ) );
324 StringBuffer sbQuery = new StringBuffer( SearchItem.FIELD_UID ).append( ":" ).append( sbSlotUidEscaped );
325 sbLogs.append( "Delete by query: " ).append( sbQuery ).append( StringUtils.CR ).append( StringUtils.LF );
326 UpdateResponse update = SolrServerService.getInstance( ).getSolrServer( ).deleteByQuery( sbQuery.toString( ), 1000 );
327 sbLogs.append( "Server response: " ).append( update ).append( StringUtils.CR ).append( StringUtils.LF );
328 }
329 }
330
331 private static synchronized Object getLock( String key )
332 {
333 _lockIndexer.putIfAbsent( key, new Object( ) );
334 return _lockIndexer.get( key );
335 }
336 }