Project

General

Profile

1
/**
2
 *  Copyright: 2013 Regents of the University of California and the
3
 *             National Center for Ecological Analysis and Synthesis
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 */
19
package edu.ucsb.nceas.metacat.index;
20

    
21
import java.io.ByteArrayInputStream;
22
import java.io.FileInputStream;
23
import java.io.FileNotFoundException;
24
import java.io.IOException;
25
import java.io.InputStream;
26
import java.net.MalformedURLException;
27
import java.util.ArrayList;
28
import java.util.Calendar;
29
import java.util.Collection;
30
import java.util.Date;
31
import java.util.HashMap;
32
import java.util.Iterator;
33
import java.util.List;
34
import java.util.Map;
35
import java.util.Set;
36
import java.util.Vector;
37

    
38
import javax.xml.parsers.DocumentBuilder;
39
import javax.xml.parsers.DocumentBuilderFactory;
40
import javax.xml.parsers.ParserConfigurationException;
41
import javax.xml.xpath.XPath;
42
import javax.xml.xpath.XPathExpressionException;
43
import javax.xml.xpath.XPathFactory;
44

    
45
import org.apache.commons.codec.EncoderException;
46
import org.apache.commons.collections.CollectionUtils;
47
import org.apache.commons.io.output.ByteArrayOutputStream;
48
import org.apache.commons.lang.StringUtils;
49
import org.apache.commons.logging.Log;
50
import org.apache.commons.logging.LogFactory;
51
import org.apache.solr.client.solrj.SolrQuery;
52
import org.apache.solr.client.solrj.SolrServer;
53
import org.apache.solr.client.solrj.SolrServerException;
54
import org.apache.solr.client.solrj.response.QueryResponse;
55
import org.apache.solr.client.solrj.response.UpdateResponse;
56
import org.apache.solr.common.SolrDocument;
57
import org.apache.solr.common.SolrDocumentList;
58
import org.apache.solr.common.SolrInputDocument;
59
import org.apache.solr.schema.IndexSchema;
60
import org.dataone.cn.indexer.XMLNamespaceConfig;
61
import org.dataone.cn.indexer.convert.SolrDateConverter;
62
import org.dataone.cn.indexer.parser.BaseXPathDocumentSubprocessor;
63
import org.dataone.cn.indexer.parser.IDocumentDeleteSubprocessor;
64
import org.dataone.cn.indexer.parser.IDocumentSubprocessor;
65
import org.dataone.cn.indexer.parser.SolrField;
66
import org.dataone.cn.indexer.solrhttp.SolrDoc;
67
import org.dataone.cn.indexer.solrhttp.SolrElementField;
68
import org.dataone.exceptions.MarshallingException;
69
import org.dataone.service.exceptions.NotFound;
70
import org.dataone.service.exceptions.NotImplemented;
71
import org.dataone.service.exceptions.ServiceFailure;
72
import org.dataone.service.exceptions.UnsupportedType;
73
import org.dataone.service.types.v1.Event;
74
import org.dataone.service.types.v1.Identifier;
75
import org.dataone.service.types.v2.SystemMetadata;
76
import org.dataone.service.util.DateTimeMarshaller;
77
import org.dataone.service.util.TypeMarshaller;
78
import org.dspace.foresite.OREParserException;
79
import org.w3c.dom.Document;
80
import org.xml.sax.SAXException;
81

    
82
import edu.ucsb.nceas.metacat.common.index.event.IndexEvent;
83
import edu.ucsb.nceas.metacat.common.query.SolrQueryServiceController;
84
import edu.ucsb.nceas.metacat.index.event.EventlogFactory;
85
import edu.ucsb.nceas.metacat.index.resourcemap.ResourceMapSubprocessor;
86

    
87
/**
88
 * A class does insert, update and remove indexes to a SOLR server
89
 * @author tao
90
 *
91
 */
92
public class SolrIndex {
93
            
94
    public static final String ID = "id";
95
    private static final String IDQUERY = ID+":*";
96
    private List<IDocumentSubprocessor> subprocessors = null;
97
    private List<IDocumentDeleteSubprocessor> deleteSubprocessors = null;
98

    
99
    private SolrServer solrServer = null;
100
    private XMLNamespaceConfig xmlNamespaceConfig = null;
101
    private List<SolrField> sysmetaSolrFields = null;
102

    
103
    private static DocumentBuilderFactory documentBuilderFactory = null;
104
    private static DocumentBuilder builder = null;
105

    
106
    private static XPathFactory xpathFactory = null;
107
    private static XPath xpath = null;
108
    Log log = LogFactory.getLog(SolrIndex.class);
109
    
110
    static {
111
        documentBuilderFactory = DocumentBuilderFactory.newInstance();
112
        documentBuilderFactory.setNamespaceAware(true);
113
        try {
114
            builder = documentBuilderFactory.newDocumentBuilder();
115
        } catch (ParserConfigurationException e) {
116
            e.printStackTrace();
117
        }
118
        xpathFactory = XPathFactory.newInstance();
119
        xpath = xpathFactory.newXPath();
120
    }
121
    
122
    /**
123
     * Constructor
124
     * @throws SAXException 
125
     * @throws IOException 
126
     */
127
    public SolrIndex(XMLNamespaceConfig xmlNamespaceConfig, List<SolrField> sysmetaSolrFields)
128
                    throws XPathExpressionException, ParserConfigurationException, IOException, SAXException {
129
         this.xmlNamespaceConfig = xmlNamespaceConfig;
130
         this.sysmetaSolrFields = sysmetaSolrFields;
131
         init();
132
    }
133
    
134
    private void init() throws ParserConfigurationException, XPathExpressionException {
135
        xpath.setNamespaceContext(xmlNamespaceConfig);
136
        initExpressions();
137
    }
138

    
139
    private void initExpressions() throws XPathExpressionException {
140
        for (SolrField field : sysmetaSolrFields) {
141
            field.initExpression(xpath);
142
        }
143

    
144
    }
145
    
146
    
147
    /**
148
     * Get the list of the Subprocessors in this index.
149
     * @return the list of the Subprocessors.
150
     */
151
    public List<IDocumentSubprocessor> getSubprocessors() {
152
        return subprocessors;
153
    }
154

    
155
    /**
156
     * Set the list of Subprocessors.
157
     * @param subprocessorList  the list will be set.
158
     */
159
    public void setSubprocessors(List<IDocumentSubprocessor> subprocessorList) {
160
        for (IDocumentSubprocessor subprocessor : subprocessorList) {
161
        	if (subprocessor instanceof BaseXPathDocumentSubprocessor) {
162
        		((BaseXPathDocumentSubprocessor)subprocessor).initExpression(xpath);
163
        	}
164
        }
165
        this.subprocessors = subprocessorList;
166
    }
167
    
168
    public List<IDocumentDeleteSubprocessor> getDeleteSubprocessors() {
169
		return deleteSubprocessors;
170
	}
171

    
172
	public void setDeleteSubprocessors(
173
			List<IDocumentDeleteSubprocessor> deleteSubprocessors) {
174
		this.deleteSubprocessors = deleteSubprocessors;
175
	}
176

    
177
	/**
178
     * Generate the index for the given information
179
     * @param id
180
     * @param systemMetadata
181
     * @param dataStream
182
     * @return
183
     * @throws IOException
184
     * @throws SAXException
185
     * @throws ParserConfigurationException
186
     * @throws XPathExpressionException
187
     * @throws MarshallingException 
188
     * @throws SolrServerException 
189
     * @throws EncoderException
190
     * @throws UnsupportedType 
191
     * @throws NotFound 
192
     * @throws NotImplemented 
193
     */
194
    private Map<String, SolrDoc> process(String id, SystemMetadata systemMetadata, String objectPath)
195
                    throws IOException, SAXException, ParserConfigurationException,
196
                    XPathExpressionException, MarshallingException, EncoderException, SolrServerException, NotImplemented, NotFound, UnsupportedType{
197
        log.debug("SolrIndex.process - trying to generate the solr doc object for the pid "+id);
198
        // Load the System Metadata document
199
        ByteArrayOutputStream systemMetadataOutputStream = new ByteArrayOutputStream();
200
        TypeMarshaller.marshalTypeToOutputStream(systemMetadata, systemMetadataOutputStream);
201
        ByteArrayInputStream systemMetadataStream = new ByteArrayInputStream(systemMetadataOutputStream.toByteArray());
202
        Document sysMetaDoc = generateXmlDocument(systemMetadataStream);
203
        if (sysMetaDoc == null) {
204
            log.error("Could not load System metadata for ID: " + id);
205
            return null;
206
        }
207

    
208
        // Extract the field values from the System Metadata
209
        List<SolrElementField> sysSolrFields = processSysmetaFields(sysMetaDoc, id);
210
        SolrDoc indexDocument = new SolrDoc(sysSolrFields);
211
        Map<String, SolrDoc> docs = new HashMap<String, SolrDoc>();
212
        docs.put(id, indexDocument);
213
        
214
        // get the format id for this object
215
        String formatId = indexDocument.getFirstFieldValue(SolrElementField.FIELD_OBJECTFORMAT);
216
        log.debug("SolrIndex.process - the object format id for the pid "+id+" is "+formatId);
217
        // Determine if subprocessors are available for this ID
218
        if (subprocessors != null) {
219
	        // for each subprocessor loaded from the spring config
220
	        for (IDocumentSubprocessor subprocessor : subprocessors) {
221
	            // Does this subprocessor apply?
222
	            if (subprocessor.canProcess(formatId)) {
223
	                // if so, then extract the additional information from the
224
	                // document.
225
	                try {
226
	                    // docObject = the resource map document or science
227
	                    // metadata document.
228
	                    // note that resource map processing touches all objects
229
	                    // referenced by the resource map.
230
	                	FileInputStream dataStream = new FileInputStream(objectPath);
231
	                    if (!dataStream.getFD().valid()) {
232
	                    	log.error("SolrIndex.process - subprocessor "+ subprocessor.getClass().getName() +" couldn't process since it could not load OBJECT file for ID,Path=" + id + ", "
233
                                    + objectPath);
234
	                        //throw new Exception("Could not load OBJECT for ID " + id );
235
	                    } else {
236
	                        docs = subprocessor.processDocument(id, docs, dataStream);
237
	                        log.debug("SolrIndex.process - subprocessor "+ subprocessor.getClass().getName() +" generated solr doc for id "+id);
238
	                    }
239
	                } catch (Exception e) {
240
	                    e.printStackTrace();
241
	                    log.error(e.getMessage(), e);
242
	                    throw new SolrServerException(e.getMessage());
243
	                }
244
	            }
245
	        }
246
       }
247

    
248
        /*if(docs != null) {
249
                SolrDoc solrDoc = docs.get(id);
250
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
251
                solrDoc.serialize(baos, "UTF-8");
252
                log.warn("after process the science metadata, the solr doc is \n"+baos.toString());
253
        }*/
254
        
255
       // TODO: in the XPathDocumentParser class in d1_cn_index_process module,
256
       // merge is only for resource map. We need more work here.
257
       for (SolrDoc mergeDoc : docs.values()) {
258
           if (!mergeDoc.isMerged()) {
259
                 mergeWithIndexedDocument(mergeDoc);
260
           }
261
       }
262

    
263
       /*if(docs != null) {
264
               SolrDoc solrDoc  = docs.get(id);
265
               ByteArrayOutputStream baos = new ByteArrayOutputStream();
266
               solrDoc.serialize(baos, "UTF-8");
267
               log.warn("after merge, the solr doc is \n"+baos.toString());
268
       }*/
269
       //SolrElementAdd addCommand = getAddCommand(new ArrayList<SolrDoc>(docs.values()));
270
               
271
       return docs;
272
    }
273
    
274
    /**
275
     * Merge updates with existing solr documents
276
     * 
277
     * This method appears to re-set the data package field data into the
278
     * document about to be updated in the solr index. Since packaging
279
     * information is derived from the package document (resource map), this
280
     * information is not present when processing a document contained in a data
281
     * package. This method replaces those values from the existing solr index
282
     * record for the document being processed. -- sroseboo, 1-18-12
283
     * 
284
     * @param indexDocument
285
     * @return
286
     * @throws IOException
287
     * @throws EncoderException
288
     * @throws XPathExpressionException
289
     * @throws SAXException 
290
     * @throws ParserConfigurationException 
291
     * @throws SolrServerException 
292
     * @throws UnsupportedType 
293
     * @throws NotFound 
294
     * @throws NotImplemented 
295
     */
296
    // TODO:combine merge function with resourcemap merge function
297

    
298
    private SolrDoc mergeWithIndexedDocument(SolrDoc indexDocument) throws IOException,
299
            EncoderException, XPathExpressionException, SolrServerException, ParserConfigurationException, SAXException, NotImplemented, NotFound, UnsupportedType {
300
        List<String> ids = new ArrayList<String>();
301
        ids.add(indexDocument.getIdentifier());
302
        //Retrieve the existing solr document from the solr server for the id. If it doesn't exist, null or empty solr doc will be returned.
303
        List<SolrDoc> indexedDocuments = ResourceMapSubprocessor.getSolrDocs(ids);
304
        SolrDoc indexedDocument = indexedDocuments == null || indexedDocuments.size() <= 0 ? null
305
                : indexedDocuments.get(0);
306
        
307
        IndexSchema indexSchema = SolrQueryServiceController.getInstance().getSchema();
308

    
309
        if (indexedDocument == null || indexedDocument.getFieldList().size() <= 0) {
310
            return indexDocument;
311
        } else {
312
            Vector<SolrElementField> mergeNeededFields = new Vector<SolrElementField>(); 
313
            for (SolrElementField field : indexedDocument.getFieldList()) {
314
                if ((field.getName().equals(SolrElementField.FIELD_ISDOCUMENTEDBY)
315
                        || field.getName().equals(SolrElementField.FIELD_DOCUMENTS) || field
316
                        .getName().equals(SolrElementField.FIELD_RESOURCEMAP))
317
                        && !indexDocument.hasFieldWithValue(field.getName(), field.getValue())) {
318
                    indexDocument.addField(field);
319
                } else if (!indexSchema.isCopyFieldTarget(indexSchema.getField(field.getName())) && !indexDocument.hasField(field.getName()) && !isSystemMetadataField(field.getName())) {
320
                    // we don't merge the system metadata field since they can be removed.
321
                    log.debug("SolrIndex.mergeWithIndexedDocument - put the merge-needed existing solr field "+field.getName()+" with value "+field.getValue()+" from the solr server to a vector. We will merge it later.");
322
                    //indexDocument.addField(field);
323
                    mergeNeededFields.add(field);//record this name since we can have mutiple name/value for the same name. See https://projects.ecoinformatics.org/ecoinfo/issues/7168
324
                } 
325
            }
326
            if(mergeNeededFields != null) {
327
                for(SolrElementField field: mergeNeededFields) {
328
                    log.debug("SolrIndex.mergeWithIndexedDocument - merge the existing solr field "+field.getName()+" with value "+field.getValue()+" from the solr server to the currently processing document of "+indexDocument.getIdentifier());
329
                    indexDocument.addField(field);
330
                }
331
            }
332
            indexDocument.setMerged(true);
333
            return indexDocument;
334
        }
335
    }
336
    
337
    /*
338
     * If the given field name is a system metadata field.
339
     */
340
    private boolean isSystemMetadataField(String fieldName) {
341
        boolean is = false;
342
        if (fieldName != null && !fieldName.trim().equals("") && sysmetaSolrFields != null) {
343
            for(SolrField field : sysmetaSolrFields) {
344
                if(field !=  null && field.getName() != null && field.getName().equals(fieldName)) {
345
                    log.debug("SolrIndex.isSystemMetadataField - the field name "+fieldName+" matches one record of system metadata field list. It is a system metadata field.");
346
                    is = true;
347
                    break;
348
                }
349
            }
350
        }
351
        return is;
352
    }
353
    /*
354
     * Generate a Document from the InputStream
355
     */
356
    private Document generateXmlDocument(InputStream smdStream) throws SAXException {
357
        Document doc = null;
358

    
359
        try {
360
            doc = builder.parse(smdStream);
361
        } catch (IOException e) {
362
            log.error(e.getMessage(), e);
363
        }
364

    
365
        return doc;
366
    }
367
    
368
    /*
369
     * Index the fields of the system metadata
370
     */
371
    private List<SolrElementField> processSysmetaFields(Document doc, String identifier) {
372

    
373
        List<SolrElementField> fieldList = new ArrayList<SolrElementField>();
374
        // solrFields is the list of fields defined in the application context
375
       
376
        for (SolrField field : sysmetaSolrFields) {
377
            try {
378
                // the field.getFields method can return a single value or
379
                // multiple values for multi-valued fields
380
                // or can return multiple SOLR document fields.
381
                fieldList.addAll(field.getFields(doc, identifier));
382
            } catch (Exception e) {
383
                e.printStackTrace();
384
            }
385
        }
386
        return fieldList;
387

    
388
    }
389
    
390
    /**
391
     * Check the parameters of the insert or update methods.
392
     * @param pid
393
     * @param systemMetadata
394
     * @param data
395
     * @throws SolrServerException
396
     */
397
    private void checkParams(Identifier pid, SystemMetadata systemMetadata, String objectPath) throws SolrServerException {
398
        if(pid == null || pid.getValue() == null || pid.getValue().trim().equals("")) {
399
            throw new SolrServerException("The identifier of the indexed document should not be null or blank.");
400
        }
401
        if(systemMetadata == null) {
402
            throw new SolrServerException("The system metadata of the indexed document "+pid.getValue()+ " should not be null.");
403
        }
404
        if(objectPath == null) {
405
            throw new SolrServerException("The indexed document itself for pid "+pid.getValue()+" should not be null.");
406
        }
407
    }
408
    
409
    /**
410
     * Insert the indexes for a document.
411
     * @param pid  the id of this document
412
     * @param systemMetadata  the system metadata associated with the data object
413
     * @param data  the path to the object file itself
414
     * @throws SolrServerException 
415
     * @throws MarshallingException 
416
     * @throws EncoderException 
417
     * @throws UnsupportedType 
418
     * @throws NotFound 
419
     * @throws NotImplemented 
420
     */
421
    private synchronized void insert(Identifier pid, SystemMetadata systemMetadata, String objectPath) 
422
                    throws IOException, SAXException, ParserConfigurationException,
423
                    XPathExpressionException, SolrServerException, MarshallingException, EncoderException, NotImplemented, NotFound, UnsupportedType {
424
        checkParams(pid, systemMetadata, objectPath);
425
        log.debug("SolrIndex.insert - trying to insert the solrDoc for object "+pid.getValue());
426
        Map<String, SolrDoc> docs = process(pid.getValue(), systemMetadata, objectPath);
427
        
428
        //transform the Map to the SolrInputDocument which can be used by the solr server
429
        if(docs != null) {
430
            Set<String> ids = docs.keySet();
431
            for(String id : ids) {
432
                if(id != null) {
433
                    SolrDoc doc = docs.get(id);
434
                    insertToIndex(doc);
435
                    log.debug("SolrIndex.insert - inserted the solr-doc object of pid "+id+", which relates to object "+pid.getValue()+", into the solr server.");
436
                }
437
                
438
            }
439
            log.debug("SolrIndex.insert - finished to insert the solrDoc for object "+pid.getValue());
440
        } else {
441
            log.debug("SolrIndex.insert - the genered solrDoc is null. So we will not index the object "+pid.getValue());
442
        }
443
    }
444
    
445
    /**
446
     * Adds the given fields to the solr index for the given pid, preserving the index values
447
     * that previously existed
448
     * @param pid
449
     * @param fields
450
     */
451
    public void insertFields(Identifier pid, Map<String, List<Object>> fields) {
452
    	
453
    	try {
454
			// copy the original values already indexed for this document	
455
	    	SolrQuery query = new SolrQuery("id:\"" + pid.getValue() + "\"");
456
	    	QueryResponse res = solrServer.query(query);
457
	    	SolrDoc doc = new SolrDoc();
458
	    	
459
	    	// include existing values if they exist
460
	        IndexSchema indexSchema = SolrQueryServiceController.getInstance().getSchema();
461

    
462
	        if (res.getResults().size() > 0) {
463
		        SolrDocument orig = res.getResults().get(0);
464
		    	for (String fieldName: orig.getFieldNames()) {
465
		        	//  don't transfer the copyTo fields, otherwise there are errors
466
		        	if (indexSchema.isCopyFieldTarget(indexSchema.getField(fieldName))) {
467
		        		continue;
468
		        	}
469
		        	for (Object value: orig.getFieldValues(fieldName)) {
470
		        		String stringValue = value.toString();
471
		        		// special handling for dates in ISO 8601
472
		        		if (value instanceof Date) {
473
		        			stringValue = DateTimeMarshaller.serializeDateToUTC((Date)value);
474
		        			SolrDateConverter converter = new SolrDateConverter();
475
		        			stringValue = converter.convert(stringValue);
476
		        		}
477
						SolrElementField field = new SolrElementField(fieldName, stringValue);
478
						log.debug("Adding field: " + fieldName);
479
						doc.addField(field);
480
		        	}
481
		        }
482
	        }
483
	    	
484
	        // add the additional fields we are trying to include in the index
485
	        for (String fieldName: fields.keySet()) {
486
	    		List<Object> values = fields.get(fieldName);
487
	    		for (Object value: values) {
488
	    			if (!doc.hasFieldWithValue(fieldName, value.toString())) {
489
	    				if (indexSchema.getField(fieldName).multiValued()) {
490
	    					doc.addField(new SolrElementField(fieldName, value.toString()));
491
	    				} else {
492
	    	    	    	doc.updateOrAddField(fieldName, value.toString());
493
	    				}
494
	    			}
495
	    		}
496
	    	}
497
	        
498
	        // make sure there is an id in the solrdoc so it is added to the index
499
	        if (!doc.hasField(ID)) {
500
	        	doc.updateOrAddField(ID, pid.getValue());
501
	        }
502
	        
503
	        // insert the whole thing
504
	        insertToIndex(doc);
505
    	} catch (Exception e) {
506
    		String error = "SolrIndex.insetFields - could not update the solr index: " + e.getMessage();
507
            writeEventLog(null, pid, error);
508
            log.error(error, e);
509
    	}
510

    
511
    }
512
    
513
    /*
514
     * Insert a SolrDoc to the solr server.
515
     */
516
    private synchronized void insertToIndex(SolrDoc doc) throws SolrServerException, IOException {
517
        if(doc != null ) {
518
            SolrInputDocument solrDoc = new SolrInputDocument();
519
            List<SolrElementField> list = doc.getFieldList();
520
            if(list != null) {
521
                //solrDoc.addField(METACATPIDFIELD, pid);
522
                Iterator<SolrElementField> iterator = list.iterator();
523
                while (iterator.hasNext()) {
524
                    SolrElementField field = iterator.next();
525
                    if(field != null) {
526
                        String value = field.getValue();
527
                        String name = field.getName();
528
                        log.trace("SolrIndex.insertToIndex - add name/value pair - "+name+"/"+value);
529
                        solrDoc.addField(name, value);
530
                    }
531
                }
532
            }
533
            if(!solrDoc.isEmpty()) {
534
                /*IndexEvent event = new IndexEvent();
535
                event.setDate(Calendar.getInstance().getTime());
536
                Identifier pid = new Identifier();
537
                pid.setValue(doc.getIdentifier());
538
                event.setIdentifier(pid);*/
539
                try {
540
                    UpdateResponse response = solrServer.add(solrDoc);
541
                    solrServer.commit();
542
                    /*event.setType(IndexEvent.SUCCESSINSERT);
543
                    event.setDescription("Successfully insert the solr index for the id "+pid.getValue());
544
                    try {
545
                        EventlogFactory.createIndexEventLog().write(event);
546
                    } catch (Exception e) {
547
                        log.error("SolrIndex.insertToIndex - IndexEventLog can't log the index inserting event :"+e.getMessage());
548
                    }*/
549
                } catch (SolrServerException e) {
550
                    /*event.setAction(Event.CREATE);
551
                    event.setDescription("Failed to insert the solr index for the id "+pid.getValue()+" since "+e.getMessage());
552
                    try {
553
                        EventlogFactory.createIndexEventLog().write(event);
554
                    } catch (Exception ee) {
555
                        log.error("SolrIndex.insertToIndex - IndexEventLog can't log the index inserting event :"+ee.getMessage());
556
                    }*/
557
                    throw e;
558
                } catch (IOException e) {
559
                    /*event.setAction(Event.CREATE);
560
                    event.setDescription("Failed to insert the solr index for the id "+pid.getValue()+" since "+e.getMessage());
561
                    try {
562
                        EventlogFactory.createIndexEventLog().write(event);
563
                    } catch (Exception ee) {
564
                        log.error("SolrIndex.insertToIndex - IndexEventLog can't log the index inserting event :"+ee.getMessage());
565
                    }*/
566
                    throw e;
567
                    
568
                }
569
                //System.out.println("=================the response is:\n"+response.toString());
570
            }
571
        }
572
    }
573
    
574
    /**
575
     * Update the solr index. This method handles the three scenarios:
576
     * 1. Remove an existing doc - if the the system metadata shows the value of the archive is true,
577
     *    remove the index for the previous version(s) and generate new index for the doc.
578
     * 2. Add a new doc - if the system metadata shows the value of the archive is false, generate the
579
     *    index for the doc.
580
     */
581
    public void update(Identifier pid, SystemMetadata systemMetadata) {
582
        if(systemMetadata==null || pid==null) {
583
            log.error("SolrIndex.update - the systemMetadata or pid is null. So nothing will be indexed.");
584
            return;
585
        }
586
        log.debug("SolrIndex.update - trying to update(insert or remove) solr index of object "+pid.getValue());
587
        String objectPath = null;
588
        try {
589
            if (systemMetadata.getArchived() == null || !systemMetadata.getArchived()) {
590
                objectPath = DistributedMapsFactory.getObjectPathMap().get(pid);
591
            }
592
            update(pid, systemMetadata, objectPath);
593
            EventlogFactory.createIndexEventLog().remove(pid);
594
        } catch (Exception e) {
595
            String error = "SolrIndex.update - could not update the solr index since " + e.getMessage();
596
            writeEventLog(systemMetadata, pid, error);
597
            log.error(error, e);
598
        }
599
    }
600
   
601
    
602
    /**
603
     * Update the solr index. This method handles the three scenarios:
604
     * 1. Remove an existing doc - if the the system metadata shows the value of the archive is true,
605
     *    remove the index for the previous version(s) and generate new index for the doc.
606
     * 2. Add a new doc - if the system metadata shows the value of the archive is false, generate the
607
     *    index for the doc.
608
     * @param pid
609
     * @param systemMetadata
610
     * @param data
611
     * @throws SolrServerException
612
     * @throws ServiceFailure
613
     * @throws XPathExpressionException
614
     * @throws NotImplemented
615
     * @throws NotFound
616
     * @throws UnsupportedType
617
     * @throws IOException
618
     * @throws SAXException
619
     * @throws ParserConfigurationException
620
     * @throws OREParserException
621
     * @throws MarshallingException
622
     * @throws EncoderException
623
     */
624
    void update(Identifier pid, SystemMetadata systemMetadata, String objectPath) throws Exception {
625
        //checkParams(pid, systemMetadata, objectPath);
626
        if(systemMetadata==null || pid==null) {
627
            log.error("SolrIndex.update - the systemMetadata or pid is null. So nothing will be indexed.");
628
            return;
629
        }
630
        boolean isArchive = systemMetadata.getArchived() != null && systemMetadata.getArchived();
631
        if(isArchive ) {
632
            //delete the index for the archived objects
633
            remove(pid.getValue(), systemMetadata);
634
            log.info("SolrIndex.update============================= archive the idex for the identifier "+pid.getValue());
635
        } else {
636
            //generate index for either add or update.
637
            insert(pid, systemMetadata, objectPath);
638
            log.info("SolrIndex.update============================= insert index for the identifier "+pid.getValue());
639
        }
640
    }
641
    
642
   
643

    
644
    /*
645
     * Is the pid a resource map
646
     */
647
    private boolean isDataPackage(String pid, SystemMetadata sysmeta) throws FileNotFoundException, ServiceFailure {
648
        boolean isDataPackage = false;
649
        //SystemMetadata sysmeta = DistributedMapsFactory.getSystemMetadata(pid);
650
        if(sysmeta != null) {
651
            isDataPackage = IndexGeneratorTimerTask.isResourceMap(sysmeta.getFormatId());
652
        }
653
        return isDataPackage;
654
    }
655

    
656
    private boolean isPartOfDataPackage(String pid) throws XPathExpressionException, NotImplemented, NotFound, UnsupportedType, SolrServerException, IOException, ParserConfigurationException, SAXException {
657
        SolrDoc dataPackageIndexDoc = ResourceMapSubprocessor.getSolrDoc(pid);
658
        if (dataPackageIndexDoc != null) {
659
            String resourceMapId = dataPackageIndexDoc
660
                    .getFirstFieldValue(SolrElementField.FIELD_RESOURCEMAP);
661
            return StringUtils.isNotEmpty(resourceMapId);
662
        } else {
663
            return false;
664
        }
665
    }
666
    /**
667
     * Remove the indexed associated with specified pid.
668
     * @param pid  the pid which the indexes are associated with
669
     * @throws IOException
670
     * @throws SolrServerException
671
     * @throws ParserConfigurationException 
672
     * @throws SAXException 
673
     * @throws UnsupportedType 
674
     * @throws NotFound 
675
     * @throws NotImplemented 
676
     * @throws XPathExpressionException 
677
     * @throws ServiceFailure 
678
     * @throws OREParserException 
679
     */
680
    private void remove(String pid, SystemMetadata sysmeta) throws Exception {
681
        if (isDataPackage(pid, sysmeta)) {
682
            removeDataPackage(pid);
683
        } else if (isPartOfDataPackage(pid)) {
684
            removeFromDataPackage(pid);
685
        } else {
686
            removeFromIndex(pid);
687
        }
688
    }
689
    
690
    /*
691
     * Remove the resource map from the solr index. It doesn't only remove the index for itself and also
692
     * remove the relationship for the related metadata and data objects.
693
     */
694
    private void removeDataPackage(String pid) throws Exception {
695
        removeFromIndex(pid);
696
        List<SolrDoc> docsToUpdate = getUpdatedSolrDocsByRemovingResourceMap(pid);
697
        if (docsToUpdate != null && !docsToUpdate.isEmpty()) {
698
            //SolrElementAdd addCommand = new SolrElementAdd(docsToUpdate);
699
            //httpService.sendUpdate(solrIndexUri, addCommand);
700
            for(SolrDoc doc : docsToUpdate) {
701
                removeFromIndex(doc.getIdentifier());
702
                insertToIndex(doc);
703
            }
704
        }
705

    
706
    }
707

    
708
    /*
709
     * Get the list of the solr doc which need to be updated because the removal of the resource map
710
     */
711
    private List<SolrDoc> getUpdatedSolrDocsByRemovingResourceMap(String resourceMapId)
712
            throws UnsupportedType, NotFound, SolrServerException, ParserConfigurationException, SAXException, MalformedURLException, IOException, XPathExpressionException {
713
        List<SolrDoc> updatedSolrDocs = null;
714
        if (resourceMapId != null && !resourceMapId.trim().equals("")) {
715
            /*List<SolrDoc> docsContainResourceMap = httpService.getDocumentsByResourceMap(
716
                    solrQueryUri, resourceMapId);*/
717
            List<SolrDoc> docsContainResourceMap = ResourceMapSubprocessor.getDocumentsByResourceMap(resourceMapId);
718
            updatedSolrDocs = removeResourceMapRelationship(docsContainResourceMap,
719
                    resourceMapId);
720
        }
721
        return updatedSolrDocs;
722
    }
723

    
724
    /*
725
     * Get the list of the solr doc which need to be updated because the removal of the resource map
726
     */
727
    private List<SolrDoc> removeResourceMapRelationship(List<SolrDoc> docsContainResourceMap,
728
            String resourceMapId) throws XPathExpressionException, IOException {
729
        List<SolrDoc> totalUpdatedSolrDocs = new ArrayList<SolrDoc>();
730
        if (docsContainResourceMap != null && !docsContainResourceMap.isEmpty()) {
731
            for (SolrDoc doc : docsContainResourceMap) {
732
                List<SolrDoc> updatedSolrDocs = new ArrayList<SolrDoc>();
733
                List<String> resourceMapIdStrs = doc
734
                        .getAllFieldValues(SolrElementField.FIELD_RESOURCEMAP);
735
                List<String> dataIdStrs = doc
736
                        .getAllFieldValues(SolrElementField.FIELD_DOCUMENTS);
737
                List<String> metadataIdStrs = doc
738
                        .getAllFieldValues(SolrElementField.FIELD_ISDOCUMENTEDBY);
739
                if ((dataIdStrs == null || dataIdStrs.isEmpty())
740
                        && (metadataIdStrs == null || metadataIdStrs.isEmpty())) {
741
                    // only has resourceMap field, doesn't have either documentBy or documents fields.
742
                    // so we only remove the resource map field.
743
                    doc.removeFieldsWithValue(SolrElementField.FIELD_RESOURCEMAP, resourceMapId);
744
                    updatedSolrDocs.add(doc);
745
                } else if ((dataIdStrs != null && !dataIdStrs.isEmpty())
746
                        && (metadataIdStrs == null || metadataIdStrs.isEmpty())) {
747
                    //The solr doc is for a metadata object since the solr doc documents data files
748
                    updatedSolrDocs = removeAggregatedItems(resourceMapId, doc, resourceMapIdStrs,
749
                            dataIdStrs, SolrElementField.FIELD_DOCUMENTS);
750
                } else if ((dataIdStrs == null || dataIdStrs.isEmpty())
751
                        && (metadataIdStrs != null && !metadataIdStrs.isEmpty())) {
752
                    //The solr doc is for a data object since it documentedBy elements.
753
                    updatedSolrDocs = removeAggregatedItems(resourceMapId, doc, resourceMapIdStrs,
754
                            metadataIdStrs, SolrElementField.FIELD_ISDOCUMENTEDBY);
755
                } else if ((dataIdStrs != null && !dataIdStrs.isEmpty())
756
                        && (metadataIdStrs != null && !metadataIdStrs.isEmpty())){
757
                    // both metadata and data for one object
758
                    List<SolrDoc> solrDocsRemovedDocuments = removeAggregatedItems(resourceMapId, doc, resourceMapIdStrs,
759
                            dataIdStrs, SolrElementField.FIELD_DOCUMENTS);
760
                    List<SolrDoc> solrDocsRemovedDocumentBy = removeAggregatedItems(resourceMapId, doc, resourceMapIdStrs,
761
                            metadataIdStrs, SolrElementField.FIELD_ISDOCUMENTEDBY);
762
                    updatedSolrDocs = mergeUpdatedSolrDocs(solrDocsRemovedDocumentBy, solrDocsRemovedDocuments);
763
                }
764
                //move them to the final result
765
                if(updatedSolrDocs != null) {
766
                    for(SolrDoc updatedDoc: updatedSolrDocs) {
767
                        totalUpdatedSolrDocs.add(updatedDoc);
768
                    }
769
                }
770
                
771
            }
772

    
773
        }
774
        return totalUpdatedSolrDocs;
775
    }
776
    
777
    /*
778
     * Process the list of ids of the documentBy/documents in a slor doc.
779
     */
780
    private List<SolrDoc> removeAggregatedItems(String targetResourceMapId, SolrDoc doc,
781
            List<String> resourceMapIdsInDoc, List<String> aggregatedItemsInDoc, String fieldNameRemoved) {
782
        List<SolrDoc> updatedSolrDocs = new ArrayList<SolrDoc>();
783
        if (doc != null && resourceMapIdsInDoc != null && aggregatedItemsInDoc != null
784
                && fieldNameRemoved != null) {
785
            if (resourceMapIdsInDoc.size() == 1) {
786
                //only has one resource map. remove the resource map. also remove the documentBy
787
                doc.removeFieldsWithValue(SolrElementField.FIELD_RESOURCEMAP, targetResourceMapId);
788
                doc.removeAllFields(fieldNameRemoved);
789
                updatedSolrDocs.add(doc);
790
            } else if (resourceMapIdsInDoc.size() > 1) {
791
                //we have multiple resource maps. We should match them.                     
792
                Map<String, String> ids = matchResourceMapsAndItems(doc.getIdentifier(),
793
                        targetResourceMapId, resourceMapIdsInDoc, aggregatedItemsInDoc, fieldNameRemoved);
794
                if (ids != null) {
795
                    for (String id : ids.keySet()) {
796
                        doc.removeFieldsWithValue(fieldNameRemoved, id);
797
                    }
798
                }
799
                doc.removeFieldsWithValue(SolrElementField.FIELD_RESOURCEMAP,
800
                        targetResourceMapId);
801
                updatedSolrDocs.add(doc);
802
                /*if (aggregatedItemsInDoc.size() > 1) {
803
                    
804

    
805
                } else {
806
                    //multiple resource map aggregate same metadata and data. Just remove the resource map
807
                    doc.removeFieldsWithValue(SolrElementField.FIELD_RESOURCEMAP,
808
                            targetResourceMapId);
809
                    updatedSolrDocs.add(doc);
810
                }*/
811
            }
812
        }
813
        return updatedSolrDocs;
814
    }
815

    
816
    /*
817
     * Return a map of mapping aggregation id map the target resourceMapId.
818
     * This will look the aggregation information in another side - If the targetId
819
     * is a metadata object, we will look the data objects which it describes; If 
820
     * the targetId is a data object, we will look the metadata object which documents it.
821
     */
822
    private Map<String, String> matchResourceMapsAndItems(String targetId,
823
            String targetResourceMapId, List<String> originalResourceMaps, List<String> aggregatedItems, String fieldName) {
824
        Map<String, String> map = new HashMap<String, String>();
825
        if (targetId != null && targetResourceMapId != null && aggregatedItems != null
826
                && fieldName != null) {
827
            String newFieldName = null;
828
            if (fieldName.equals(SolrElementField.FIELD_ISDOCUMENTEDBY)) {
829
                newFieldName = SolrElementField.FIELD_DOCUMENTS;
830
            } else if (fieldName.equals(SolrElementField.FIELD_DOCUMENTS)) {
831
                newFieldName = SolrElementField.FIELD_ISDOCUMENTEDBY;
832
            }
833
            if (newFieldName != null) {
834
                for (String item : aggregatedItems) {
835
                    SolrDoc doc = null;
836
                    try {
837
                        doc = getDocumentById(item);
838
                        List<String> fieldValues = doc.getAllFieldValues(newFieldName);
839
                        List<String> resourceMapIds = doc
840
                                .getAllFieldValues(SolrElementField.FIELD_RESOURCEMAP);
841
                        if ((fieldValues != null && fieldValues.contains(targetId))
842
                                && (resourceMapIds != null && resourceMapIds
843
                                        .contains(targetResourceMapId))) {
844
                            //okay, we found the target aggregation item id and the resource map id
845
                            //in this solr doc. However, we need check if another resource map with different
846
                            //id but specify the same relationship. If we have the id(s), we should not
847
                            // remove the documents( or documentBy) element since we need to preserve the 
848
                            // relationship for the remain resource map. 
849
                            boolean hasDuplicateIds = false;
850
                            if(originalResourceMaps != null) {
851
                               for(String id :resourceMapIds) {
852
                                    if (originalResourceMaps.contains(id) && !id.equals(targetResourceMapId)) {
853
                                        hasDuplicateIds = true;
854
                                        break;
855
                                    }
856
                                }
857
                            }
858
                            if(!hasDuplicateIds) {
859
                                map.put(item, targetResourceMapId);
860
                            }
861
                            
862
                        }
863
                    } catch (Exception e) {
864
                        log.warn("SolrIndex.matchResourceMapsAndItems - can't get the solrdoc for the id "
865
                                + item + " since " + e.getMessage());
866
                    }
867
                }
868
            }
869
        }
870
        return map;
871
    }
872

    
873
    /*
874
     * Get the solr index doc from the index server for the given id.
875
     */
876
    private SolrDoc getDocumentById(String id) throws NotImplemented, NotFound, UnsupportedType, 
877
                SolrServerException, ParserConfigurationException, SAXException, XPathExpressionException, IOException {
878
        SolrDoc doc = ResourceMapSubprocessor.getSolrDoc(id);
879
        return doc;
880
    }
881
    
882
    /*
883
     * Merge two list of updated solr docs. removedDocumentBy has the correct information about documentBy element.
884
     * removedDocuments has the correct information about the documents element.
885
     * So we go through the two list and found the two docs having the same identifier.
886
     * Get the list of the documents value from the one in the removedDoucments (1). 
887
     * Remove all values of documents from the one in the removedDocumentBy. 
888
     * Then copy the list of documents value from (1) to to the one in the removedDocumentBy.
889
     */
890
    private List<SolrDoc> mergeUpdatedSolrDocs(List<SolrDoc>removedDocumentBy, List<SolrDoc>removedDocuments) {
891
        List<SolrDoc> mergedDocuments = new ArrayList<SolrDoc>();
892
        if(removedDocumentBy == null || removedDocumentBy.isEmpty()) {
893
            mergedDocuments = removedDocuments;
894
        } else if (removedDocuments == null || removedDocuments.isEmpty()) {
895
            mergedDocuments = removedDocumentBy;
896
        } else {
897
            int sizeOfDocBy = removedDocumentBy.size();
898
            int sizeOfDocs = removedDocuments.size();
899
            for(int i=sizeOfDocBy-1; i>= 0; i--) {
900
                SolrDoc docInRemovedDocBy = removedDocumentBy.get(i);
901
                for(int j= sizeOfDocs-1; j>=0; j--) {
902
                    SolrDoc docInRemovedDocs = removedDocuments.get(j);
903
                    if(docInRemovedDocBy.getIdentifier().equals(docInRemovedDocs.getIdentifier())) {
904
                        //find the same doc in both list. let's merge them.
905
                        //first get all the documents element from the docWithDocs(it has the correct information about the documents element)
906
                        List<String> idsInDocuments = docInRemovedDocs.getAllFieldValues(SolrElementField.FIELD_DOCUMENTS);
907
                        docInRemovedDocBy.removeAllFields(SolrElementField.FIELD_DOCUMENTS);//clear out any documents element in docInRemovedDocBy
908
                        //add the Documents element from the docInRemovedDocs if it has any.
909
                        // The docInRemovedDocs has the correct information about the documentBy. Now it copied the correct information of the documents element.
910
                        // So docInRemovedDocs has both correct information about the documentBy and documents elements.
911
                        if(idsInDocuments != null) {
912
                            for(String id : idsInDocuments) {
913
                                if(id != null && !id.trim().equals("")) {
914
                                    docInRemovedDocBy.addField(new SolrElementField(SolrElementField.FIELD_DOCUMENTS, id));
915
                                }
916
                                
917
                            }
918
                        }
919
                        //intersect the resource map ids.
920
                        List<String> resourceMapIdsInWithDocs = docInRemovedDocs.getAllFieldValues(SolrElementField.FIELD_RESOURCEMAP);
921
                        List<String> resourceMapIdsInWithDocBy = docInRemovedDocBy.getAllFieldValues(SolrElementField.FIELD_RESOURCEMAP);
922
                        docInRemovedDocBy.removeAllFields(SolrElementField.FIELD_RESOURCEMAP);
923
                        Collection resourceMapIds = CollectionUtils.union(resourceMapIdsInWithDocs, resourceMapIdsInWithDocBy);
924
                        if(resourceMapIds != null) {
925
                            for(Object idObj : resourceMapIds) {
926
                                String id = (String)idObj;
927
                                docInRemovedDocBy.addField(new SolrElementField(SolrElementField.FIELD_RESOURCEMAP, id));
928
                            }
929
                        }
930
                        //we don't need do anything about the documentBy elements since the docInRemovedDocBy has the correct information.
931
                        mergedDocuments.add(docInRemovedDocBy);
932
                        //delete the two documents from the list
933
                        removedDocumentBy.remove(i);
934
                        removedDocuments.remove(j);
935
                        break;
936
                    }
937
                    
938
                }
939
            }
940
            // when we get there, if the two lists are empty, this will be a perfect merge. However, if something are left. we 
941
            //just put them in.
942
            for(SolrDoc doc: removedDocumentBy) {
943
                mergedDocuments.add(doc);
944
            }
945
            for(SolrDoc doc: removedDocuments) {
946
                mergedDocuments.add(doc);
947
            }
948
        }
949
        return mergedDocuments;
950
    }
951
    
952

    
953
    /*
954
     * Remove a pid which is part of resource map.
955
     */
956
    private void removeFromDataPackage(String pid) throws Exception  {
957
        SolrDoc indexedDoc = ResourceMapSubprocessor.getSolrDoc(pid);
958
        removeFromIndex(pid);
959
        List<SolrDoc> docsToUpdate = new ArrayList<SolrDoc>();
960

    
961
        List<String> documents = indexedDoc.getAllFieldValues(SolrElementField.FIELD_DOCUMENTS);
962
        for (String documentsValue : documents) {
963
            SolrDoc solrDoc = ResourceMapSubprocessor.getSolrDoc(documentsValue);
964
            solrDoc.removeFieldsWithValue(SolrElementField.FIELD_ISDOCUMENTEDBY, pid);
965
            removeFromIndex(documentsValue);
966
            insertToIndex(solrDoc);
967
        }
968

    
969
        List<String> documentedBy = indexedDoc
970
                .getAllFieldValues(SolrElementField.FIELD_ISDOCUMENTEDBY);
971
        for (String documentedByValue : documentedBy) {
972
            SolrDoc solrDoc = ResourceMapSubprocessor.getSolrDoc(documentedByValue);
973
            solrDoc.removeFieldsWithValue(SolrElementField.FIELD_DOCUMENTS, pid);
974
            //docsToUpdate.add(solrDoc);
975
            removeFromIndex(documentedByValue);
976
            insertToIndex(solrDoc);
977
        }
978

    
979
        //SolrElementAdd addCommand = new SolrElementAdd(docsToUpdate);
980
        //httpService.sendUpdate(solrIndexUri, addCommand);
981
    }
982

    
983
    /*
984
     * Remove a pid from the solr index
985
     */
986
    private synchronized void removeFromIndex(String identifier) throws Exception {
987
    	
988
    	
989
    	Map<String, SolrDoc> docs = new HashMap<String, SolrDoc>();
990

    
991
        for (IDocumentDeleteSubprocessor deleteSubprocessor : deleteSubprocessors) {
992
            docs.putAll(deleteSubprocessor.processDocForDelete(identifier, docs));
993
        }
994
        List<SolrDoc> docsToUpdate = new ArrayList<SolrDoc>();
995
        List<String> idsToIndex = new ArrayList<String>();
996
        for (String idToUpdate : docs.keySet()) {
997
            if (docs.get(idToUpdate) != null) {
998
                docsToUpdate.add(docs.get(idToUpdate));
999
            } else {
1000
                idsToIndex.add(idToUpdate);
1001
            }
1002
        }
1003

    
1004
        // update the docs we have
1005
        for (SolrDoc docToUpdate : docsToUpdate) {
1006
        	insertToIndex(docToUpdate);
1007
        }
1008
        
1009
        // delete this one
1010
        deleteDocFromIndex(identifier);
1011

    
1012
        // index the rest
1013
        for (String idToIndex : idsToIndex) {
1014
        	Identifier pid = new Identifier();
1015
        	pid.setValue(idToIndex);
1016
            SystemMetadata sysMeta = DistributedMapsFactory.getSystemMetadata(idToIndex);
1017
            if (SolrDoc.visibleInIndex(sysMeta)) {
1018
                String objectPath = DistributedMapsFactory.getObjectPathMap().get(pid);
1019
                insert(pid, sysMeta, objectPath);
1020
            }
1021
        }
1022
    		
1023
    }
1024
    
1025
    private void deleteDocFromIndex(String pid) throws Exception {
1026
    	if (pid != null && !pid.trim().equals("")) {
1027
            /*IndexEvent event = new IndexEvent();
1028
            event.setDate(Calendar.getInstance().getTime());
1029
            Identifier identifier = new Identifier();
1030
            identifier.setValue(pid);
1031
            event.setIdentifier(identifier);*/
1032
            try {
1033
                solrServer.deleteById(pid);
1034
                solrServer.commit();
1035
                /*event.setType(IndexEvent.SUCCESSDELETE);
1036
                event.setDescription("Successfully remove the solr index for the id "+identifier.getValue());
1037
                try {
1038
                    EventlogFactory.createIndexEventLog().write(event);
1039
                } catch (Exception e) {
1040
                    log.error("SolrIndex.removeFromIndex - IndexEventLog can't log the index deleting event :"+e.getMessage());
1041
                }*/
1042
            } catch (SolrServerException e) {
1043
                /*event.setAction(Event.DELETE);
1044
                event.setDescription("Failurely remove the solr index for the id "+identifier.getValue()+" since "+e.getMessage());
1045
                try {
1046
                    EventlogFactory.createIndexEventLog().write(event);
1047
                } catch (Exception ee) {
1048
                    log.error("SolrIndex.removeFromIndex - IndexEventLog can't log the index deleting event :"+ee.getMessage());
1049
                }*/
1050
                throw e;
1051
                
1052
            } catch (IOException e) {
1053
                /*event.setAction(Event.DELETE);
1054
                event.setDescription("Failurely remove the solr index for the id "+identifier.getValue()+" since "+e.getMessage());
1055
                try {
1056
                    EventlogFactory.createIndexEventLog().write(event);
1057
                } catch (Exception ee) {
1058
                    log.error("SolrIndex.removeFromIndex - IndexEventLog can't log the index deleting event :"+ee.getMessage());
1059
                }*/
1060
                throw e;
1061
            }
1062
            
1063
        }
1064
    
1065
    }
1066

    
1067
    /**
1068
     * Get the solrServer
1069
     * @return
1070
     */
1071
    public SolrServer getSolrServer() {
1072
        return solrServer;
1073
    }
1074

    
1075
    /**
1076
     * Set the solrServer. 
1077
     * @param solrServer
1078
     */
1079
    public void setSolrServer(SolrServer solrServer) {
1080
        this.solrServer = solrServer;
1081
    }
1082
    
1083
    /**
1084
     * Get all indexed ids in the solr server. 
1085
     * @return an empty list if there is no index.
1086
     * @throws SolrServerException
1087
     */
1088
    public List<String> getSolrIds() throws SolrServerException {
1089
        List<String> list = new ArrayList<String>();
1090
        SolrQuery query = new SolrQuery(IDQUERY); 
1091
        query.setRows(Integer.MAX_VALUE); 
1092
        query.setFields(ID); 
1093
        QueryResponse response = solrServer.query(query); 
1094
        SolrDocumentList docs = response.getResults();
1095
        if(docs != null) {
1096
            for(SolrDocument doc :docs) {
1097
                String identifier = (String)doc.getFieldValue(ID);
1098
                //System.out.println("======================== "+identifier);
1099
                list.add(identifier);
1100
            }
1101
        }
1102
        return list;
1103
    }
1104
    
1105
    private void writeEventLog(SystemMetadata systemMetadata, Identifier pid, String error) {
1106
        IndexEvent event = new IndexEvent();
1107
        event.setIdentifier(pid);
1108
        event.setDate(Calendar.getInstance().getTime());
1109
        String action = null;
1110
        if (systemMetadata == null ) {
1111
            action = Event.CREATE.xmlValue();
1112
            event.setAction(Event.CREATE);
1113
        }
1114
        else if(systemMetadata.getArchived() != null && systemMetadata.getArchived()) {
1115
            action = Event.DELETE.xmlValue();
1116
            event.setAction(Event.DELETE);
1117
        } else {
1118
            action = Event.CREATE.xmlValue();
1119
            event.setAction(Event.CREATE);
1120
        }
1121
        event.setDescription("Failed to "+action+"the solr index for the id "+pid.getValue()+" since "+error);
1122
        try {
1123
            EventlogFactory.createIndexEventLog().write(event);
1124
        } catch (Exception ee) {
1125
            log.error("SolrIndex.insertToIndex - IndexEventLog can't log the index inserting event :"+ee.getMessage());
1126
        }
1127
    }
1128
}
(6-6/7)