package org.exist.fulltext; import org.exist.TestUtils; import org.exist.collections.Collection; import org.exist.collections.CollectionConfigurationManager; import org.exist.collections.IndexInfo; import org.exist.dom.DefaultDocumentSet; import org.exist.dom.DocumentSet; import org.exist.dom.MutableDocumentSet; import org.exist.dom.QName; import org.exist.security.PermissionDeniedException; import org.exist.security.SecurityManager; import org.exist.security.xacml.AccessContext; import org.exist.storage.BrokerPool; import org.exist.storage.DBBroker; import org.exist.storage.ElementValue; import org.exist.storage.txn.TransactionManager; import org.exist.storage.txn.Txn; import org.exist.test.TestConstants; import org.exist.util.Configuration; import org.exist.util.ConfigurationHelper; import org.exist.util.Occurrences; import org.exist.xmldb.XmldbURI; import org.exist.xquery.XQuery; import org.exist.xquery.value.Sequence; import org.exist.xupdate.Modification; import org.exist.xupdate.XUpdateProcessor; import org.junit.*; import static org.junit.Assert.*; import org.xml.sax.InputSource; import java.io.File; import java.io.StringReader; import org.exist.storage.TextSearchEngine; /** * Low-level tests for fulltext index configuration and index updates. */ public class FTIndexTest { public final static String XML = "<content>" + "<figure>" + "<title>Location of equiment items on aircraft</title>" + "<img src='foo.jpg'/>" + "<img src='baz.jpg'/>" + "</figure>" + "<figure>" + "<title>Hydraulic Power<b>System</b></title>" + "<p>paragraphs with <span>mix</span><span>ed</span> content are <span>danger</span>ous.</p>" + "</figure>" + "</content>"; private static String XML1 = "<test>" + " <item id='1' attr='attribute'><description>Chair</description></item>" + " <item id='2'><description>Table</description><price>892.25</price></item>" + " <item id='3'><description>Cabinet</description><price>1525.00</price></item>" + "</test>"; private static String COLLECTION_CONFIG1 = "<collection xmlns=\"http://exist-db.org/collection-config/1.0\">" + " <index>" + " <fulltext default=\"none\">" + " <include path=\"/content/figure/title\"/>" + " <create qname=\"p\" content=\"mixed\"/>" + " <create qname=\"content\"/>" + " </fulltext>" + " </index>" + "</collection>"; private static String COLLECTION_CONFIG2 = "<collection xmlns=\"http://exist-db.org/collection-config/1.0\">" + " <index>" + " <fulltext default=\"none\">" + " <create qname=\"item\"/>" + " <create qname=\"description\"/>" + " <create qname=\"price\"/>" + " <create qname=\"@attr\"/>" + " </fulltext>" + " </index>" + "</collection>"; private static String COLLECTION_CONFIG3 = "<collection xmlns=\"http://exist-db.org/collection-config/1.0\">" + " <index>" + " <fulltext default=\"none\">" + " <include path=\"/content/figure/title\" content=\"mixed\"/>" + " <include path=\"/content//p\" content=\"mixed\"/>" + " </fulltext>" + " </index>" + "</collection>"; private static String XUPDATE_START = "<xu:modifications version=\"1.0\" xmlns:xu=\"http://www.xmldb.org/xupdate\">"; private static String XUPDATE_END = "</xu:modifications>"; private static BrokerPool pool; private static Collection root; private static final QName[] QNDESC = new QName[]{ new QName("description", "", "") }; private static final QName[] QNPRICE = new QName[]{ new QName("price", "", "") }; private static final QName[] QNITEM = new QName[]{ new QName("item", "", "") }; @Test public void mixedIndexes() { DocumentSet docs = configureAndStore(COLLECTION_CONFIG3, XML, "mixedIndexes.xml"); DBBroker broker = null; try { broker = pool.get(org.exist.security.SecurityManager.SYSTEM_USER); assertNotNull(broker); Occurrences[] occur = checkIndex(docs, broker, null, "hydraulic", 1); assertEquals("hydraulic", occur[0].getTerm()); checkIndex(docs, broker, null, "system", 0); occur = checkIndex(docs, broker, null, "powersystem", 1); assertEquals("powersystem", occur[0].getTerm()); occur = checkIndex(docs, broker, null, "mix", 1); assertEquals("mixed", occur[0].getTerm()); checkIndex(docs, broker, null, "ed", 0); occur = checkIndex(docs, broker, null, "mixed", 1); assertEquals("mixed", occur[0].getTerm()); occur = checkIndex(docs, broker, null, "danger", 1); assertEquals("dangerous", occur[0].getTerm()); occur = checkIndex(docs, broker, null, "dangerous", 1); assertEquals("dangerous", occur[0].getTerm()); } catch (Exception e) { e.printStackTrace(); fail(e.getMessage()); } finally { pool.release(broker); } } @Test public void mixedQNameIndexes() { DocumentSet docs = configureAndStore(COLLECTION_CONFIG1, XML, "mixedIndexes.xml"); DBBroker broker = null; try { broker = pool.get(org.exist.security.SecurityManager.SYSTEM_USER); assertNotNull(broker); Occurrences[] occur = checkIndex(docs, broker, null, "aircraft", 1); assertEquals("aircraft", occur[0].getTerm()); occur = checkIndex(docs, broker, null, "system", 1); assertEquals("system", occur[0].getTerm()); occur = checkIndex(docs, broker, null, "power", 1); assertEquals("power", occur[0].getTerm()); QName qn[] = { new QName("p", "", "") }; occur = checkIndex(docs, broker, qn, "mixed", 1); assertEquals("mixed", occur[0].getTerm()); occur = checkIndex(docs, broker, qn, "dangerous", 1); assertEquals("dangerous", occur[0].getTerm()); occur = checkIndex(docs, broker, qn, "content", 1); assertEquals("content", occur[0].getTerm()); qn[0] = new QName("content", "", ""); occur = checkIndex(docs, broker, qn, "aircraft", 1); assertEquals("aircraft", occur[0].getTerm()); occur = checkIndex(docs, broker, qn, "hydraulic", 1); assertEquals("hydraulic", occur[0].getTerm()); // not a mixed-content index checkIndex(docs, broker, qn, "dangerous", 0); occur = checkIndex(docs, broker, qn, "danger", 1); assertEquals("danger", occur[0].getTerm()); occur = checkIndex(docs, broker, qn, "power", 1); assertEquals("power", occur[0].getTerm()); } catch (Exception e) { e.printStackTrace(); fail(e.getMessage()); } finally { pool.release(broker); } } @Test public void dropDocument() { DocumentSet docs = configureAndStore(COLLECTION_CONFIG1, XML, "dropDocument.xml"); DBBroker broker = null; TransactionManager transact = null; Txn transaction = null; try { broker = pool.get(org.exist.security.SecurityManager.SYSTEM_USER); assertNotNull(broker); transact = pool.getTransactionManager(); assertNotNull(transact); transaction = transact.beginTransaction(); assertNotNull(transaction); System.out.println("Removing document dropDocument.xml"); root.removeXMLResource(transaction, broker, XmldbURI.create("dropDocument.xml")); transact.commit(transaction); checkIndex(docs, broker, null, null, 0); QName qn[] = { new QName("p", "", "") }; checkIndex(docs, broker, qn, null, 0); qn[0] = new QName("content", "", ""); checkIndex(docs, broker, qn, null, 0); checkIndex(docs, broker, null, null, 0); transact.commit(transaction); } catch (Exception e) { transact.abort(transaction); e.printStackTrace(); fail(e.getMessage()); } finally { pool.release(broker); } } @Test public void reindex() { DocumentSet docs = configureAndStore(COLLECTION_CONFIG1, XML, "dropDocument.xml"); DBBroker broker = null; try { broker = pool.get(org.exist.security.SecurityManager.SYSTEM_USER); assertNotNull(broker); broker.reindexCollection(TestConstants.TEST_COLLECTION_URI); TextSearchEngine engine = broker.getTextEngine(); if(engine==null){ fail("The old FT index has been switched off by default"); } Occurrences[] occur = engine.scanIndexTerms(docs, docs.docsToNodeSet(), "o", "ox"); printOccurrences("o, ox", occur); assertEquals(2, occur.length); assertEquals("of", occur[0].getTerm()); assertEquals("on", occur[1].getTerm()); occur = checkIndex(docs, broker, null, "power", 1); assertEquals("power", occur[0].getTerm()); QName qn[] = { new QName("p", "", "") }; checkIndex(docs, broker, qn, "mixed", 1); } catch (Exception e) { e.printStackTrace(); fail(e.getMessage()); } finally { pool.release(broker); } } /** * Remove nodes from different levels of the tree and check if the index is * correctly updated. */ @Test public void xupdateRemove() { DocumentSet docs = configureAndStore(COLLECTION_CONFIG2, XML1, "xupdate.xml"); DBBroker broker = null; TransactionManager transact = null; Txn transaction = null; try { broker = pool.get(SecurityManager.SYSTEM_USER); transact = pool.getTransactionManager(); transaction = transact.beginTransaction(); Occurrences occur[] = checkIndex(docs, broker, QNDESC, "chair", 1); assertEquals("chair", occur[0].getTerm()); checkIndex(docs, broker, QNITEM, null, 5); XQuery xquery = broker.getXQueryService(); assertNotNull(xquery); Sequence seq = xquery.execute("//item[description &= 'chair']", null, AccessContext.TEST); assertNotNull(seq); assertEquals(1, seq.getItemCount()); XUpdateProcessor proc = new XUpdateProcessor(broker, docs, AccessContext.TEST); assertNotNull(proc); proc.setBroker(broker); proc.setDocumentSet(docs); String xupdate = XUPDATE_START + " <xu:remove select=\"//item[@id='2']/price\"/>" + XUPDATE_END; Modification[] modifications = proc.parse(new InputSource(new StringReader(xupdate))); assertNotNull(modifications); modifications[0].process(transaction); proc.reset(); checkIndex(docs, broker, QNPRICE, null, 1); checkIndex(docs, broker, QNITEM, null, 4); checkIndex(docs, broker, QNPRICE, "892", 0); checkIndex(docs, broker, QNITEM, "892", 0); Occurrences o[] = checkIndex(docs, broker, QNDESC, "table", 1); assertEquals("table", o[0].getTerm()); o = checkIndex(docs, broker, QNDESC, "cabinet", 1); assertEquals("cabinet", o[0].getTerm()); o = checkIndex(docs, broker, QNITEM, "table", 1); assertEquals("table", o[0].getTerm()); o = checkIndex(docs, broker, QNITEM, "cabinet", 1); assertEquals("cabinet", o[0].getTerm()); proc.setBroker(broker); proc.setDocumentSet(docs); xupdate = XUPDATE_START + " <xu:remove select=\"//item[@id='3']/description/text()\"/>" + XUPDATE_END; modifications = proc.parse(new InputSource(new StringReader(xupdate))); assertNotNull(modifications); modifications[0].process(transaction); proc.reset(); checkIndex(docs, broker, QNDESC, null, 2); checkIndex(docs, broker, QNITEM, null, 3); checkIndex(docs, broker, QNDESC, "cabinet", 0); checkIndex(docs, broker, QNITEM, "cabinet", 0); o = checkIndex(docs, broker, QNPRICE, "1525.00", 1); assertEquals("1525.00", o[0].getTerm()); o = checkIndex(docs, broker, QNITEM, "1525.00", 1); assertEquals("1525.00", o[0].getTerm()); proc.setBroker(broker); proc.setDocumentSet(docs); xupdate = XUPDATE_START + " <xu:remove select=\"//item[@id='1']/@attr\"/>" + XUPDATE_END; modifications = proc.parse(new InputSource(new StringReader(xupdate))); assertNotNull(modifications); modifications[0].process(transaction); proc.reset(); QName qnattr[] = { new QName("attr", "", "") }; qnattr[0].setNameType(ElementValue.ATTRIBUTE); checkIndex(docs, broker, qnattr, null, 0); proc.setBroker(broker); proc.setDocumentSet(docs); xupdate = XUPDATE_START + " <xu:remove select=\"//item[@id='1']\"/>" + XUPDATE_END; modifications = proc.parse(new InputSource(new StringReader(xupdate))); assertNotNull(modifications); modifications[0].process(transaction); proc.reset(); o = checkIndex(docs, broker, QNDESC, null, 1); assertEquals("table", o[0].getTerm()); checkIndex(docs, broker, QNDESC, "chair", 0); checkIndex(docs, broker, QNITEM, null, 2); assertEquals("table", o[0].getTerm()); transact.commit(transaction); } catch (Exception e) { transact.abort(transaction); e.printStackTrace(); fail(e.getMessage()); } finally { if (pool != null) { pool.release(broker); } } } /** * Remove nodes from different levels of the tree and check if the index is * correctly updated. */ @Test public void xupdateInsert() { DocumentSet docs = configureAndStore(COLLECTION_CONFIG2, XML1, "xupdate.xml"); DBBroker broker = null; TransactionManager transact = null; Txn transaction = null; try { broker = pool.get(SecurityManager.SYSTEM_USER); transact = pool.getTransactionManager(); transaction = transact.beginTransaction(); Occurrences occur[] = checkIndex(docs, broker, QNDESC, "chair", 1); assertEquals("chair", occur[0].getTerm()); checkIndex(docs, broker, QNITEM, null, 5); XQuery xquery = broker.getXQueryService(); assertNotNull(xquery); Sequence seq = xquery.execute("//item[description &= 'chair']", null, AccessContext.TEST); assertNotNull(seq); assertEquals(1, seq.getItemCount()); // Append to root node XUpdateProcessor proc = new XUpdateProcessor(broker, docs, AccessContext.TEST); assertNotNull(proc); proc.setBroker(broker); proc.setDocumentSet(docs); String xupdate = XUPDATE_START + " <xu:append select=\"/test\">" + " <item id='4'><description>Armchair</description><price>340</price></item>" + " </xu:append>" + XUPDATE_END; Modification[] modifications = proc.parse(new InputSource(new StringReader(xupdate))); assertNotNull(modifications); modifications[0].process(transaction); proc.reset(); checkIndex(docs, broker, QNPRICE, null, 3); checkIndex(docs, broker, QNDESC, null, 4); checkIndex(docs, broker, QNITEM, null, 7); Occurrences o[] = checkIndex(docs, broker, QNPRICE, "340", 1); assertEquals("340", o[0].getTerm()); o = checkIndex(docs, broker, QNDESC, "armchair", 1); assertEquals("armchair", o[0].getTerm()); o = checkIndex(docs, broker, QNITEM, "340", 1); assertEquals("340", o[0].getTerm()); o = checkIndex(docs, broker, QNITEM, "armchair", 1); assertEquals("armchair", o[0].getTerm()); // Insert before top element proc.setBroker(broker); proc.setDocumentSet(docs); xupdate = XUPDATE_START + " <xu:insert-before select=\"//item[@id = '1']\">" + " <item id='0'><description>Wheelchair</description><price>1230</price></item>" + " </xu:insert-before>" + XUPDATE_END; modifications = proc.parse(new InputSource(new StringReader(xupdate))); assertNotNull(modifications); modifications[0].process(transaction); proc.reset(); checkIndex(docs, broker, QNPRICE, null, 4); checkIndex(docs, broker, QNDESC, null, 5); checkIndex(docs, broker, QNITEM, null, 9); o = checkIndex(docs, broker, QNPRICE, "1230", 1); assertEquals("1230", o[0].getTerm()); o = checkIndex(docs, broker, QNDESC, "wheelchair", 1); assertEquals("wheelchair", o[0].getTerm()); o = checkIndex(docs, broker, QNITEM, "1230", 1); assertEquals("1230", o[0].getTerm()); o = checkIndex(docs, broker, QNITEM, "wheelchair", 1); assertEquals("wheelchair", o[0].getTerm()); // Insert after element proc.setBroker(broker); proc.setDocumentSet(docs); xupdate = XUPDATE_START + " <xu:insert-after select=\"//item[@id = '1']\">" + " <item id='1.1'><description>refrigerator</description><price>777</price></item>" + " </xu:insert-after>" + XUPDATE_END; modifications = proc.parse(new InputSource(new StringReader(xupdate))); assertNotNull(modifications); modifications[0].process(transaction); proc.reset(); checkIndex(docs, broker, QNPRICE, null, 5); checkIndex(docs, broker, QNDESC, null, 6); checkIndex(docs, broker, QNITEM, null, 11); o = checkIndex(docs, broker, QNPRICE, "777", 1); assertEquals("777", o[0].getTerm()); o = checkIndex(docs, broker, QNDESC, "refrigerator", 1); assertEquals("refrigerator", o[0].getTerm()); o = checkIndex(docs, broker, QNITEM, "777", 1); assertEquals("777", o[0].getTerm()); o = checkIndex(docs, broker, QNITEM, "refrigerator", 1); assertEquals("refrigerator", o[0].getTerm()); proc.setBroker(broker); proc.setDocumentSet(docs); xupdate = XUPDATE_START + " <xu:insert-after select=\"//item[@id = '1']/description\">" + " <price>999</price>" + " </xu:insert-after>" + XUPDATE_END; modifications = proc.parse(new InputSource(new StringReader(xupdate))); assertNotNull(modifications); modifications[0].process(transaction); proc.reset(); checkIndex(docs, broker, QNPRICE, null, 6); checkIndex(docs, broker, QNITEM, null, 12); o = checkIndex(docs, broker, QNPRICE, "999", 1); assertEquals("999", o[0].getTerm()); o = checkIndex(docs, broker, QNITEM, "999", 1); assertEquals("999", o[0].getTerm()); // Insert before nested element proc.setBroker(broker); proc.setDocumentSet(docs); xupdate = XUPDATE_START + " <xu:insert-before select=\"//item[@id = '1']/description\">" + " <price>888</price>" + " </xu:insert-before>" + XUPDATE_END; modifications = proc.parse(new InputSource(new StringReader(xupdate))); assertNotNull(modifications); modifications[0].process(transaction); proc.reset(); checkIndex(docs, broker, QNPRICE, null, 7); checkIndex(docs, broker, QNITEM, null, 13); o = checkIndex(docs, broker, QNPRICE, "999", 1); assertEquals("999", o[0].getTerm()); o = checkIndex(docs, broker, QNPRICE, "888", 1); assertEquals("888", o[0].getTerm()); o = checkIndex(docs, broker, QNITEM, "999", 1); assertEquals("999", o[0].getTerm()); o = checkIndex(docs, broker, QNITEM, "888", 1); assertEquals("888", o[0].getTerm()); // Overwrite attribute proc.setBroker(broker); proc.setDocumentSet(docs); xupdate = XUPDATE_START + " <xu:append select=\"//item[@id = '1']\">" + " <xu:attribute name=\"attr\">abc</xu:attribute>" + " </xu:append>" + XUPDATE_END; modifications = proc.parse(new InputSource(new StringReader(xupdate))); assertNotNull(modifications); modifications[0].process(transaction); proc.reset(); QName qnattr[] = { new QName("attr", "", "") }; qnattr[0].setNameType(ElementValue.ATTRIBUTE); o = checkIndex(docs, broker, qnattr, null, 1); assertEquals("abc", o[0].getTerm()); checkIndex(docs, broker, qnattr, "attribute", 0); transact.commit(transaction); } catch (Exception e) { transact.abort(transaction); e.printStackTrace(); fail(e.getMessage()); } finally { if (pool != null) { pool.release(broker); } } } @Test public void xupdateUpdate() { DocumentSet docs = configureAndStore(COLLECTION_CONFIG2, XML1, "xupdate.xml"); DBBroker broker = null; TransactionManager transact = null; Txn transaction = null; try { broker = pool.get(org.exist.security.SecurityManager.SYSTEM_USER); transact = pool.getTransactionManager(); transaction = transact.beginTransaction(); Occurrences occur[] = checkIndex(docs, broker, QNDESC, "chair", 1); assertEquals("chair", occur[0].getTerm()); checkIndex(docs, broker, QNITEM, null, 5); XQuery xquery = broker.getXQueryService(); assertNotNull(xquery); Sequence seq = xquery.execute("//item[description &= 'chair']", null, AccessContext.TEST); assertNotNull(seq); assertEquals(1, seq.getItemCount()); // Update element content XUpdateProcessor proc = new XUpdateProcessor(broker, docs, AccessContext.TEST); assertNotNull(proc); proc.setBroker(broker); proc.setDocumentSet(docs); String xupdate = XUPDATE_START + " <xu:update select=\"//item[@id = '1']/description\">wardrobe</xu:update>" + XUPDATE_END; Modification[] modifications = proc.parse(new InputSource(new StringReader(xupdate))); assertNotNull(modifications); modifications[0].process(transaction); proc.reset(); checkIndex(docs, broker, QNDESC, null, 3); checkIndex(docs, broker, QNITEM, null, 5); checkIndex(docs, broker, QNDESC, "chair", 0); checkIndex(docs, broker, QNITEM, "chair", 0); Occurrences o[] = checkIndex(docs, broker, QNDESC, "wardrobe", 1); assertEquals("wardrobe", o[0].getTerm()); o = checkIndex(docs, broker, QNITEM, "wardrobe", 1); assertEquals("wardrobe", o[0].getTerm()); // Update text node proc.setBroker(broker); proc.setDocumentSet(docs); xupdate = XUPDATE_START + " <xu:update select=\"//item[@id = '1']/description/text()\">Wheelchair</xu:update>" + XUPDATE_END; modifications = proc.parse(new InputSource(new StringReader(xupdate))); assertNotNull(modifications); modifications[0].process(transaction); proc.reset(); checkIndex(docs, broker, QNDESC, null, 3); checkIndex(docs, broker, QNITEM, null, 5); checkIndex(docs, broker, QNDESC, "wardrobe", 0); checkIndex(docs, broker, QNITEM, "wardrobe", 0); o = checkIndex(docs, broker, QNDESC, "wheelchair", 1); assertEquals("wheelchair", o[0].getTerm()); o = checkIndex(docs, broker, QNITEM, "wheelchair", 1); assertEquals("wheelchair", o[0].getTerm()); // Update attribute value proc.setBroker(broker); proc.setDocumentSet(docs); xupdate = XUPDATE_START + " <xu:update select=\"//item[@id = '1']/@attr\">abc</xu:update>" + XUPDATE_END; modifications = proc.parse(new InputSource(new StringReader(xupdate))); assertNotNull(modifications); modifications[0].process(transaction); proc.reset(); QName qnattr[] = { new QName("attr", "", "") }; qnattr[0].setNameType(ElementValue.ATTRIBUTE); o = checkIndex(docs, broker, qnattr, null, 1); assertEquals("abc", o[0].getTerm()); checkIndex(docs, broker, qnattr, "attribute", 0); transact.commit(transaction); } catch (Exception e) { transact.abort(transaction); e.printStackTrace(); fail(e.getMessage()); } finally { if (pool != null) { pool.release(broker); } } } @Test public void xupdateReplace() { DocumentSet docs = configureAndStore(COLLECTION_CONFIG2, XML1, "xupdate.xml"); DBBroker broker = null; TransactionManager transact = null; Txn transaction = null; try { broker = pool.get(SecurityManager.SYSTEM_USER); transact = pool.getTransactionManager(); transaction = transact.beginTransaction(); Occurrences occur[] = checkIndex(docs, broker, QNDESC, "chair", 1); assertEquals("chair", occur[0].getTerm()); checkIndex(docs, broker, QNITEM, null, 5); XQuery xquery = broker.getXQueryService(); assertNotNull(xquery); Sequence seq = xquery.execute("//item[description &= 'chair']", null, AccessContext.TEST); assertNotNull(seq); assertEquals(1, seq.getItemCount()); XUpdateProcessor proc = new XUpdateProcessor(broker, docs, AccessContext.TEST); assertNotNull(proc); proc.setBroker(broker); proc.setDocumentSet(docs); String xupdate = XUPDATE_START + " <xu:replace select=\"//item[@id = '1']\">" + " <item id='4'><description>Wheelchair</description><price>809.50</price></item>" + " </xu:replace>" + XUPDATE_END; Modification[] modifications = proc.parse(new InputSource(new StringReader(xupdate))); assertNotNull(modifications); modifications[0].process(transaction); proc.reset(); checkIndex(docs, broker, QNDESC, null, 3); checkIndex(docs, broker, QNPRICE, null, 3); checkIndex(docs, broker, QNITEM, null, 6); checkIndex(docs, broker, QNDESC, "chair", 0); checkIndex(docs, broker, QNITEM, "chair", 0); Occurrences o[] = checkIndex(docs, broker, QNDESC, "wheelchair", 1); assertEquals("wheelchair", o[0].getTerm()); o = checkIndex(docs, broker, QNPRICE, "809.50", 1); assertEquals("809.50", o[0].getTerm()); o = checkIndex(docs, broker, QNITEM, "wheelchair", 1); assertEquals("wheelchair", o[0].getTerm()); o = checkIndex(docs, broker, QNITEM, "809.50", 1); assertEquals("809.50", o[0].getTerm()); proc.setBroker(broker); proc.setDocumentSet(docs); xupdate = XUPDATE_START + " <xu:replace select=\"//item[@id = '4']/description\">" + " <description>Armchair</description>" + " </xu:replace>" + XUPDATE_END; modifications = proc.parse(new InputSource(new StringReader(xupdate))); assertNotNull(modifications); modifications[0].process(transaction); proc.reset(); checkIndex(docs, broker, QNDESC, null, 3); checkIndex(docs, broker, QNITEM, null, 6); checkIndex(docs, broker, QNDESC, "wheelchair", 0); o = checkIndex(docs, broker, QNDESC, "armchair", 1); assertEquals("armchair", o[0].getTerm()); checkIndex(docs, broker, QNITEM, "wheelchair", 0); o = checkIndex(docs, broker, QNITEM, "armchair", 1); assertEquals("armchair", o[0].getTerm()); transact.commit(transaction); } catch (Exception e) { transact.abort(transaction); e.printStackTrace(); fail(e.getMessage()); } finally { if (pool != null) { pool.release(broker); } } } @Test public void xupdateRename() { DocumentSet docs = configureAndStore(COLLECTION_CONFIG2, XML1, "xupdate.xml"); DBBroker broker = null; TransactionManager transact = null; Txn transaction = null; try { broker = pool.get(SecurityManager.SYSTEM_USER); transact = pool.getTransactionManager(); transaction = transact.beginTransaction(); Occurrences occur[] = checkIndex(docs, broker, QNDESC, "chair", 1); assertEquals("chair", occur[0].getTerm()); checkIndex(docs, broker, QNITEM, null, 5); XQuery xquery = broker.getXQueryService(); assertNotNull(xquery); Sequence seq = xquery.execute("//item[description &= 'chair']", null, AccessContext.TEST); assertNotNull(seq); assertEquals(1, seq.getItemCount()); XUpdateProcessor proc = new XUpdateProcessor(broker, docs, AccessContext.TEST); assertNotNull(proc); proc.setBroker(broker); proc.setDocumentSet(docs); String xupdate = XUPDATE_START + " <xu:rename select=\"//item[@id='2']\">renamed</xu:rename>" + XUPDATE_END; Modification[] modifications = proc.parse(new InputSource(new StringReader(xupdate))); assertNotNull(modifications); modifications[0].process(transaction); proc.reset(); checkIndex(docs, broker, QNDESC, null, 3); checkIndex(docs, broker, QNPRICE, null, 2); checkIndex(docs, broker, QNITEM, null, 3); Occurrences o[] = checkIndex(docs, broker, QNDESC, "table", 1); assertEquals("table", o[0].getTerm()); checkIndex(docs, broker, QNITEM, "table", 0); transact.commit(transaction); } catch (Exception e) { transact.abort(transaction); e.printStackTrace(); fail(e.getMessage()); } finally { if (pool != null) { pool.release(broker); } } } private Occurrences[] checkIndex(DocumentSet docs, DBBroker broker, QName[] qn, String term, int expected) throws PermissionDeniedException { TextSearchEngine engine = broker.getTextEngine(); if(engine==null) fail("old FullText has been switched off by default"); Occurrences[] occur; if (qn == null) occur = engine.scanIndexTerms(docs, docs.docsToNodeSet(), term, null); else occur = engine.scanIndexTerms(docs, docs.docsToNodeSet(), qn, term, null); printOccurrences(term, occur); assertEquals(expected, occur.length); return occur; } private void printOccurrences(String msg, Occurrences[] occur) { StringBuilder buf = new StringBuilder(); if (msg != null) buf.append(msg).append(": "); for (int i = 0; i < occur.length; i++) { Occurrences occurrences = occur[i]; if (i > 0) buf.append(", "); buf.append(occurrences.getTerm()).append(":\t").append(occurrences.getOccurrences()); } System.out.println(buf.toString()); } private DocumentSet configureAndStore(String configuration, String data, String docName) { DBBroker broker = null; TransactionManager transact = null; Txn transaction = null; MutableDocumentSet docs = new DefaultDocumentSet(); try { broker = pool.get(org.exist.security.SecurityManager.SYSTEM_USER); assertNotNull(broker); transact = pool.getTransactionManager(); assertNotNull(transact); transaction = transact.beginTransaction(); assertNotNull(transaction); if (configuration != null) { CollectionConfigurationManager mgr = pool.getConfigurationManager(); mgr.addConfiguration(transaction, broker, root, configuration); } IndexInfo info = root.validateXMLResource(transaction, broker, XmldbURI.create(docName), data); assertNotNull(info); root.store(transaction, broker, info, data, false); docs.add(info.getDocument()); transact.commit(transaction); } catch (Exception e) { e.printStackTrace(); transact.abort(transaction); fail(e.getMessage()); } finally { pool.release(broker); } return docs; } @Before public void setup() { DBBroker broker = null; TransactionManager transact = null; Txn transaction = null; try { broker = pool.get(org.exist.security.SecurityManager.SYSTEM_USER); assertNotNull(broker); transact = pool.getTransactionManager(); assertNotNull(transact); transaction = transact.beginTransaction(); assertNotNull(transaction); System.out.println("Transaction started ..."); root = broker.getOrCreateCollection(transaction, TestConstants.TEST_COLLECTION_URI); assertNotNull(root); broker.saveCollection(transaction, root); transact.commit(transaction); } catch (Exception e) { e.printStackTrace(); transact.abort(transaction); fail(e.getMessage()); } finally { if (pool != null) pool.release(broker); } } @After public void cleanup() { BrokerPool pool = null; DBBroker broker = null; TransactionManager transact = null; Txn transaction = null; try { pool = BrokerPool.getInstance(); assertNotNull(pool); broker = pool.get(org.exist.security.SecurityManager.SYSTEM_USER); assertNotNull(broker); transact = pool.getTransactionManager(); assertNotNull(transact); transaction = transact.beginTransaction(); assertNotNull(transaction); Collection config = broker.getOrCreateCollection(transaction, XmldbURI.create(CollectionConfigurationManager.CONFIG_COLLECTION + "/db")); assertNotNull(config); broker.removeCollection(transaction, config); assertNotNull(root); broker.removeCollection(transaction, root); transact.commit(transaction); } catch (Exception e) { transact.abort(transaction); e.printStackTrace(); fail(e.getMessage()); } finally { if (pool != null) pool.release(broker); } } @BeforeClass public static void startDB() { try { File confFile = ConfigurationHelper.lookup("conf.xml"); Configuration config = new Configuration(confFile.getAbsolutePath()); BrokerPool.configure(1, 5, config); pool = BrokerPool.getInstance(); assertNotNull(pool); } catch (Exception e) { e.printStackTrace(); fail(e.getMessage()); } } @AfterClass public static void stopDB() { TestUtils.cleanupDB(); BrokerPool.stopAll(false); pool = null; root = null; } }