/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This 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 software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.xwiki.search.solr.internal.api;
import java.util.Locale;
/**
* Contains constants naming the Solr/Lucene index fields used by this module for indexing entities. Also contains
* additional constants used for composing field names on multilingual fields.
* <p>
* A multilingual and virtual/alias field, is not stored in the index with the specified name. It is only used at query
* time and it is expanded automatically to the actual fields from the index.
* <p>
* Example: "title" becomes "title_ | title_en | title_ro | title_fr | etc..."
* <p>
* <b>Note</b>: When indexing a field, the actual field name must be used instead of the virtual field name.
*
* @version $Id: a09fdf7f572527e2bc756e8293df5fbd7e00bf86 $
* @since 5.1M2
*/
public final class FieldUtils
{
/**
* The suffix added to the fields used for sorting.
*/
public static final String SORT_SUFFIX = "_sort";
/**
* Keyword field, holds a string uniquely identifying a document across the index. This is used for finding old
* versions of a document to be indexed. The value format is wiki:Space.Page_locale .
*/
public static final String ID = "id";
/**
* Language of the document.
*/
public static final String LANGUAGE = "language";
/**
* The real/calculated locale of the document (the default locale in default document entry case).
*/
public static final String LOCALE = "locale";
/**
* Technical locale of the document (empty for the default document entry). Not indexed, mostly used to find the
* document in database.
*/
public static final String DOCUMENT_LOCALE = "doclocale";
/**
* The list of Locales covered by this entity. Dynamically determined from the list of enabled Locales and the
* various Locales of the associated wiki document.
*/
public static final String LOCALES = "locales";
/**
* Keyword field, holds the name of the virtual wiki a document belongs to.
*/
public static final String WIKI = "wiki";
/**
* The local reference of the space the document belongs to. For a document {@code A.B.C.Page} the value of this
* field is {@code A.B.C}. This field is analyzed and thus used for free text search.
*
* @deprecated since 7.2, use {@link #SPACES} instead; the problem with this field is that the standard tokenizer
* doesn't split around dots, and even if it did, it would also split around escaped dots (e.g.
* {@code A.B\.1.C}) which is not what we want.
* @see <a href="https://jira.xwiki.org/browse/XWIKI-12594">XWIKI-12594: The path of a nested document is not
* properly matched</a>
*/
@Deprecated
public static final String SPACE = "space";
/**
* The names of all the nested spaces the document belongs to. For a document {@code A.B.C.Page} the value of this
* field will be {@code ['A', 'B', 'C']}. This field is used for free text search.
*/
public static final String SPACES = "spaces";
/**
* The local space reference, unanalyzed and not stored, used for exact matching.
*/
public static final String SPACE_EXACT = "space_exact";
/**
* This field is used for hierarchical faceting on nested spaces (using 'facet.prefix'-based drill down). E.g. for a
* document A.B.C.Page this field will hold ['0/A.', '1/A.B.', '2/A.B.C.']
*
* @see <a href='https://wiki.apache.org/solr/HierarchicalFaceting'>Hierarchical Faceting</a>
* @since 7.2RC1
*/
public static final String SPACE_FACET = "space_facet";
/**
* This field is used to match descendant documents. A query such as {@code space_prefix:A.B} will match the
* documents from space A.B and all its descendants (like A.B.C). This is possible because this field holds the
* local references of all the ancestor spaces of a document (i.e. all the prefixes of the space reference). E.g.
* for a document A.B.C.Page this field will hold ['A', 'A.B', 'A.B.C']. As a consequence, searching for
* {@code space_prefix:A.B} will match A.B.C.Page
*
* @since 7.2RC1
*/
public static final String SPACE_PREFIX = "space_prefix";
/**
* Name of the document.
*/
public static final String NAME = "name";
/**
* Unanalyzed and not stored version of the document's name.
*/
public static final String NAME_EXACT = "name_exact";
/**
* FullName of the document (example: {@code Main.WebHome}).
*/
public static final String FULLNAME = "fullname";
/**
* Title of the document.
* <p>
* Note: Multilingual and virtual field.
*/
public static final String TITLE = "title";
/**
* Lowercased, unanalyzed and not stored version of the document's title, used for sorting.
*/
public static final String TITLE_SORT = TITLE + SORT_SUFFIX;
/**
* Version of the document (example: {@code 4.2}).
*/
public static final String VERSION = "version";
/**
* For storing the comment associated to the version.
* <p>
* Note: Multilingual and virtual field.
*/
public static final String COMMENT = "comment";
/**
* Type of a document. "DOCUMENT", "ATTACHMENT", "OBJECT" and "OBJECT_PROPERTY" are the used values corresponding to
* the values from {@link org.xwiki.model.EntityType}.
*/
public static final String TYPE = "type";
/**
* Used to index XClass names.
* <ul>
* <li>document: the type of objects a document has, e.g. [Blog.BlogPostClass, XWiki.TagClass, ..]</li>
* <li>object: the object type</li>
* <li>object property: the type of object this property belongs to</li>.
* </ul>
*/
public static final String CLASS = "class";
/**
* XWiki object number, only used for objects and properties.
*/
public static final String NUMBER = "number";
/**
* XWiki object content. Used by objects to index their properties and by documents to index all the properties of
* the contained objects.
* <p>
* Note: Multilingual and virtual field.
*/
public static final String OBJECT_CONTENT = "objcontent";
/**
* Last modifier.
*/
public static final String AUTHOR = "author";
/**
* Last modifier, in its display version (i.e., "first_name last_name").
*/
public static final String AUTHOR_DISPLAY = "author_display";
/**
* Lowercased, unanalyzed and not stored version of the document's last author display version, used for sorting.
*/
public static final String AUTHOR_DISPLAY_SORT = AUTHOR_DISPLAY + SORT_SUFFIX;
/**
* Creator of the document.
*/
public static final String CREATOR = "creator";
/**
* Creator of the document, in its display version (i.e., "first_name last_name").
*/
public static final String CREATOR_DISPLAY = "creator_display";
/**
* Date of last modification.
*/
public static final String DATE = "date";
/**
* Date of creation.
*/
public static final String CREATIONDATE = "creationdate";
/**
* Document hidden flag.
*/
public static final String HIDDEN = "hidden";
/**
* Document score, not an actual field. It's only computed at query time.
*/
public static final String SCORE = "score";
/**
* Fulltext plain rendered content.
* <p>
* Note: Multilingual and virtual field.
*/
public static final String DOCUMENT_RENDERED_CONTENT = "doccontent";
/**
* Raw content.
*/
public static final String DOCUMENT_RAW_CONTENT = "doccontentraw";
/**
* Attachment content.
* <p>
* Note: Multilingual and virtual field.
*/
public static final String ATTACHMENT_CONTENT = "attcontent";
/**
* Attachment version.
*/
public static final String ATTACHMENT_VERSION = "attversion";
/**
* The date when the last version of the attachment was uploaded.
*/
public static final String ATTACHMENT_DATE = "attdate";
/**
* Same as {@link #ATTACHMENT_DATE} but single valued so that it can be used for sorting.
*/
public static final String ATTACHMENT_DATE_SORT = ATTACHMENT_DATE + SORT_SUFFIX;
/**
* The size in bytes of the last version of the attachment.
*/
public static final String ATTACHMENT_SIZE = "attsize";
/**
* Same as {@link #ATTACHMENT_SIZE} but single valued so that it can be used for sorting.
*/
public static final String ATTACHMENT_SIZE_SORT = ATTACHMENT_SIZE + SORT_SUFFIX;
/**
* The user that uploaded the last version of the attachment.
*/
public static final String ATTACHMENT_AUTHOR = "attauthor";
/**
* The display name of the user that uploaded the last version of the attachment.
*/
public static final String ATTACHMENT_AUTHOR_DISPLAY = ATTACHMENT_AUTHOR + "_display";
/**
* Same as {@link #ATTACHMENT_AUTHOR_DISPLAY} but used for sorting.
*/
public static final String ATTACHMENT_AUTHOR_DISPLAY_SORT = ATTACHMENT_AUTHOR_DISPLAY + SORT_SUFFIX;
/**
* For storing mimetype of the attachments.
*/
public static final String MIME_TYPE = "mimetype";
/**
* Filename, only used for attachments.
*/
public static final String FILENAME = "filename";
/**
* The attachment file name, used for sorting.
*/
public static final String FILENAME_SORT = FILENAME + SORT_SUFFIX;
/**
* For storing property name.
*/
public static final String PROPERTY_NAME = "propertyname";
/**
* For storing property value.
* <p>
* Note: Multilingual and virtual field.
*/
public static final String PROPERTY_VALUE = "propertyvalue";
/**
* Underscore character, used to separate the field name from the suffix.
*/
public static final String USCORE = "_";
/**
* Utility class.
*/
private FieldUtils()
{
}
/**
* Format string for multilingual fields.
*
* @param field the field name
* @param locale the locale of the content of the field
* @return the localized version of the field name
*/
public static String getFieldName(String field, Locale locale)
{
StringBuilder builder = new StringBuilder(field);
builder.append(USCORE);
if (locale != null) {
if (locale.equals(Locale.ROOT)) {
builder.append(USCORE);
} else {
builder.append(locale);
}
}
return builder.toString();
}
/**
* Get the name of a dynamic field based on its type or the given locale. If the field type is specified then it is
* suffixed to the field name so that its value is indexed properly (see schema.xml). Otherwise, the locale is
* suffixed to the field name so that the field text content is indexed based on the specified locale.
*
* @param prefix the field name prefix
* @param type the field type
* @param locale the locale of the field value in case the type is not specified
* @return the name that should be used for the specified field in order for its value to be indexed correctly
*/
public static String getFieldName(String prefix, String type, Locale locale)
{
if (type != null) {
return prefix + FieldUtils.USCORE + type;
} else {
return FieldUtils.getFieldName(prefix, locale);
}
}
}