001    /**
002     * $RCSfile: MCRLuceneCommands.java,v $
003     * $Revision: 1.0 $ $Date: 22.10.2008 06:48:51 $
004     *
005     * This file is part of ** M y C o R e **
006     * Visit our homepage at http://www.mycore.de/ for details.
007     *
008     * This program is free software; you can use it, redistribute it
009     * and / or modify it under the terms of the GNU General Public License
010     * (GPL) as published by the Free Software Foundation; either version 2
011     * of the License or (at your option) any later version.
012     *
013     * This program is distributed in the hope that it will be useful, but
014     * WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program, normally in the file license.txt.
020     * If not, write to the Free Software Foundation Inc.,
021     * 59 Temple Place - Suite 330, Boston, MA  02111-1307 USA
022     *
023     **/
024    package org.mycore.frontend.cli;
025    
026    import java.io.IOException;
027    import java.util.ArrayList;
028    import java.util.GregorianCalendar;
029    import java.util.List;
030    import java.util.Properties;
031    import java.util.Map.Entry;
032    
033    import org.apache.log4j.Logger;
034    import org.hibernate.CacheMode;
035    import org.hibernate.Criteria;
036    import org.hibernate.ScrollMode;
037    import org.hibernate.ScrollableResults;
038    import org.hibernate.Session;
039    import org.hibernate.criterion.Restrictions;
040    import org.jdom.Document;
041    import org.jdom.Element;
042    import org.jdom.JDOMException;
043    import org.jdom.Namespace;
044    
045    import org.mycore.backend.hibernate.MCRHIBConnection;
046    import org.mycore.backend.hibernate.tables.MCRFSNODES;
047    import org.mycore.backend.hibernate.tables.MCRXMLTABLE;
048    import org.mycore.common.MCRConfiguration;
049    import org.mycore.common.MCRConstants;
050    import org.mycore.common.xml.MCRXMLResource;
051    import org.mycore.datamodel.ifs.MCRFile;
052    import org.mycore.datamodel.ifs.MCRFileMetadataManager;
053    import org.mycore.services.fieldquery.MCRData2Fields;
054    import org.mycore.services.fieldquery.MCRFieldDef;
055    import org.mycore.services.fieldquery.MCRFieldValue;
056    import org.mycore.services.fieldquery.MCRSearcher;
057    import org.mycore.services.fieldquery.MCRSearcherFactory;
058    
059    /**
060     * provides static methods to manipulate MCRSearcher indexes.
061     * 
062     * @author Thomas Scheffler (yagee)
063     */
064    
065    public class MCRSearcherCommands extends MCRAbstractCommands {
066        private static final String INDEX_TYPE_CONTENT = "file";
067    
068        private static final String INDEX_TYPE_METADATA = "object";
069    
070        private static Logger LOGGER = Logger.getLogger(MCRSearcherCommands.class);
071    
072        private static final String SEARCHER_PROPERTY_START = "MCR.Searcher.";
073    
074        private static final String SEARCHER_CLASS_SUFFIX = ".Class";
075    
076        private static final String SEARCHER_INDEX_SUFFIX = ".Index";
077    
078        public MCRSearcherCommands() {
079            super();
080            command.add(new MCRCommand("rebuild metadata index", "org.mycore.frontend.cli.MCRSearcherCommands.repairMetaIndex", "Repairs metadata index"));
081            command.add(new MCRCommand("rebuild content index", "org.mycore.frontend.cli.MCRSearcherCommands.repairContentIndex", "Repairs metadata index"));
082        }
083    
084        /**
085         * repairs all metadata indexes
086         * 
087         * @throws IOException
088         * @throws JDOMException
089         */
090        public static void repairMetaIndex() throws IOException, JDOMException {
091            List<String> indexes = getIndexes();
092            List<String> metaSearcher = new ArrayList<String>(1);
093            for (String index : indexes) {
094                if (isIndexType(index, INDEX_TYPE_METADATA))
095                    metaSearcher.add(index);
096            }
097            for (String searcherID : metaSearcher) {
098                MCRSearcher searcher = MCRSearcherFactory.getSearcher(searcherID);
099                LOGGER.info("clearing index " + searcherID);
100                searcher.clearIndex();
101                searcher.notifySearcher("insert");
102                Session session = MCRHIBConnection.instance().getSession();
103                Criteria xmlCriteria = session.createCriteria(MCRXMLTABLE.class);
104                xmlCriteria.setCacheMode(CacheMode.IGNORE);
105                ScrollableResults results = xmlCriteria.scroll(ScrollMode.FORWARD_ONLY);
106                while (results.next()) {
107                    MCRXMLTABLE xmlEntry = (MCRXMLTABLE) results.get(0);
108                    if (xmlEntry.getType().equals("derivate"))
109                        continue;
110                    addMetaToIndex(xmlEntry, false, searcher);
111                    session.evict(xmlEntry);
112                }
113                searcher.notifySearcher("finish");
114                LOGGER.info("Done building index " + searcherID);
115            }
116        }
117    
118        /**
119         * repairs all content indexes
120         * 
121         * @throws IOException
122         * @throws JDOMException
123         */
124        public static void repairContentIndex() throws IOException, JDOMException {
125            List<String> indexes = getIndexes();
126            List<String> contentSearcher = new ArrayList<String>(1);
127            for (String index : indexes) {
128                if (isIndexType(index, INDEX_TYPE_CONTENT))
129                    contentSearcher.add(index);
130            }
131            for (String searcherID : contentSearcher) {
132                MCRSearcher searcher = MCRSearcherFactory.getSearcher(searcherID);
133                LOGGER.info("clearing index " + searcherID);
134                searcher.clearIndex();
135                searcher.notifySearcher("insert");
136                Session session = MCRHIBConnection.instance().getSession();
137                Criteria fileCriteria = session.createCriteria(MCRFSNODES.class);
138                fileCriteria.add(Restrictions.eq("type", "F"));
139                fileCriteria.setCacheMode(CacheMode.IGNORE);
140                ScrollableResults results = fileCriteria.scroll(ScrollMode.FORWARD_ONLY);
141                while (results.next()) {
142                    MCRFSNODES node = (MCRFSNODES) results.get(0);
143                    GregorianCalendar greg = new GregorianCalendar();
144                    greg.setTime(node.getDate());
145                    MCRFile file = (MCRFile) MCRFileMetadataManager.instance().buildNode(node.getType(), node.getId(), node.getPid(), node.getOwner(),
146                            node.getName(), node.getLabel(), node.getSize(), greg, node.getStoreid(), node.getStorageid(), node.getFctid(), node.getMd5(),
147                            node.getNumchdd(), node.getNumchdf(), node.getNumchtd(), node.getNumchtf());
148                    addFileToIndex(file, false, searcher);
149                    session.evict(node);
150                }
151                searcher.notifySearcher("finish");
152                LOGGER.info("Done building index " + searcherID);
153            }
154        }
155    
156        private static List<String> getIndexes() {
157            Properties searcherProps = MCRConfiguration.instance().getProperties(SEARCHER_PROPERTY_START);
158            List<String> luceneIndexes = new ArrayList<String>(2);
159            for (Entry<Object, Object> property : searcherProps.entrySet()) {
160                if (property.getKey().toString().endsWith(SEARCHER_CLASS_SUFFIX)) {
161                    luceneIndexes.add(property.getKey().toString().split("\\.")[2]);
162                }
163            }
164            LOGGER.info("Found MCRSearcher indexes: " + luceneIndexes);
165            return luceneIndexes;
166        }
167    
168        private static boolean isIndexType(String index, String type) throws IOException, JDOMException {
169            Document searchFields = MCRXMLResource.instance().getResource("searchfields.xml");
170            final String indexKey = MCRConfiguration.instance().getString(SEARCHER_PROPERTY_START + index + SEARCHER_INDEX_SUFFIX);
171            for (Object indexElement : searchFields.getRootElement().getChildren("index", MCRConstants.MCR_NAMESPACE)) {
172                final Element indexE = (Element) indexElement;
173                if (indexE.getAttributeValue("id").equals(indexKey))
174                    for (Object fieldElement : indexE.getChildren("field", MCRConstants.MCR_NAMESPACE)) {
175                        String source = ((Element) fieldElement).getAttributeValue("source");
176                        if (source.startsWith(type)) {
177                            return true;
178                        }
179                    }
180            }
181            return false;
182        }
183    
184        private static void addMetaToIndex(MCRXMLTABLE xmlEntry, boolean update, MCRSearcher searcher) {
185            List<MCRFieldValue> fields = MCRData2Fields.buildFields(xmlEntry.getXmlByteArray(), searcher.getIndex(), MCRFieldDef.OBJECT_METADATA
186                    + MCRFieldDef.OBJECT_CATEGORY, xmlEntry.getType());
187            if (update)
188                searcher.removeFromIndex(xmlEntry.getId());
189            searcher.addToIndex(xmlEntry.getId(), xmlEntry.getId(), fields);
190        }
191    
192        private static void addFileToIndex(MCRFile file, boolean update, MCRSearcher searcher) {
193            List<MCRFieldValue> fields = MCRData2Fields.buildFields(file, searcher.getIndex());
194            String entryID = file.getID();
195            String returnID = searcher.getReturnID(file);
196            if (update)
197                searcher.removeFromIndex(entryID);
198            searcher.addToIndex(entryID, returnID, fields);
199        }
200    }