|
From: <fg...@us...> - 2013-10-20 19:02:17
|
Revision: 4415
http://openutils.svn.sourceforge.net/openutils/?rev=4415&view=rev
Author: fgiust
Date: 2013-10-20 19:02:14 +0000 (Sun, 20 Oct 2013)
Log Message:
-----------
upgrade tagcloud to jackrabbit 2.&/lucene 3.6 and fix test configuration
Modified Paths:
--------------
magnoliamodules/trunk/magnolia-test-webapp/pom.xml
magnoliamodules/trunk/magnolia-test-webapp/src/main/resources/log4j.xml
magnoliamodules/trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/utils/BaseAnalyzer.java
magnoliamodules/trunk/openutils-mgnlcriteria/src/test/resources/log4j.xml
magnoliamodules/trunk/openutils-mgnltagcloud/pom.xml
Added Paths:
-----------
magnoliamodules/trunk/magnolia-test-webapp/src/main/java/com/
magnoliamodules/trunk/magnolia-test-webapp/src/main/java/com/browseengine/
magnoliamodules/trunk/magnolia-test-webapp/src/main/java/com/browseengine/bobo/
magnoliamodules/trunk/magnolia-test-webapp/src/main/java/com/browseengine/bobo/api/
magnoliamodules/trunk/magnolia-test-webapp/src/main/java/com/browseengine/bobo/api/BoboIndexReader.java
magnoliamodules/trunk/magnolia-test-webapp/src/main/webapp/templates/samples-lms/
magnoliamodules/trunk/magnolia-test-webapp/src/main/webapp/templates/samples-lms/courses.jsp
magnoliamodules/trunk/magnolia-test-webapp/src/main/webapp/templates/samples-lms/index.jsp
magnoliamodules/trunk/openutils-mgnltagcloud/src/test/java/com/
magnoliamodules/trunk/openutils-mgnltagcloud/src/test/java/com/browseengine/
magnoliamodules/trunk/openutils-mgnltagcloud/src/test/java/com/browseengine/bobo/
magnoliamodules/trunk/openutils-mgnltagcloud/src/test/java/com/browseengine/bobo/api/
magnoliamodules/trunk/openutils-mgnltagcloud/src/test/java/com/browseengine/bobo/api/BoboIndexReader.java
Modified: magnoliamodules/trunk/magnolia-test-webapp/pom.xml
===================================================================
--- magnoliamodules/trunk/magnolia-test-webapp/pom.xml 2013-10-20 18:52:41 UTC (rev 4414)
+++ magnoliamodules/trunk/magnolia-test-webapp/pom.xml 2013-10-20 19:02:14 UTC (rev 4415)
@@ -218,6 +218,17 @@
<artifactId>openutils-mgnllms</artifactId>
<version>5.0.10-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>2.5.5</version><!-- temporarily used for bobo-browse patch -->
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
</dependencies>
<dependencyManagement>
<dependencies>
Added: magnoliamodules/trunk/magnolia-test-webapp/src/main/java/com/browseengine/bobo/api/BoboIndexReader.java
===================================================================
--- magnoliamodules/trunk/magnolia-test-webapp/src/main/java/com/browseengine/bobo/api/BoboIndexReader.java (rev 0)
+++ magnoliamodules/trunk/magnolia-test-webapp/src/main/java/com/browseengine/bobo/api/BoboIndexReader.java 2013-10-20 19:02:14 UTC (rev 4415)
@@ -0,0 +1,914 @@
+/**
+ *
+ * Tagcloud module for Magnolia CMS (http://www.openmindlab.com/lab/products/mgnltagcloud.html)
+ * Copyright(C) 2010-2013, Openmind S.r.l. http://www.openmindonline.it
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// lucene 3.6 compatibility patch for bobo-browse 3.2.0, see https://github.com/senseidb/bobo/commit/e78d91ef8a00965d8d55c819f967cac172c23d17
+/**
+ * Bobo Browse Engine - High performance faceted/parametric search implementation
+ * that handles various types of semi-structured data. Written in Java.
+ *
+ * Copyright (C) 2005-2006 John Wang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * To contact the project administrators for the bobo-browse project,
+ * please go to https://sourceforge.net/projects/bobo-browse/, or
+ * send mail to ow...@br....
+ */
+
+package com.browseengine.bobo.api;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import org.apache.log4j.Logger;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.index.CorruptIndexException;
+import org.apache.lucene.index.FilterIndexReader;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.MultiReader;
+import org.apache.lucene.index.SegmentInfo;
+import org.apache.lucene.index.SegmentInfos;
+import org.apache.lucene.index.SegmentReader;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.index.TermEnum;
+import org.apache.lucene.search.MatchAllDocsQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.FSDirectory;
+import org.apache.lucene.util.ReaderUtil;
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+import org.springframework.context.support.GenericApplicationContext;
+
+import com.browseengine.bobo.facets.FacetHandler;
+import com.browseengine.bobo.facets.RuntimeFacetHandler;
+import com.browseengine.bobo.facets.RuntimeFacetHandlerFactory;
+
+
+/**
+ * bobo browse index reader
+ */
+public class BoboIndexReader extends FilterIndexReader
+{
+
+ private static final String SPRING_CONFIG = "bobo.spring";
+
+ private static Logger logger = Logger.getLogger(BoboIndexReader.class);
+
+ protected Map<String, FacetHandler< ? >> _facetHandlerMap;
+
+ protected Collection<FacetHandler< ? >> _facetHandlers;
+
+ protected Collection<RuntimeFacetHandlerFactory< ? , ? >> _runtimeFacetHandlerFactories;
+
+ protected Map<String, RuntimeFacetHandlerFactory< ? , ? >> _runtimeFacetHandlerFactoryMap;
+
+ protected WorkArea _workArea;
+
+ protected IndexReader _srcReader;
+
+ protected BoboIndexReader[] _subReaders = null;
+
+ protected int[] _starts = null;
+
+ private Directory _dir = null;
+
+ private final Map<String, Object> _facetDataMap = new HashMap<String, Object>();
+
+ private final ThreadLocal<Map<String, Object>> _runtimeFacetDataMap = new ThreadLocal<Map<String, Object>>()
+ {
+
+ protected Map<String, Object> initialValue()
+ {
+ return new HashMap<String, Object>();
+ }
+ };
+
+ private final ThreadLocal<Map<String, RuntimeFacetHandler< ? >>> _runtimeFacetHandlerMap = new ThreadLocal<Map<String, RuntimeFacetHandler< ? >>>()
+ {
+
+ protected Map<String, RuntimeFacetHandler< ? >> initialValue()
+ {
+ return new HashMap<String, RuntimeFacetHandler< ? >>();
+ }
+ };
+
+ /**
+ * Constructor
+ * @param reader Index reader
+ * @throws IOException
+ */
+ public static BoboIndexReader getInstance(IndexReader reader) throws IOException
+ {
+ return BoboIndexReader.getInstance(reader, null, null, new WorkArea());
+ }
+
+ public static BoboIndexReader getInstance(IndexReader reader, WorkArea workArea) throws IOException
+ {
+ return BoboIndexReader.getInstance(reader, null, null, workArea);
+ }
+
+ /**
+ * Constructor.
+ * @param reader index reader
+ * @param facetHandlers List of facet handlers
+ * @throws IOException
+ */
+ public static BoboIndexReader getInstance(IndexReader reader, Collection<FacetHandler< ? >> facetHandlers,
+ Collection<RuntimeFacetHandlerFactory< ? , ? >> facetHandlerFactories) throws IOException
+ {
+ return BoboIndexReader.getInstance(reader, facetHandlers, facetHandlerFactories, new WorkArea());
+ }
+
+ public static BoboIndexReader getInstance(IndexReader reader, Collection<FacetHandler< ? >> facetHandlers)
+ throws IOException
+ {
+ return BoboIndexReader.getInstance(reader, facetHandlers, Collections.EMPTY_LIST, new WorkArea());
+ }
+
+ public static BoboIndexReader getInstance(IndexReader reader, Collection<FacetHandler< ? >> facetHandlers,
+ Collection<RuntimeFacetHandlerFactory< ? , ? >> facetHandlerFactories, WorkArea workArea) throws IOException
+ {
+ BoboIndexReader boboReader = new BoboIndexReader(reader, facetHandlers, facetHandlerFactories, workArea);
+ boboReader.facetInit();
+ return boboReader;
+ }
+
+ public static BoboIndexReader getInstanceAsSubReader(IndexReader reader) throws IOException
+ {
+ return getInstanceAsSubReader(reader, null, null, new WorkArea());
+ }
+
+ public static BoboIndexReader getInstanceAsSubReader(IndexReader reader,
+ Collection<FacetHandler< ? >> facetHandlers,
+ Collection<RuntimeFacetHandlerFactory< ? , ? >> facetHandlerFactories) throws IOException
+ {
+ return getInstanceAsSubReader(reader, facetHandlers, facetHandlerFactories, new WorkArea());
+ }
+
+ public static BoboIndexReader getInstanceAsSubReader(IndexReader reader,
+ Collection<FacetHandler< ? >> facetHandlers,
+ Collection<RuntimeFacetHandlerFactory< ? , ? >> facetHandlerFactories, WorkArea workArea) throws IOException
+ {
+ BoboIndexReader boboReader = new BoboIndexReader(reader, facetHandlers, facetHandlerFactories, workArea, false);
+ boboReader.facetInit();
+ return boboReader;
+ }
+
+ @Override
+ public long getVersion()
+ {
+ try
+ {
+ SegmentInfos sinfos = new SegmentInfos();
+ sinfos.read(_dir);
+ return sinfos.getVersion();
+ }
+ catch (Exception e)
+ {
+ return 0L;
+ }
+ }
+
+ public IndexReader getInnerReader()
+ {
+ return in;
+ }
+
+ @Override
+ public synchronized IndexReader reopen() throws CorruptIndexException, IOException
+ {
+ IndexReader newInner = null;
+
+ SegmentInfos sinfos = new SegmentInfos();
+ sinfos.read(_dir);
+ int size = sinfos.size();
+
+ if (in instanceof MultiReader)
+ {
+ // setup current reader list
+ List<IndexReader> boboReaderList = new LinkedList<IndexReader>();
+ ReaderUtil.gatherSubReaders((List<IndexReader>) boboReaderList, in);
+ Map<String, BoboIndexReader> readerMap = new HashMap<String, BoboIndexReader>();
+ for (IndexReader reader : boboReaderList)
+ {
+ BoboIndexReader boboReader = (BoboIndexReader) reader;
+ SegmentReader sreader = (SegmentReader) (boboReader.in);
+ readerMap.put(sreader.getSegmentName(), boboReader);
+ }
+
+ ArrayList<BoboIndexReader> currentReaders = new ArrayList<BoboIndexReader>(size);
+ boolean isNewReader = false;
+ for (int i = 0; i < size; ++i)
+ {
+ SegmentInfo sinfo = (SegmentInfo) sinfos.info(i);
+ BoboIndexReader breader = readerMap.remove(sinfo.name);
+ if (breader != null)
+ {
+ // should use SegmentReader.reopen
+ // TODO: see LUCENE-2559
+ BoboIndexReader newReader = (BoboIndexReader) breader.reopen(true);
+ if (newReader != breader)
+ {
+ isNewReader = true;
+ }
+ if (newReader != null)
+ {
+ currentReaders.add(newReader);
+ }
+ }
+ else
+ {
+ isNewReader = true;
+ SegmentReader newSreader = SegmentReader.get(true, sinfo, 1);
+ breader = BoboIndexReader.getInstanceAsSubReader(
+ newSreader,
+ this._facetHandlers,
+ this._runtimeFacetHandlerFactories);
+ breader._dir = _dir;
+ currentReaders.add(breader);
+ }
+ }
+ isNewReader = isNewReader || (readerMap.size() != 0);
+ if (!isNewReader)
+ {
+ return this;
+ }
+ else
+ {
+ MultiReader newMreader = new MultiReader(currentReaders.toArray(new BoboIndexReader[currentReaders
+ .size()]), false);
+ BoboIndexReader newReader = BoboIndexReader.getInstanceAsSubReader(
+ newMreader,
+ this._facetHandlers,
+ this._runtimeFacetHandlerFactories);
+ newReader._dir = _dir;
+ return newReader;
+ }
+ }
+ else if (in instanceof SegmentReader)
+ {
+ // should use SegmentReader.reopen
+ // TODO: see LUCENE-2559
+
+ SegmentReader sreader = (SegmentReader) in;
+ int numDels = sreader.numDeletedDocs();
+
+ SegmentInfo sinfo = null;
+ boolean sameSeg = false;
+ // get SegmentInfo instance
+ for (int i = 0; i < size; ++i)
+ {
+ SegmentInfo sinfoTmp = (SegmentInfo) sinfos.info(i);
+ if (sinfoTmp.name.equals(sreader.getSegmentName()))
+ {
+ int numDels2 = sinfoTmp.getDelCount();
+ sameSeg = numDels == numDels2;
+ sinfo = sinfoTmp;
+ break;
+ }
+ }
+
+ if (sinfo == null)
+ {
+ // segment no longer exists
+ return null;
+ }
+ if (sameSeg)
+ {
+ return this;
+ }
+ else
+ {
+ SegmentReader newSreader = SegmentReader.get(true, sinfo, 1);
+ return BoboIndexReader.getInstanceAsSubReader(
+ newSreader,
+ this._facetHandlers,
+ this._runtimeFacetHandlerFactories);
+ }
+ }
+ else
+ {
+ // should not reach here, a catch-all default case
+ IndexReader reader = in.reopen(true);
+ if (in != reader)
+ {
+ return BoboIndexReader.getInstance(newInner, _facetHandlers, _runtimeFacetHandlerFactories, _workArea);
+ }
+ else
+ {
+ return this;
+ }
+ }
+ }
+
+ @Override
+ public synchronized IndexReader reopen(boolean openReadOnly) throws CorruptIndexException, IOException
+ {
+
+ // bobo readers are always readonly
+ return reopen();
+ }
+
+ public Object getFacetData(String name)
+ {
+ return _facetDataMap.get(name);
+ }
+
+ public Object putFacetData(String name, Object data)
+ {
+ return _facetDataMap.put(name, data);
+ }
+
+ public Object getRuntimeFacetData(String name)
+ {
+ Map<String, Object> map = _runtimeFacetDataMap.get();
+ if (map == null)
+ return null;
+
+ return map.get(name);
+ }
+
+ public Object putRuntimeFacetData(String name, Object data)
+ {
+ Map<String, Object> map = _runtimeFacetDataMap.get();
+ if (map == null)
+ {
+ map = new HashMap<String, Object>();
+ _runtimeFacetDataMap.set(map);
+ }
+ return map.put(name, data);
+ }
+
+ public void clearRuntimeFacetData()
+ {
+ _runtimeFacetDataMap.set(null);
+ }
+
+ public RuntimeFacetHandler< ? > getRuntimeFacetHandler(String name)
+ {
+ Map<String, RuntimeFacetHandler< ? >> map = _runtimeFacetHandlerMap.get();
+ if (map == null)
+ return null;
+
+ return map.get(name);
+ }
+
+ public void putRuntimeFacetHandler(String name, RuntimeFacetHandler< ? > data)
+ {
+ Map<String, RuntimeFacetHandler< ? >> map = _runtimeFacetHandlerMap.get();
+ if (map == null)
+ {
+ map = new HashMap<String, RuntimeFacetHandler< ? >>();
+ _runtimeFacetHandlerMap.set(map);
+ }
+ map.put(name, data);
+ }
+
+ public void clearRuntimeFacetHandler()
+ {
+ _runtimeFacetHandlerMap.set(null);
+ }
+
+ @Override
+ protected void doClose() throws IOException
+ {
+ _facetDataMap.clear();
+ if (_srcReader != null)
+ _srcReader.close();
+ super.doClose();
+ }
+
+ @Override
+ protected void doCommit(Map commitUserData) throws IOException
+ {
+ if (_srcReader != null)
+ _srcReader.flush(commitUserData);
+ }
+
+ @Override
+ protected void doDelete(int n) throws CorruptIndexException, IOException
+ {
+ if (_srcReader != null)
+ _srcReader.deleteDocument(n);
+ }
+
+ private void loadFacetHandler(String name, Set<String> loaded, Set<String> visited, WorkArea workArea)
+ throws IOException
+ {
+ FacetHandler< ? > facetHandler = _facetHandlerMap.get(name);
+ if (facetHandler != null && !loaded.contains(name))
+ {
+ visited.add(name);
+ Set<String> dependsOn = facetHandler.getDependsOn();
+ if (dependsOn.size() > 0)
+ {
+ Iterator<String> iter = dependsOn.iterator();
+ while (iter.hasNext())
+ {
+ String f = iter.next();
+ if (name.equals(f))
+ continue;
+ if (!loaded.contains(f))
+ {
+ if (visited.contains(f))
+ {
+ throw new IOException("Facet handler dependency cycle detected, facet handler: "
+ + name
+ + " not loaded");
+ }
+ loadFacetHandler(f, loaded, visited, workArea);
+ }
+ if (!loaded.contains(f))
+ {
+ throw new IOException("unable to load facet handler: " + f);
+ }
+ facetHandler.putDependedFacetHandler(_facetHandlerMap.get(f));
+ }
+ }
+
+ long start = System.currentTimeMillis();
+ facetHandler.loadFacetData(this, workArea);
+ long end = System.currentTimeMillis();
+ if (logger.isDebugEnabled())
+ {
+ StringBuffer buf = new StringBuffer();
+ buf.append("facetHandler loaded: ").append(name).append(", took: ").append(end - start).append(" ms");
+ logger.debug(buf.toString());
+ }
+ loaded.add(name);
+ }
+ }
+
+ private void loadFacetHandlers(WorkArea workArea, Set<String> toBeRemoved) throws IOException
+ {
+ Set<String> loaded = new HashSet<String>();
+ Set<String> visited = new HashSet<String>();
+
+ for (String name : _facetHandlerMap.keySet())
+ {
+ loadFacetHandler(name, loaded, visited, workArea);
+ }
+
+ for (String name : toBeRemoved)
+ {
+ _facetHandlerMap.remove(name);
+ }
+ }
+
+ /**
+ * Find all the leaf sub-readers and wrap each in BoboIndexReader.
+ * @param reader
+ * @param workArea
+ * @return
+ * @throws IOException
+ */
+ private static IndexReader[] createSubReaders(IndexReader reader, WorkArea workArea) throws IOException
+ {
+ List<IndexReader> readerList = new ArrayList<IndexReader>();
+ ReaderUtil.gatherSubReaders(readerList, reader);
+ IndexReader[] subReaders = (IndexReader[]) readerList.toArray(new IndexReader[readerList.size()]);
+ BoboIndexReader[] boboReaders;
+
+ if (subReaders != null && subReaders.length > 0)
+ {
+ boboReaders = new BoboIndexReader[subReaders.length];
+ for (int i = 0; i < subReaders.length; i++)
+ {
+ boboReaders[i] = new BoboIndexReader(subReaders[i], null, null, workArea, false);
+ }
+ }
+ else
+ {
+ boboReaders = new BoboIndexReader[]{new BoboIndexReader(reader, null, null, workArea, false) };
+ }
+ return boboReaders;
+ }
+
+ @Override
+ public Directory directory()
+ {
+ return (_subReaders != null ? _subReaders[0].directory() : super.directory());
+ }
+
+ private static Collection<FacetHandler< ? >> loadFromIndex(File file, WorkArea workArea) throws IOException
+ {
+ // File springFile = new File(file, SPRING_CONFIG);
+ // FileSystemXmlApplicationContext appCtx =
+ // new FileSystemXmlApplicationContext("file:" + springFile.getAbsolutePath());
+ // return (Collection<FacetHandler<?>>) appCtx.getBean("handlers");
+
+ Set<Entry<Class< ? >, Object>> entries = workArea.map.entrySet();
+ FileSystemXmlApplicationContext appCtx = new FileSystemXmlApplicationContext();
+ for (Entry<Class< ? >, Object> entry : entries)
+ {
+ Object obj = entry.getValue();
+ if (obj instanceof ClassLoader)
+ {
+ appCtx.setClassLoader((ClassLoader) obj);
+ break;
+ }
+ }
+
+ String absolutePath = file.getAbsolutePath();
+ String partOne = absolutePath.substring(0, absolutePath.lastIndexOf(File.separator));
+ String partTwo = URLEncoder.encode(
+ absolutePath.substring(absolutePath.lastIndexOf(File.separator) + 1),
+ "UTF-8");
+ absolutePath = partOne + File.separator + partTwo;
+
+ File springFile = new File(new File(absolutePath), SPRING_CONFIG);
+ appCtx.setConfigLocation("file:" + springFile.getAbsolutePath());
+ appCtx.refresh();
+
+ return (Collection<FacetHandler< ? >>) appCtx.getBean("handlers");
+
+ }
+
+ protected void initialize(Collection<FacetHandler< ? >> facetHandlers) throws IOException
+ {
+ if (facetHandlers == null) // try to load from index
+ {
+ Directory idxDir = directory();
+ if (idxDir != null && idxDir instanceof FSDirectory)
+ {
+ FSDirectory fsDir = (FSDirectory) idxDir;
+ File file = fsDir.getFile();
+
+ if (new File(file, SPRING_CONFIG).exists())
+ {
+ facetHandlers = loadFromIndex(file, _workArea);
+ }
+ else
+ {
+ facetHandlers = new ArrayList<FacetHandler< ? >>();
+ }
+ }
+ else
+ {
+ facetHandlers = new ArrayList<FacetHandler< ? >>();
+ }
+ }
+
+ _facetHandlers = facetHandlers;
+ _facetHandlerMap = new HashMap<String, FacetHandler< ? >>();
+ for (FacetHandler< ? > facetHandler : facetHandlers)
+ {
+ _facetHandlerMap.put(facetHandler.getName(), facetHandler);
+ }
+ }
+
+ /**
+ * @param reader
+ * @param facetHandlers
+ * @param facetHandlerFactories
+ * @param workArea
+ * @throws IOException
+ */
+ protected BoboIndexReader(
+ IndexReader reader,
+ Collection<FacetHandler< ? >> facetHandlers,
+ Collection<RuntimeFacetHandlerFactory< ? , ? >> facetHandlerFactories,
+ WorkArea workArea) throws IOException
+ {
+ this(reader, facetHandlers, facetHandlerFactories, workArea, true);
+ _srcReader = reader;
+ }
+
+ /**
+ * @param reader
+ * @param facetHandlers
+ * @param facetHandlerFactories
+ * @param workArea
+ * @param useSubReaders true => we create a MultiReader of all the leaf sub-readers as the inner reader. false => we
+ * use the given reader as the inner reader.
+ * @throws IOException
+ */
+ protected BoboIndexReader(
+ IndexReader reader,
+ Collection<FacetHandler< ? >> facetHandlers,
+ Collection<RuntimeFacetHandlerFactory< ? , ? >> facetHandlerFactories,
+ WorkArea workArea,
+ boolean useSubReaders) throws IOException
+ {
+ super(useSubReaders ? new MultiReader(createSubReaders(reader, workArea), false) : reader);
+ if (useSubReaders)
+ {
+ _dir = reader.directory();
+ BoboIndexReader[] subReaders = (BoboIndexReader[]) in.getSequentialSubReaders();
+ if (subReaders != null && subReaders.length > 0)
+ {
+ _subReaders = subReaders;
+
+ int maxDoc = 0;
+ _starts = new int[_subReaders.length + 1];
+ for (int i = 0; i < _subReaders.length; i++)
+ {
+ _subReaders[i]._dir = _dir;
+ if (facetHandlers != null)
+ _subReaders[i].setFacetHandlers(facetHandlers);
+ _starts[i] = maxDoc;
+ maxDoc += _subReaders[i].maxDoc();
+ }
+ _starts[_subReaders.length] = maxDoc;
+ }
+ }
+ _runtimeFacetHandlerFactories = facetHandlerFactories;
+ _runtimeFacetHandlerFactoryMap = new HashMap<String, RuntimeFacetHandlerFactory< ? , ? >>();
+ if (_runtimeFacetHandlerFactories != null)
+ {
+ for (RuntimeFacetHandlerFactory< ? , ? > factory : _runtimeFacetHandlerFactories)
+ {
+ _runtimeFacetHandlerFactoryMap.put(factory.getName(), factory);
+ }
+ }
+ _facetHandlers = facetHandlers;
+ _workArea = workArea;
+ }
+
+ protected void facetInit() throws IOException
+ {
+ facetInit(new HashSet<String>());
+ }
+
+ protected void facetInit(Set<String> toBeRemoved) throws IOException
+ {
+ initialize(_facetHandlers);
+ if (_subReaders == null)
+ {
+ loadFacetHandlers(_workArea, toBeRemoved);
+ }
+ else
+ {
+ for (BoboIndexReader r : _subReaders)
+ {
+ r.facetInit(toBeRemoved);
+ }
+
+ for (String name : toBeRemoved)
+ {
+ _facetHandlerMap.remove(name);
+ }
+ }
+ }
+
+ protected void setFacetHandlers(Collection<FacetHandler< ? >> facetHandlers)
+ {
+ _facetHandlers = facetHandlers;
+ }
+
+ /**
+ * @deprecated use {@link org.apache.lucene.search.MatchAllDocsQuery} instead.
+ * @return query that matches all docs in the index
+ */
+ public Query getFastMatchAllDocsQuery()
+ {
+ return new MatchAllDocsQuery();
+ }
+
+ /**
+ * Utility method to dump out all fields (name and terms) for a given index.
+ * @param outFile File to dump to.
+ * @throws IOException
+ */
+ public void dumpFields(File outFile) throws IOException
+ {
+ FileWriter writer = null;
+ try
+ {
+ writer = new FileWriter(outFile);
+ PrintWriter out = new PrintWriter(writer);
+ Set<String> fieldNames = getFacetNames();
+ for (String fieldName : fieldNames)
+ {
+ TermEnum te = terms(new Term(fieldName, ""));
+ out.write(fieldName + ":\n");
+ while (te.next())
+ {
+ Term term = te.term();
+ if (!fieldName.equals(term.field()))
+ {
+ break;
+ }
+ out.write(term.text() + "\n");
+ }
+ out.write("\n\n");
+ }
+ }
+ finally
+ {
+ if (writer != null)
+ {
+ writer.close();
+ }
+ }
+ }
+
+ /**
+ * Gets all the facet field names
+ * @return Set of facet field names
+ */
+ public Set<String> getFacetNames()
+ {
+ return _facetHandlerMap.keySet();
+ }
+
+ /**
+ * Gets a facet handler
+ * @param fieldname name
+ * @return facet handler
+ */
+ public FacetHandler< ? > getFacetHandler(String fieldname)
+ {
+ FacetHandler< ? > f = _facetHandlerMap.get(fieldname);
+ if (f == null)
+ f = getRuntimeFacetHandler(fieldname);
+ return f;
+ }
+
+ @Override
+ public IndexReader[] getSequentialSubReaders()
+ {
+ return _subReaders;
+ }
+
+ /**
+ * Gets the facet handler map
+ * @return facet handler map
+ */
+ public Map<String, FacetHandler< ? >> getFacetHandlerMap()
+ {
+ return _facetHandlerMap;
+ }
+
+ /**
+ * @return the map of RuntimeFacetHandlerFactories
+ */
+ public Map<String, RuntimeFacetHandlerFactory< ? , ? >> getRuntimeFacetHandlerFactoryMap()
+ {
+ return _runtimeFacetHandlerFactoryMap;
+ }
+
+ public Document fillFacetData(int docid, Document doc) throws IOException
+ {
+ if (_subReaders != null)
+ {
+ int readerIndex = readerIndex(docid, _starts, _subReaders.length);
+ BoboIndexReader subReader = _subReaders[readerIndex];
+ int subid = docid - _starts[readerIndex];
+ return subReader.fillFacetData(subid, doc);
+ }
+ else
+ {
+ if (doc == null)
+ {
+ doc = new Document();
+ }
+ Collection<FacetHandler< ? >> facetHandlers = _facetHandlerMap.values();
+ for (FacetHandler< ? > facetHandler : facetHandlers)
+ {
+ String[] vals = facetHandler.getFieldValues(this, docid);
+ if (vals != null)
+ {
+ String[] values = doc.getValues(facetHandler.getName());
+ Set<String> storedVals = new HashSet<String>(Arrays.asList(values));
+
+ for (String val : vals)
+ {
+ storedVals.add(val);
+ }
+ doc.removeField(facetHandler.getName());
+
+ for (String val : storedVals)
+ {
+ doc.add(new Field(facetHandler.getName(), val, Field.Store.NO, Field.Index.NOT_ANALYZED));
+ }
+ }
+ }
+ return doc;
+ }
+ }
+
+ private static int readerIndex(int n, int[] starts, int numSubReaders)
+ {
+ int lo = 0;
+ int hi = numSubReaders - 1;
+
+ while (hi >= lo)
+ {
+ int mid = (lo + hi) >>> 1;
+ int midValue = starts[mid];
+ if (n < midValue)
+ hi = mid - 1;
+ else if (n > midValue)
+ lo = mid + 1;
+ else
+ {
+ while (mid + 1 < numSubReaders && starts[mid + 1] == midValue)
+ {
+ mid++;
+ }
+ return mid;
+ }
+ }
+ return hi;
+ }
+
+ /**
+ * Work area for loading
+ */
+ public static class WorkArea
+ {
+
+ HashMap<Class< ? >, Object> map = new HashMap<Class< ? >, Object>();
+
+ @SuppressWarnings("unchecked")
+ public <T> T get(Class<T> cls)
+ {
+ T obj = (T) map.get(cls);
+ return obj;
+ }
+
+ public void put(Object obj)
+ {
+ map.put(obj.getClass(), obj);
+ }
+
+ public void clear()
+ {
+ map.clear();
+ }
+
+ @Override
+ public String toString()
+ {
+ return map.toString();
+ }
+ }
+
+ private BoboIndexReader(IndexReader in)
+ {
+ super(in);
+ }
+
+ public BoboIndexReader copy(IndexReader in)
+ {
+ if (_subReaders != null)
+ {
+ throw new IllegalStateException("this BoboIndexReader has subreaders");
+ }
+ BoboIndexReader copy = new BoboIndexReader(in);
+ copy._facetHandlerMap = this._facetHandlerMap;
+ copy._facetHandlers = this._facetHandlers;
+ copy._runtimeFacetHandlerFactories = this._runtimeFacetHandlerFactories;
+ copy._runtimeFacetHandlerFactoryMap = this._runtimeFacetHandlerFactoryMap;
+ copy._workArea = this._workArea;
+ copy._facetDataMap.putAll(this._facetDataMap);
+ copy._srcReader = in;
+ copy._starts = this._starts;
+ return copy;
+ }
+}
Property changes on: magnoliamodules/trunk/magnolia-test-webapp/src/main/java/com/browseengine/bobo/api/BoboIndexReader.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: magnoliamodules/trunk/magnolia-test-webapp/src/main/resources/log4j.xml
===================================================================
--- magnoliamodules/trunk/magnolia-test-webapp/src/main/resources/log4j.xml 2013-10-20 18:52:41 UTC (rev 4414)
+++ magnoliamodules/trunk/magnolia-test-webapp/src/main/resources/log4j.xml 2013-10-20 19:02:14 UTC (rev 4415)
@@ -1,5 +1,5 @@
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration>
<!-- log4j test configuration -->
<appender name="test-appender" class="org.apache.log4j.ConsoleAppender">
@@ -31,6 +31,9 @@
<category name="score">
<priority value="INFO" />
</category>
+ <category name="it">
+ <priority value="INFO" />
+ </category>
<category name="info.magnolia.module.model.reader.BetwixtModuleDefinitionReader">
<priority value="INFO" />
</category>
Added: magnoliamodules/trunk/magnolia-test-webapp/src/main/webapp/templates/samples-lms/courses.jsp
===================================================================
--- magnoliamodules/trunk/magnolia-test-webapp/src/main/webapp/templates/samples-lms/courses.jsp (rev 0)
+++ magnoliamodules/trunk/magnolia-test-webapp/src/main/webapp/templates/samples-lms/courses.jsp 2013-10-20 19:02:14 UTC (rev 4415)
@@ -0,0 +1,36 @@
+<jsp:root version="2.0" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:cms="urn:jsptld:cms-taglib" xmlns:cmsu="urn:jsptld:cms-util-taglib"
+ xmlns:c="urn:jsptld:http://java.sun.com/jsp/jstl/core" xmlns:fmt="urn:jsptld:http://java.sun.com/jsp/jstl/fmt"
+ xmlns:cmsfn="http://www.magnolia.info/tlds/cmsfn-taglib.tld" xmlns:lmsfn="urn:jsptld:lms-fn">
+ <jsp:directive.page contentType="text/html; charset=UTF-8" session="false" />
+ <jsp:text>
+ <![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> ]]>
+ </jsp:text>
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>${actpage.title}</title>
+ <cms:links />
+ </head>
+ <body>
+ <h1>${actpage.title}</h1>
+ <p>Click on a course in the list below. It opens a popup with the course inside</p>
+ <ul>
+ <c:forEach items="${lmsfn:courseList()}" var="course">
+ <li>
+ <lmsfn:playerUrl course="${course}" target="blank" />
+ </li>
+ </c:forEach>
+ </ul>
+ <p>The code to create the list is:</p>
+ <pre>
+ &lt;ul&gt;
+ &lt;c:forEach items="\${lmsfn:courseList()}" var="course"&gt;
+ &lt;li&gt;
+ &lt;lmsfn:playerUrl course="\${course}" target="blank" /&gt;
+ &lt;/li&gt;
+ &lt;/c:forEach&gt;
+ &lt;/ul&gt;
+ </pre>
+ </body>
+ </html>
+</jsp:root>
\ No newline at end of file
Property changes on: magnoliamodules/trunk/magnolia-test-webapp/src/main/webapp/templates/samples-lms/courses.jsp
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/xml
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: magnoliamodules/trunk/magnolia-test-webapp/src/main/webapp/templates/samples-lms/index.jsp
===================================================================
--- magnoliamodules/trunk/magnolia-test-webapp/src/main/webapp/templates/samples-lms/index.jsp (rev 0)
+++ magnoliamodules/trunk/magnolia-test-webapp/src/main/webapp/templates/samples-lms/index.jsp 2013-10-20 19:02:14 UTC (rev 4415)
@@ -0,0 +1,62 @@
+<jsp:root version="2.0" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:cms="urn:jsptld:cms-taglib" xmlns:cmsu="urn:jsptld:cms-util-taglib"
+ xmlns:c="urn:jsptld:http://java.sun.com/jsp/jstl/core" xmlns:fmt="urn:jsptld:http://java.sun.com/jsp/jstl/fmt"
+ xmlns:cmsfn="http://www.magnolia.info/tlds/cmsfn-taglib.tld" xmlns:lmsfn="urn:jsptld:lms-fn">
+ <jsp:directive.page contentType="text/html; charset=UTF-8" session="false" />
+ <jsp:text>
+ <![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> ]]>
+ </jsp:text>
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>${actpage.title}</title>
+ <cms:links />
+ </head>
+ <body>
+ <h1>${actpage.title}</h1>
+ <p>Welcome to Magnolia LMS Module sample page.</p>
+ <p>The sample course repository is structured as:</p>
+ <ul>
+ <li>
+ <b>samples</b>
+ <ul>
+ <li>
+ <b>std-level-1</b>
+ <ol>
+ <li>Simple course 1</li>
+ <li>Simple course 2</li>
+ </ol>
+ <ul>
+ <li>
+ <b>std-level2a</b>
+ <ol>
+ <li>Simple course 1</li>
+ </ol>
+ </li>
+ <li>
+ <b>std-level2b</b>
+ <ol>
+ <li>Simple course 1</li>
+ </ol>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ <p>There are three roles, one for each folder:</p>
+ <ul>
+ <li><b>std-level-1</b> which can view its courses but not subfolders</li>
+ <li><b>std-level-2a</b> which can view its courses but not subfolders</li>
+ <li><b>std-level-3a</b> which can view its courses but not subfolders</li>
+ </ul>
+ <p>The user student/student has the role std-level-1; there is an example listener (net.sourceforge.openutils.mgnllms.samples.listeners.StudentLevelListener defined in /modules/lms/lms-config/listeners/student-level),
+ that is called whenever a user complete a course and performs following actions:
+ <ol>
+ <li>check if the user has successfully completed all courses to which he has access</li>
+ <li>if true assign to user additional roles corresponding to the names of subfolders of the last completed course</li>
+ </ol>
+ </p>
+ <p><a href="${pageContext.request.contextPath}/sample-lms/courses.html">Go to the courses list!</a> (use student/student to access)</p>
+ </body>
+ </html>
+</jsp:root>
\ No newline at end of file
Property changes on: magnoliamodules/trunk/magnolia-test-webapp/src/main/webapp/templates/samples-lms/index.jsp
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/xml
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: magnoliamodules/trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/utils/BaseAnalyzer.java
===================================================================
--- magnoliamodules/trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/utils/BaseAnalyzer.java 2013-10-20 18:52:41 UTC (rev 4414)
+++ magnoliamodules/trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/utils/BaseAnalyzer.java 2013-10-20 19:02:14 UTC (rev 4415)
@@ -37,14 +37,14 @@
{
@Override
- public TokenStream tokenStream(String fieldName, Reader reader)
+ public final TokenStream tokenStream(String fieldName, Reader reader)
{
StandardTokenizer tokenStream = tokenize(reader);
return tokenFiltersChain(tokenStream);
}
@Override
- public TokenStream reusableTokenStream(String fieldName, Reader reader) throws IOException
+ public final TokenStream reusableTokenStream(String fieldName, Reader reader) throws IOException
{
SavedStreams streams = (SavedStreams) getPreviousTokenStream();
if (streams == null)
Modified: magnoliamodules/trunk/openutils-mgnlcriteria/src/test/resources/log4j.xml
===================================================================
--- magnoliamodules/trunk/openutils-mgnlcriteria/src/test/resources/log4j.xml 2013-10-20 18:52:41 UTC (rev 4414)
+++ magnoliamodules/trunk/openutils-mgnlcriteria/src/test/resources/log4j.xml 2013-10-20 19:02:14 UTC (rev 4415)
@@ -28,9 +28,6 @@
<category name="org.dbunit">
<priority value="WARN" />
</category>
- <category name="it.openmindonline.sapere.search.SapereSearcher">
- <priority value="DEBUG" />
- </category>
<category name="score">
<priority value="INFO" />
</category>
Modified: magnoliamodules/trunk/openutils-mgnltagcloud/pom.xml
===================================================================
--- magnoliamodules/trunk/openutils-mgnltagcloud/pom.xml 2013-10-20 18:52:41 UTC (rev 4414)
+++ magnoliamodules/trunk/openutils-mgnltagcloud/pom.xml 2013-10-20 19:02:14 UTC (rev 4415)
@@ -145,7 +145,8 @@
<dependency>
<groupId>com.browseengine.bobo</groupId>
<artifactId>bobo-browse</artifactId>
- <version>2.5.1</version>
+ <version>3.2.0</version>
+ <!-- <version>2.5.1</version> for jackrabbit 2.4 -->
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
Added: magnoliamodules/trunk/openutils-mgnltagcloud/src/test/java/com/browseengine/bobo/api/BoboIndexReader.java
===================================================================
--- magnoliamodules/trunk/openutils-mgnltagcloud/src/test/java/com/browseengine/bobo/api/BoboIndexReader.java (rev 0)
+++ magnoliamodules/trunk/openutils-mgnltagcloud/src/test/java/com/browseengine/bobo/api/BoboIndexReader.java 2013-10-20 19:02:14 UTC (rev 4415)
@@ -0,0 +1,914 @@
+/**
+ *
+ * Tagcloud module for Magnolia CMS (http://www.openmindlab.com/lab/products/mgnltagcloud.html)
+ * Copyright(C) 2010-2013, Openmind S.r.l. http://www.openmindonline.it
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// lucene 3.6 compatibility patch for bobo-browse 3.2.0, see https://github.com/senseidb/bobo/commit/e78d91ef8a00965d8d55c819f967cac172c23d17
+/**
+ * Bobo Browse Engine - High performance faceted/parametric search implementation
+ * that handles various types of semi-structured data. Written in Java.
+ *
+ * Copyright (C) 2005-2006 John Wang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * To contact the project administrators for the bobo-browse project,
+ * please go to https://sourceforge.net/projects/bobo-browse/, or
+ * send mail to ow...@br....
+ */
+
+package com.browseengine.bobo.api;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import org.apache.log4j.Logger;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.index.CorruptIndexException;
+import org.apache.lucene.index.FilterIndexReader;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.MultiReader;
+import org.apache.lucene.index.SegmentInfo;
+import org.apache.lucene.index.SegmentInfos;
+import org.apache.lucene.index.SegmentReader;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.index.TermEnum;
+import org.apache.lucene.search.MatchAllDocsQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.FSDirectory;
+import org.apache.lucene.util.ReaderUtil;
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+import org.springframework.context.support.GenericApplicationContext;
+
+import com.browseengine.bobo.facets.FacetHandler;
+import com.browseengine.bobo.facets.RuntimeFacetHandler;
+import com.browseengine.bobo.facets.RuntimeFacetHandlerFactory;
+
+
+/**
+ * bobo browse index reader
+ */
+public class BoboIndexReader extends FilterIndexReader
+{
+
+ private static final String SPRING_CONFIG = "bobo.spring";
+
+ private static Logger logger = Logger.getLogger(BoboIndexReader.class);
+
+ protected Map<String, FacetHandler< ? >> _facetHandlerMap;
+
+ protected Collection<FacetHandler< ? >> _facetHandlers;
+
+ protected Collection<RuntimeFacetHandlerFactory< ? , ? >> _runtimeFacetHandlerFactories;
+
+ protected Map<String, RuntimeFacetHandlerFactory< ? , ? >> _runtimeFacetHandlerFactoryMap;
+
+ protected WorkArea _workArea;
+
+ protected IndexReader _srcReader;
+
+ protected BoboIndexReader[] _subReaders = null;
+
+ protected int[] _starts = null;
+
+ private Directory _dir = null;
+
+ private final Map<String, Object> _facetDataMap = new HashMap<String, Object>();
+
+ private final ThreadLocal<Map<String, Object>> _runtimeFacetDataMap = new ThreadLocal<Map<String, Object>>()
+ {
+
+ protected Map<String, Object> initialValue()
+ {
+ return new HashMap<String, Object>();
+ }
+ };
+
+ private final ThreadLocal<Map<String, RuntimeFacetHandler< ? >>> _runtimeFacetHandlerMap = new ThreadLocal<Map<String, RuntimeFacetHandler< ? >>>()
+ {
+
+ protected Map<String, RuntimeFacetHandler< ? >> initialValue()
+ {
+ return new HashMap<String, RuntimeFacetHandler< ? >>();
+ }
+ };
+
+ /**
+ * Constructor
+ * @param reader Index reader
+ * @throws IOException
+ */
+ public static BoboIndexReader getInstance(IndexReader reader) throws IOException
+ {
+ return BoboIndexReader.getInstance(reader, null, null, new WorkArea());
+ }
+
+ public static BoboIndexReader getInstance(IndexReader reader, WorkArea workArea) throws IOException
+ {
+ return BoboIndexReader.getInstance(reader, null, null, workArea);
+ }
+
+ /**
+ * Constructor.
+ * @param reader index reader
+ * @param facetHandlers List of facet handlers
+ * @throws IOException
+ */
+ public static BoboIndexReader getInstance(IndexReader reader, Collection<FacetHandler< ? >> facetHandlers,
+ Collection<RuntimeFacetHandlerFactory< ? , ? >> facetHandlerFactories) throws IOException
+ {
+ return BoboIndexReader.getInstance(reader, facetHandlers, facetHandlerFactories, new WorkArea());
+ }
+
+ public static BoboIndexReader getInstance(IndexReader reader, Collection<FacetHandler< ? >> facetHandlers)
+ throws IOException
+ {
+ return BoboIndexReader.getInstance(reader, facetHandlers, Collections.EMPTY_LIST, new WorkArea());
+ }
+
+ public static BoboIndexReader getInstance(IndexReader reader, Collection<FacetHandler< ? >> facetHandlers,
+ Collection<RuntimeFacetHandlerFactory< ? , ? >> facetHandlerFactories, WorkArea workArea) throws IOException
+ {
+ BoboIndexReader boboReader = new BoboIndexReader(reader, facetHandlers, facetHandlerFactories, workArea);
+ boboReader.facetInit();
+ return boboReader;
+ }
+
+ public static BoboIndexReader getInstanceAsSubReader(IndexReader reader) throws IOException
+ {
+ return getInstanceAsSubReader(reader, null, null, new WorkArea());
+ }
+
+ public static BoboIndexReader getInstanceAsSubReader(IndexReader reader,
+ Collection<FacetHandler< ? >> facetHandlers,
+ Collection<RuntimeFacetHandlerFactory< ? , ? >> facetHandlerFactories) throws IOException
+ {
+ return getInstanceAsSubReader(reader, facetHandlers, facetHandlerFactories, new WorkArea());
+ }
+
+ public static BoboIndexReader getInstanceAsSubReader(IndexReader reader,
+ Collection<FacetHandler< ? >> facetHandlers,
+ Collection<RuntimeFacetHandlerFactory< ? , ? >> facetHandlerFactories, WorkArea workArea) throws IOException
+ {
+ BoboIndexReader boboReader = new BoboIndexReader(reader, facetHandlers, facetHandlerFactories, workArea, false);
+ boboReader.facetInit();
+ return boboReader;
+ }
+
+ @Override
+ public long getVersion()
+ {
+ try
+ {
+ SegmentInfos sinfos = new SegmentInfos();
+ sinfos.read(_dir);
+ return sinfos.getVersion();
+ }
+ catch (Exception e)
+ {
+ return 0L;
+ }
+ }
+
+ public IndexReader getInnerReader()
+ {
+ return in;
+ }
+
+ @Override
+ public synchronized IndexReader reopen() throws CorruptIndexException, IOException
+ {
+ IndexReader newInner = null;
+
+ SegmentInfos sinfos = new SegmentInfos();
+ sinfos.read(_dir);
+ int size = sinfos.size();
+
+ if (in instanceof MultiReader)
+ {
+ // setup current reader list
+ List<IndexReader> boboReaderList = new LinkedList<IndexReader>();
+ ReaderUtil.gatherSubReaders((List<IndexReader>) boboReaderList, in);
+ Map<String, BoboIndexReader> readerMap = new HashMap<String, BoboIndexReader>();
+ for (IndexReader reader : boboReaderList)
+ {
+ BoboIndexReader boboReader = (BoboIndexReader) reader;
+ SegmentReader sreader = (SegmentReader) (boboReader.in);
+ readerMap.put(sreader.getSegmentName(), boboReader);
+ }
+
+ ArrayList<BoboIndexReader> currentReaders = new ArrayList<BoboIndexReader>(size);
+ boolean isNewReader = false;
+ for (int i = 0; i < size; ++i)
+ {
+ SegmentInfo sinfo = (SegmentInfo) sinfos.info(i);
+ BoboIndexReader breader = readerMap.remove(sinfo.name);
+ if (breader != null)
+ {
+ // should use SegmentReader.reopen
+ // TODO: see LUCENE-2559
+ BoboIndexReader newReader = (BoboIndexReader) breader.reopen(true);
+ if (newReader != breader)
+ {
+ isNewReader = true;
+ }
+ if (newReader != null)
+ {
+ currentReaders.add(newReader);
+ }
+ }
+ else
+ {
+ isNewReader = true;
+ SegmentReader newSreader = SegmentReader.get(true, sinfo, 1);
+ breader = BoboIndexReader.getInstanceAsSubReader(
+ newSreader,
+ this._facetHandlers,
+ this._runtimeFacetHandlerFactories);
+ breader._dir = _dir;
+ currentReaders.add(breader);
+ }
+ }
+ isNewReader = isNewReader || (readerMap.size() != 0);
+ if (!isNewReader)
+ {
+ return this;
+ }
+ else
+ {
+ MultiReader newMreader = new MultiReader(currentReaders.toArray(new BoboIndexReader[currentReaders
+ .size()]), false);
+ BoboIndexReader newReader = BoboIndexReader.getInstanceAsSubReader(
+ newMreader,
+ this._facetHandlers,
+ this._runtimeFacetHandlerFactories);
+ newReader._dir = _dir;
+ return newReader;
+ }
+ }
+ else if (in instanceof SegmentReader)
+ {
+ // should use SegmentReader.reopen
+ // TODO: see LUCENE-2559
+
+ SegmentReader sreader = (SegmentReader) in;
+ int numDels = sreader.numDeletedDocs();
+
+ SegmentInfo sinfo = null;
+ boolean sameSeg = false;
+ // get SegmentInfo instance
+ for (int i = 0; i < size; ++i)
+ {
+ SegmentInfo sinfoTmp = (SegmentInfo) sinfos.info(i);
+ if (sinfoTmp.name.equals(sreader.getSegmentName()))
+ {
+ int numDels2 = sinfoTmp.getDelCount();
+ sameSeg = numDels == numDels2;
+ sinfo = sinfoTmp;
+ break;
+ }
+ }
+
+ if (sinfo == null)
+ {
+ // segment no longer exists
+ return null;
+ }
+ if (sameSeg)
+ {
+ return this;
+ }
+ else
+ {
+ SegmentReader newSreader = SegmentReader.get(true, sinfo, 1);
+ return BoboIndexReader.getInstanceAsSubReader(
+ newSreader,
+ this._facetHandlers,
+ this._runtimeFacetHandlerFactories);
+ }
+ }
+ else
+ {
+ // should not reach here, a catch-all default case
+ IndexReader reader = in.reopen(true);
+ if (in != reader)
+ {
+ return BoboIndexReader.getInstance(newInner, _facetHandlers, _runtimeFacetHandlerFactories, _workArea);
+ }
+ else
+ {
+ return this;
+ }
+ }
+ }
+
+ @Override
+ public synchronized IndexReader reopen(boolean openReadOnly) throws CorruptIndexException, IOException
+ {
+
+ // bobo readers are always readonly
+ return reopen();
+ }
+
+ public Object getFacetData(String name)
+ {
+ return _facetDataMap.get(name);
+ }
+
+ public Object putFacetData(String name, Object data)
+ {
+ return _facetDataMap.put(name, data);
+ }
+
+ public Object getRuntimeFacetData(String name)
+ {
+ Map<String, Object> map = _runtimeFacetDataMap.get();
+ if (map == null)
+ return null;
+
+ return map.get(name);
+ }
+
+ public Object putRuntimeFacetData(String name, Object data)
+ {
+ Map<String, Object> map = _runtimeFacetDataMap.get();
+ if (map == null)
+ {
+ map = new HashMap<String, Object>();
+ _runtimeFacetDataMap.set(map);
+ }
+ return map.put(name, data);
+ }
+
+ public void clearRuntimeFacetData()
+ {
+ _runtimeFacetDataMap.set(null);
+ }
+
+ public RuntimeFacetHandler< ? > getRuntimeFacetHandler(String name)
+ {
+ Map<String, RuntimeFacetHandler< ? >> map = _runtimeFacetHandlerMap.get();
+ if (map == null)
+ return null;
+
+ return map.get(name);
+ }
+
+ public void putRuntimeFacetHandler(String name, RuntimeFacetHandler< ? > data)
+ {
+ Map<String, RuntimeFacetHandler< ? >> map = _runtimeFacetHandlerMap.get();
+ if (map == null)
+ {
+ map = new HashMap<String, RuntimeFacetHandler< ? >>();
+ _runtimeFacetHandlerMap.set(map);
+ }
+ map.put(name, data);
+ }
+
+ public void clearRuntimeFacetHandler()
+ {
+ _runtimeFacetHandlerMap.set(null);
+ }
+
+ @Override
+ protected void doClose() throws IOException
+ {
+ _facetDataMap.clear();
+ if (_srcReader != null)
+ _srcReader.close();
+ super.doClose();
+ }
+
+ @Override
+ protected void doCommit(Map commitUserData) throws IOException
+ {
+ if (_srcReader != null)
+ _srcReader.flush(commitUserData);
+ }
+
+ @Override
+ protected void doDelete(int n) throws CorruptIndexException, IOException
+ {
+ if (_srcReader != null)
+ _srcReader.deleteDocument(n);
+ }
+
+ private void loadFacetHandler(String name, Set<String> loaded, Set<String> visited, WorkArea workArea)
+ throws IOException
+ {
+ FacetHandler< ? > facetHandler = _facetHandlerMap.get(name);
+ if (facetHandler != null && !loaded.contains(name))
+ {
+ visited.add(name);
+ Set<String> dependsOn = facetHandler.getDependsOn();
+ if (dependsOn.size() > 0)
+ {
+ Iterator<String> iter = dependsOn.iterator();
+ while (iter.hasNext())
+ {
+ String f = iter.next();
+ ...
[truncated message content] |