001/**
002 * Copyright (c) 2011, The University of Southampton and the individual contributors.
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without modification,
006 * are permitted provided that the following conditions are met:
007 *
008 *   *  Redistributions of source code must retain the above copyright notice,
009 *      this list of conditions and the following disclaimer.
010 *
011 *   *  Redistributions in binary form must reproduce the above copyright notice,
012 *      this list of conditions and the following disclaimer in the documentation
013 *      and/or other materials provided with the distribution.
014 *
015 *   *  Neither the name of the University of Southampton nor the names of its
016 *      contributors may be used to endorse or promote products derived from this
017 *      software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package org.openimaj.text.nlp.geocode;
031
032import java.io.File;
033import java.io.IOException;
034
035import javax.xml.parsers.ParserConfigurationException;
036
037import org.apache.solr.client.solrj.SolrQuery;
038import org.apache.solr.client.solrj.SolrServerException;
039import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
040import org.apache.solr.client.solrj.response.QueryResponse;
041import org.apache.solr.core.CoreContainer;
042import org.apache.solr.core.CoreDescriptor;
043import org.apache.solr.core.SolrConfig;
044import org.apache.solr.core.SolrCore;
045import org.apache.solr.core.SolrResourceLoader;
046import org.apache.solr.schema.IndexSchema;
047import org.slf4j.Logger;
048import org.slf4j.LoggerFactory;
049import org.xml.sax.SAXException;
050
051/**
052 * @author Sina Samangooei (ss@ecs.soton.ac.uk), Jonathan Hare
053 *         (jsh2@ecs.soton.ac.uk), David Duplaw (dpd@ecs.soton.ac.uk)
054 * 
055 */
056public class GeonamesIndex {
057        private static final int N_ROWS = 10;
058
059        private static final String[] DEFAULT_FIELDS = new String[] { "*,score" };
060
061        /** Logging */
062        private static Logger log = LoggerFactory.getLogger(GeonamesIndex.class);
063
064        /** Solr file names */
065        private static String SOLR_CONFIG = "solrconfig.xml";
066        private static String SOLR_SCHEMA = "schema.xml";
067
068        /** Solr index */
069        private CoreContainer solrContainer;
070        private EmbeddedSolrServer solrIndex;
071
072        private static GeonamesIndex instance;
073
074        private GeonamesIndex() {
075                // Find the Solr home
076                String solrHome = System.getProperty("geonames.solr.home");
077                if (solrHome == null) {
078                        log.error("No 'geonames.solr.home' provided!");
079                        return;
080                }
081                // Validate on a basic level
082                File solrDir = new File(solrHome);
083                if (solrDir == null || !solrDir.exists() || !solrDir.isDirectory()) {
084                        log.error("SOLR_HOME does not exist, or is not a directory: '{}'",solrHome);
085                        return;
086                }
087                try {
088
089                        this.solrIndex = buildSolrIndex(solrHome);
090                } catch (Exception ex) {
091                        log.error("\n... Solr failed to load!");
092                        log.error("Stack trace: ", ex);
093                        log.error("\n=============");
094                }
095        }
096
097        /**
098         * @return get the {@link GeonamesIndex} instance
099         */
100        public static synchronized GeonamesIndex instance() {
101                if (instance == null) {
102                        instance = new GeonamesIndex();
103                }
104                return instance;
105        }
106
107        private EmbeddedSolrServer buildSolrIndex(String home) throws ParserConfigurationException, IOException, SAXException {
108                SolrConfig solrConfig = new SolrConfig(home, SOLR_CONFIG, null);
109                IndexSchema schema = new IndexSchema(solrConfig, SOLR_SCHEMA, null);
110
111                solrContainer = new CoreContainer(new SolrResourceLoader(
112                                SolrResourceLoader.locateSolrHome()));
113                CoreDescriptor descriptor = new CoreDescriptor(solrContainer, "",
114                                solrConfig.getResourceLoader().getInstanceDir());
115                descriptor.setConfigName(solrConfig.getResourceName());
116                descriptor.setSchemaName(schema.getResourceName());
117                SolrCore solrCore = new SolrCore(null, solrConfig.getDataDir(),solrConfig, schema, descriptor);
118                
119                solrContainer.register("cheese", solrCore, false);
120                return new EmbeddedSolrServer(solrContainer, "cheese");
121        }
122
123        /**
124         * @param query
125         * @return The response
126         * @throws SolrServerException 
127         */
128        public QueryResponse query(String query) throws SolrServerException {
129                return query(query, N_ROWS, DEFAULT_FIELDS, null);
130        }
131        
132        /**
133         * @param query
134         * @param limit 
135         * @return The response
136         * @throws SolrServerException 
137         */
138        public QueryResponse query(String query, int limit) throws SolrServerException {
139                return query(query, limit, DEFAULT_FIELDS, null);
140        }
141
142        /**
143         * @param query
144         * @param nRows
145         * @param fields
146         * @param filter
147         * @return the response
148         * @throws SolrServerException 
149         */
150        public QueryResponse query(String query, int nRows, String[] fields,String filter) throws SolrServerException {
151                SolrQuery q = new SolrQuery();
152                q.setQuery(query);
153                q.setRows(nRows);
154                q.setFields(fields);
155                if (filter != null) {
156                        q.setFilterQueries(filter);
157                }
158                q.setFacet(false);
159                return solrIndex.query(q);
160        }
161}