/* * This library is part of OpenCms - * the Open Source Content Management System * * Copyright (c) Alkacon Software GmbH (http://www.alkacon.com) * * 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. * * For further information about Alkacon Software, please see the * company website: http://www.alkacon.com * * For further information about OpenCms, please see the * project website: http://www.opencms.org * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.opencms.search.fields; import org.opencms.file.CmsObject; import org.opencms.file.CmsProject; import org.opencms.file.CmsProperty; import org.opencms.file.CmsResource; import org.opencms.file.CmsUser; import org.opencms.file.I_CmsResource; import org.opencms.i18n.CmsMessageContainer; import org.opencms.main.CmsRuntimeException; import org.opencms.search.Messages; import org.opencms.search.extractors.I_CmsExtractionResult; import org.opencms.util.CmsStringUtil; import java.text.ParseException; import java.util.Date; import java.util.List; import org.apache.lucene.document.DateTools; /** * Describes a mapping of a piece of content from an OpenCms VFS resource to a field of a search index.<p> * * @since 7.0.0 */ public class CmsSearchFieldMapping { /** Default for expiration date since Long.MAX_VALUE is to big. */ protected static final String DATE_EXPIRED_DEFAULT_STR = "21000101"; /** The default expiration date. */ private static Date m_defaultDateExpired; /** The configured default value. */ private String m_defaultValue; /** Pre-calculated hash value. */ private int m_hashCode; /** The parameter for the mapping type. */ private String m_param; /** The mapping type. */ private CmsSearchFieldMappingType m_type; /** * Public constructor for a new search field mapping.<p> */ public CmsSearchFieldMapping() { // no initialization required } /** * Public constructor for a new search field mapping.<p> * * @param type the type to use, see {@link #setType(CmsSearchFieldMappingType)} * @param param the mapping parameter, see {@link #setParam(String)} */ public CmsSearchFieldMapping(CmsSearchFieldMappingType type, String param) { this(); setType(type); setParam(param); } /** * Returns the default expiration date, meaning the resource never expires.<p> * * @return the default expiration date * * @throws ParseException if something goes wrong parsing the default date string */ public static Date getDefaultDateExpired() throws ParseException { if (m_defaultDateExpired == null) { m_defaultDateExpired = DateTools.stringToDate(DATE_EXPIRED_DEFAULT_STR); } return m_defaultDateExpired; } /** * Two mappings are equal if the type and the parameter is equal.<p> * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj instanceof CmsSearchFieldMapping) { CmsSearchFieldMapping other = (CmsSearchFieldMapping)obj; return CmsStringUtil.isEqual(m_type, other.m_type) && CmsStringUtil.isEqual(m_param, other.m_param); } return false; } /** * Returns the default value used for this field mapping in case no content is available.<p> * * @return the default value used for this field mapping in case no content is available */ public String getDefaultValue() { return m_defaultValue; } /** * Returns the mapping parameter.<p> * * The parameter is used depending on the implementation of the rules of * the selected {@link CmsSearchFieldMappingType}.<p> * * @return the mapping parameter */ public String getParam() { return m_param; } /** * Returns the String value extracted form the provided data according to the rules of this mapping type.<p> * * @param cms the OpenCms context used for building the search index * @param res the resource that is indexed * @param extractionResult the plain text extraction result from the resource * @param properties the list of all properties directly attached to the resource (not searched) * @param propertiesSearched the list of all searched properties of the resource * * @return the String value extracted form the provided data according to the rules of this mapping type */ public String getStringValue( CmsObject cms, CmsResource res, I_CmsExtractionResult extractionResult, List<CmsProperty> properties, List<CmsProperty> propertiesSearched) { String content = null; switch (getType().getMode()) { case 0: // content if (extractionResult != null) { content = extractionResult.getContent(); } break; case 1: // property case 2: // property-search if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(getParam())) { boolean search = (getType() == CmsSearchFieldMappingType.PROPERTY_SEARCH); if (search) { content = CmsProperty.get(getParam(), propertiesSearched).getValue(); } else { content = CmsProperty.get(getParam(), properties).getValue(); } } break; case 3: // item if ((extractionResult != null) && CmsStringUtil.isNotEmptyOrWhitespaceOnly(getParam())) { content = extractionResult.getContentItems().get(getParam()); } break; case 5: // attribute if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(getParam())) { I_CmsResource.CmsResourceAttribute attribute = null; try { attribute = I_CmsResource.CmsResourceAttribute.valueOf(getParam()); } catch (Exception e) { // invalid attribute name specified, attribute will be null } if (attribute != null) { // map all attributes for a resource switch (attribute) { case dateContent: content = DateTools.timeToString(res.getDateContent(), DateTools.Resolution.MILLISECOND); break; case dateCreated: content = DateTools.timeToString(res.getDateCreated(), DateTools.Resolution.MILLISECOND); break; case dateExpired: long expirationDate = res.getDateExpired(); if (expirationDate == CmsResource.DATE_EXPIRED_DEFAULT) { // default of Long.MAX_VALUE is to big, use January 1, 2100 instead content = DATE_EXPIRED_DEFAULT_STR; } else { content = DateTools.timeToString(expirationDate, DateTools.Resolution.MILLISECOND); } break; case dateLastModified: content = DateTools.timeToString( res.getDateLastModified(), DateTools.Resolution.MILLISECOND); break; case dateReleased: content = DateTools.timeToString( res.getDateReleased(), DateTools.Resolution.MILLISECOND); break; case flags: content = String.valueOf(res.getFlags()); break; case length: content = String.valueOf(res.getLength()); break; case name: content = res.getName(); break; case projectLastModified: try { CmsProject project = cms.readProject(res.getProjectLastModified()); content = project.getName(); } catch (Exception e) { // NOOP, content is already null } break; case resourceId: content = res.getResourceId().toString(); break; case rootPath: content = res.getRootPath(); break; case siblingCount: content = String.valueOf(res.getSiblingCount()); break; case state: content = res.getState().toString(); break; case structureId: content = res.getStructureId().toString(); break; case typeId: content = String.valueOf(res.getTypeId()); break; case userCreated: try { CmsUser user = cms.readUser(res.getUserCreated()); content = user.getName(); } catch (Exception e) { // NOOP, content is already null } break; case userLastModified: try { CmsUser user = cms.readUser(res.getUserLastModified()); content = user.getName(); } catch (Exception e) { // NOOP, content is already null } break; case version: content = String.valueOf(res.getVersion()); break; default: // NOOP, content is already null } } } break; default: // NOOP, content is already null } if (content == null) { // in case the content is not available, use the default value for this mapping content = getDefaultValue(); } return content; } /** * Returns the mapping type.<p> * * @return the mapping type */ public CmsSearchFieldMappingType getType() { return m_type; } /** * The hash code depends on the type and the parameter.<p> * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { if (m_hashCode == 0) { int hashCode = 73 * ((m_type == null) ? 29 : m_type.hashCode()); if (m_param != null) { hashCode += m_param.hashCode(); } m_hashCode = hashCode; } return m_hashCode; } /** * Sets the default value for this field mapping in case no content is available.<p> * * @param defaultValue the default value to set */ public void setDefaultValue(String defaultValue) { if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(defaultValue)) { m_defaultValue = defaultValue.trim(); } else { m_defaultValue = null; } } /** * Sets the mapping parameter.<p> * * The parameter is used depending on the implementation of the rules of * the selected {@link CmsSearchFieldMappingType}.<p> * * @param param the parameter to set */ public void setParam(String param) { if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(param)) { m_param = param.trim(); } else { m_param = null; } } /** * Sets the mapping type.<p> * * @param type the type to set */ public void setType(CmsSearchFieldMappingType type) { m_type = type; } /** * Sets the mapping type as a String.<p> * * @param type the name of the type to set */ public void setType(String type) { CmsSearchFieldMappingType mappingType = CmsSearchFieldMappingType.valueOf(type); if (mappingType == null) { // invalid mapping type has been used, throw an exception throw new CmsRuntimeException(new CmsMessageContainer( Messages.get(), Messages.ERR_FIELD_TYPE_UNKNOWN_1, new Object[] {type})); } setType(mappingType); } }