001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.search;
029
030import org.opencms.main.CmsIllegalArgumentException;
031import org.opencms.main.CmsLog;
032import org.opencms.main.OpenCms;
033import org.opencms.util.CmsStringUtil;
034
035import java.io.Serializable;
036import java.util.ArrayList;
037import java.util.HashMap;
038import java.util.Iterator;
039import java.util.List;
040import java.util.Map;
041
042import org.apache.commons.logging.Log;
043
044/**
045 * A search index source is a description of a list of Cms resources
046 * to be indexed.<p>
047 *
048 * @since 6.0.0
049 */
050public class CmsSearchIndexSource implements Comparable<CmsSearchIndexSource>, Serializable {
051
052    /** The serial version id. */
053    private static final long serialVersionUID = -3869627913906693823L;
054
055    /** The log object for this class. */
056    private static final Log LOG = CmsLog.getLog(CmsSearchIndexSource.class);
057
058    /** A list of Cms resource types to be indexed. */
059    private List<String> m_documentTypes;
060
061    /** The indexer. */
062    private transient I_CmsIndexer m_indexer;
063
064    /** The class name of the indexer. */
065    private String m_indexerClassName;
066
067    /** The logical key/name of this index. */
068    private String m_name;
069
070    /** A map of optional key/value parameters. */
071    private Map<String, String> m_params;
072
073    /** A list of Cms resources to be indexed. */
074    private List<String> m_resourcesNames;
075
076    /**
077     * Creates a new CmsSearchIndexSource.<p>
078     */
079    public CmsSearchIndexSource() {
080
081        m_params = new HashMap<String, String>();
082        m_resourcesNames = new ArrayList<String>();
083        m_documentTypes = new ArrayList<String>();
084    }
085
086    /**
087     * Adds a parameter.<p>
088     *
089     * @param key the key/name of the parameter
090     * @param value the value of the parameter
091     */
092    public void addConfigurationParameter(String key, String value) {
093
094        m_params.put(key, value);
095    }
096
097    /**
098     * Adds the name of a document type.<p>
099     *
100     * @param key the name of a document type to add
101     */
102    public void addDocumentType(String key) {
103
104        m_documentTypes.add(key);
105    }
106
107    /**
108     * Adds the path of a Cms resource.<p>
109     *
110     * @param resourceName the path of a Cms resource
111     */
112    public void addResourceName(String resourceName) {
113
114        m_resourcesNames.add(resourceName);
115    }
116
117    /**
118     * Returns <code>0</code> if the given object is an index source with the same name. <p>
119     *
120     * Note that the name of an index source has to be unique within OpenCms.<p>
121     *
122     * @param obj another index source
123     *
124     * @return <code>0</code> if the given object is an index source with the same name
125     *
126     * @see java.lang.Comparable#compareTo(java.lang.Object)
127     */
128    public int compareTo(CmsSearchIndexSource obj) {
129
130        if (obj == this) {
131            return 0;
132        }
133        return m_name.compareTo(obj.m_name);
134    }
135
136    /**
137     * Two index sources are considered equal if their names as returned by {@link #getName()} is equal.<p>
138     *
139     * Note that the name of an index source has to be unique within OpenCms.<p>
140     *
141     * @see java.lang.Object#equals(java.lang.Object)
142     */
143    @Override
144    public boolean equals(Object obj) {
145
146        if (obj == this) {
147            return true;
148        }
149        if (obj instanceof CmsSearchIndexSource) {
150            return m_name.equals(((CmsSearchIndexSource)obj).m_name);
151        }
152        return false;
153    }
154
155    /**
156     * Returns the list of names (Strings) of the document types to be indexed.<p>
157     *
158     * @return the list of names (Strings) of the document types to be indexed
159     */
160    public List<String> getDocumentTypes() {
161
162        return m_documentTypes;
163    }
164
165    /**
166     * Returns the indexer.<p>
167     *
168     * @return the indexer
169     */
170    public I_CmsIndexer getIndexer() {
171
172        return m_indexer;
173    }
174
175    /**
176     * Returns the class name of the indexer.<p>
177     *
178     * @return the class name of the indexer
179     */
180    public String getIndexerClassName() {
181
182        return m_indexerClassName;
183    }
184
185    /**
186     * Returns the logical key/name of this search index source.<p>
187     *
188     * @return the logical key/name of this search index source
189     */
190    public String getName() {
191
192        return m_name;
193    }
194
195    /**
196     * Returns the value for a specified parameter key.<p>
197     *
198     * @param key the parameter key/name
199     * @return the value for the specified parameter key
200     */
201    public String getParam(String key) {
202
203        return m_params.get(key);
204    }
205
206    /**
207     * Returns the map of optional key/value parameters.<p>
208     *
209     * @return the map of optional key/value parameters
210     */
211    public Map<String, String> getParams() {
212
213        return m_params;
214    }
215
216    /**
217     * Returns the list of VFS resources to be indexed.<p>
218     *
219     * @return the list of VFS resources to be indexed
220     */
221    public List<String> getResourcesNames() {
222
223        return m_resourcesNames;
224    }
225
226    /**
227     * Overriden to be consistents with overridden method
228     * <code>{@link #equals(Object)}</code>.
229     *
230     * @see java.lang.Object#hashCode()
231     */
232    @Override
233    public int hashCode() {
234
235        return m_name.hashCode();
236    }
237
238    /**
239     * Returns <code>true</code> in case the given resource root path is contained in the list of
240     * configured resource names of this index source.<p>
241     *
242     * @param rootPath the resource root path to check
243     *
244     * @return <code>true</code> in case the given resource root path is contained in the list of
245     *       configured resource names of this index source
246     *
247     * @see #getResourcesNames()
248     */
249    public boolean isContaining(String rootPath) {
250
251        if ((rootPath != null) && (m_resourcesNames != null)) {
252            Iterator<String> i = m_resourcesNames.iterator();
253            while (i.hasNext()) {
254                String path = i.next();
255                if (rootPath.startsWith(path)) {
256                    return true;
257                }
258            }
259        }
260        return false;
261    }
262
263    /**
264     * Returns <code>true</code> in case the given resource root path is contained in the list of
265     * configured resource names, and the given document type name is contained in the
266     * list if configured document type names of this index source.<p>
267     *
268     * @param rootPath the resource root path to check
269     * @param documentType the document type factory name to check
270     *
271     * @return <code>true</code> in case the given resource root path is contained in the list of
272     *      configured resource names, and the given document type name is contained in the
273     *      list if configured document type names of this index source
274     *
275     * @see #isContaining(String)
276     * @see #getDocumentTypes()
277     */
278    public boolean isIndexing(String rootPath, String documentType) {
279
280        return m_documentTypes.contains(documentType) && isContaining(rootPath);
281    }
282
283    /**
284     * Removes the name of a document type from the list of configured types of this index source.<p>
285     *
286     * @param key the name of the document type to remove
287     *
288     * @return true if the given document type name was contained before thus could be removed successfully, false otherwise
289     */
290    public boolean removeDocumentType(String key) {
291
292        return m_documentTypes.remove(key);
293    }
294
295    /**
296     * Sets the list of document type names (Strings) to be indexed.<p>
297     *
298     * @param documentTypes the list of document type names (Strings) to be indexed
299     */
300    public void setDocumentTypes(List<String> documentTypes) {
301
302        m_documentTypes = documentTypes;
303    }
304
305    /**
306     * Sets the class name of the indexer.<p>
307     *
308     * An Exception is thrown to allow GUI-display of wrong input.<p>
309     *
310     * @param indexerClassName the class name of the indexer
311     *
312     * @throws CmsIllegalArgumentException if the given String is not a fully qualified classname (within this Java VM)
313     */
314    public void setIndexerClassName(String indexerClassName) throws CmsIllegalArgumentException {
315
316        try {
317            m_indexer = (I_CmsIndexer)Class.forName(indexerClassName).newInstance();
318            m_indexerClassName = indexerClassName;
319        } catch (Exception exc) {
320            if (LOG.isWarnEnabled()) {
321                LOG.warn(
322                    Messages.get().getBundle().key(Messages.LOG_INDEXER_CREATION_FAILED_1, m_indexerClassName),
323                    exc);
324            }
325            throw new CmsIllegalArgumentException(
326                Messages.get().container(
327                    Messages.ERR_INDEXSOURCE_INDEXER_CLASS_NAME_2,
328                    indexerClassName,
329                    I_CmsIndexer.class.getName()));
330        }
331    }
332
333    /**
334     * Sets the logical key/name of this search index source.<p>
335     *
336     * @param name the logical key/name of this search index source
337     *
338     * @throws CmsIllegalArgumentException if argument name is null, an empty or whitespace-only Strings
339     *         or already used for another indexsource's name.
340     */
341    public void setName(String name) throws CmsIllegalArgumentException {
342
343        if (CmsStringUtil.isEmptyOrWhitespaceOnly(name)) {
344            throw new CmsIllegalArgumentException(
345                Messages.get().container(Messages.ERR_INDEXSOURCE_CREATE_MISSING_NAME_0));
346        }
347        // already used? Don't test this at xml-configuration time (no manager)
348        if (OpenCms.getRunLevel() > OpenCms.RUNLEVEL_2_INITIALIZING) {
349            CmsSearchManager mngr = OpenCms.getSearchManager();
350            // don't test this if the indexsource is not new (widget invokes setName even if it was not changed)
351            if (mngr.getIndexSource(name) != this) {
352                if (mngr.getSearchIndexSources().keySet().contains(name)) {
353                    throw new CmsIllegalArgumentException(
354                        Messages.get().container(Messages.ERR_INDEXSOURCE_CREATE_INVALID_NAME_1, name));
355                }
356            }
357        }
358        m_name = name;
359    }
360
361    /**
362     * Sets the map of optional key/value parameters.<p>
363     *
364     * @param params the map of optional key/value parameters
365     */
366    public void setParams(Map<String, String> params) {
367
368        m_params = params;
369    }
370
371    /**
372     * Sets the list of Cms resources to be indexed.<p>
373     *
374     * @param resources the list of Cms resources (Strings) to be indexed
375     */
376    public void setResourcesNames(List<String> resources) {
377
378        m_resourcesNames = resources;
379    }
380}