001/* 002 * Copyright (c) 2006-2014 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * Florent Guillaume 011 * Stephane Lacoin 012 */ 013package org.nuxeo.ecm.core.storage; 014 015import java.io.Serializable; 016import java.util.Collection; 017import java.util.Collections; 018import java.util.List; 019 020import org.apache.commons.logging.Log; 021import org.apache.commons.logging.LogFactory; 022import org.nuxeo.ecm.core.api.DocumentModel; 023import org.nuxeo.ecm.core.api.DocumentRef; 024import org.nuxeo.ecm.core.api.IdRef; 025import org.nuxeo.ecm.core.work.AbstractWork; 026import org.nuxeo.ecm.core.work.api.WorkManager; 027 028/** 029 * Work task that inserts the fulltext (extracted manually by the session at save time, or through 030 * FulltextExtractorWork) into the fulltext table. 031 * <p> 032 * This is done single-threaded through the use of a {@link WorkManager} queue with only one thread. 033 */ 034public class FulltextUpdaterWork extends AbstractWork { 035 036 private static final long serialVersionUID = 1L; 037 038 private static final Log log = LogFactory.getLog(FulltextUpdaterWork.class); 039 040 public static final String SYSPROP_FULLTEXT_SIMPLE = "fulltextSimple"; 041 042 public static final String SYSPROP_FULLTEXT_BINARY = "fulltextBinary"; 043 044 public static final String SYSPROP_FULLTEXT_JOBID = "fulltextJobId"; 045 046 public static final String FULLTEXT_DEFAULT_INDEX = "default"; 047 048 protected static final String CATEGORY = "fulltextUpdater"; 049 050 protected static final String TITLE = "Fulltext Updater"; 051 052 /** Is this a simple text index or a binary text one. */ 053 protected final boolean isSimpleText; 054 055 /** If true, then all the documents with the id as their jobId are updated. */ 056 protected final boolean isJob; 057 058 /** The indexes and text to be updated. */ 059 protected final List<IndexAndText> indexesAndText; 060 061 public static class IndexAndText implements Serializable { 062 private static final long serialVersionUID = 1L; 063 064 public String indexName; 065 066 public String text; 067 068 public IndexAndText(String indexName, String text) { 069 this.indexName = indexName; 070 this.text = text; 071 } 072 } 073 074 public FulltextUpdaterWork(String repositoryName, String docId, boolean isSimpleText, boolean isJob, 075 List<IndexAndText> indexesAndText) { 076 super(); // random id, for unique job 077 setDocument(repositoryName, docId); 078 this.isSimpleText = isSimpleText; 079 this.isJob = isJob; 080 this.indexesAndText = indexesAndText; 081 } 082 083 @Override 084 public String getCategory() { 085 return CATEGORY; 086 } 087 088 @Override 089 public String getTitle() { 090 return TITLE; 091 } 092 093 @Override 094 public int getRetryCount() { 095 return 1; 096 } 097 098 @Override 099 public void work() { 100 initSession(); 101 // if the runtime has shut down (normally because tests are finished) 102 // this can happen, see NXP-4009 103 if (session.getPrincipal() == null) { 104 return; 105 } 106 107 setProgress(Progress.PROGRESS_0_PC); 108 setStatus("Updating"); 109 update(); 110 setStatus("Saving"); 111 session.save(); 112 setStatus("Done"); 113 } 114 115 protected void update() { 116 Collection<DocumentModel> docs; 117 if (isJob) { 118 String query = String.format("SELECT * FROM Document WHERE ecm:fulltextJobId = '%s' AND ecm:isProxy = 0", 119 docId); 120 docs = session.query(query); 121 } else { 122 DocumentRef ref = new IdRef(docId); 123 if (!session.exists(ref)) { 124 // doc is gone 125 return; 126 } 127 DocumentModel doc = session.getDocument(ref); 128 if (doc.isProxy()) { 129 // proxies don't have any fulltext attached, it's 130 // the target document that carries it 131 return; 132 } 133 docs = Collections.singleton(doc); 134 } 135 for (DocumentModel doc : docs) { 136 for (IndexAndText indexAndText : indexesAndText) { 137 session.setDocumentSystemProp(doc.getRef(), getFulltextPropertyName(indexAndText.indexName), 138 indexAndText.text); 139 } 140 } 141 if (isJob) { 142 // reset job id 143 for (DocumentModel doc : docs) { 144 session.setDocumentSystemProp(doc.getRef(), SYSPROP_FULLTEXT_JOBID, null); 145 } 146 } 147 } 148 149 protected String getFulltextPropertyName(String indexName) { 150 String name = isSimpleText ? SYSPROP_FULLTEXT_SIMPLE : SYSPROP_FULLTEXT_BINARY; 151 if (!FULLTEXT_DEFAULT_INDEX.equals(indexName)) { 152 name += '_' + indexName; 153 } 154 return name; 155 } 156 157}