/* * 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.model.reference; import java.beans.Transient; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; import javax.inject.Provider; import org.xwiki.component.util.DefaultParameterizedType; import org.xwiki.model.EntityType; /** * Represents a reference to a document (wiki, space and page names). * * @version $Id: 475f07867e14e4a8b0280dc87404eb92bce37dc3 $ * @since 2.2M1 */ public class DocumentReference extends EntityReference { /** * The {@link Type} for a {@code Provider<DocumentReference>}. * * @since 7.2M1 */ public static final Type TYPE_PROVIDER = new DefaultParameterizedType(null, Provider.class, DocumentReference.class); /** * Parameter key for the locale. */ static final String LOCALE = "LOCALE"; /** * Cache the {@link LocalDocumentReference} corresponding to this {@link DocumentReference}. */ private LocalDocumentReference localDocumentReference; /** * Special constructor that transforms a generic entity reference into a {@link DocumentReference}. It checks the * validity of the passed reference (ie correct type and correct parent). * * @param reference the reference to convert * @exception IllegalArgumentException if the passed reference is not a valid document reference */ public DocumentReference(EntityReference reference) { super(reference); } /** * Clone an DocumentReference, but replace one of the parent in the chain by a new one. * * @param reference the reference that is cloned * @param oldReference the old parent that will be replaced * @param newReference the new parent that will replace oldReference in the chain * @since 3.3M2 */ protected DocumentReference(EntityReference reference, EntityReference oldReference, EntityReference newReference) { super(reference, oldReference, newReference); } /** * Clone the provided reference and change the Locale. * * @param reference the reference to clone * @param locale the new locale for this reference, if null, locale is removed * @exception IllegalArgumentException if the passed reference is not a valid document reference */ public DocumentReference(EntityReference reference, Locale locale) { super(reference); setLocale(locale); } /** * Create a new Document reference from wiki, space and page name. * * @param wikiName the name of the wiki containing the document, must not be null * @param spaceName the name of the space containing the document, must not be null * @param pageName the name of the document */ public DocumentReference(String wikiName, String spaceName, String pageName) { this(pageName, new SpaceReference(spaceName, new WikiReference(wikiName))); } /** * Create a new Document reference from wiki name, space name, page name and locale. * * @param wikiName the name of the wiki containing the document, must not be null * @param spaceName the name of the space containing the document, must not be null * @param pageName the name of the document * @param locale the locale of the document reference, may be null */ public DocumentReference(String wikiName, String spaceName, String pageName, Locale locale) { this(pageName, new SpaceReference(spaceName, new WikiReference(wikiName)), locale); } /** * Create a new Document reference from wiki name, space name, page name and language. This is an helper function * during transition from language to locale, it will be deprecated ASAP. * * @param wikiName the name of the wiki containing the document, must not be null * @param spaceName the name of the space containing the document, must not be null * @param pageName the name of the document * @param language the language of the document reference, may be null */ public DocumentReference(String wikiName, String spaceName, String pageName, String language) { this(pageName, new SpaceReference(spaceName, new WikiReference(wikiName)), (language == null) ? null : new Locale(language)); } /** * Create a new Document reference from wiki name, spaces names and page name. * * @param wikiName the name of the wiki containing the document, must not be null * @param spaceNames an ordered list of the names of the spaces containing the document from root space to last one, * must not be null * @param pageName the name of the document */ public DocumentReference(String wikiName, List<String> spaceNames, String pageName) { super(pageName, EntityType.DOCUMENT, new SpaceReference(wikiName, spaceNames)); } /** * Create a new Document reference from wiki name, spaces names, page name and locale. * * @param wikiName the name of the wiki containing the document, must not be null * @param spaceNames an ordered list of the names of the spaces containing the document from root space to last one, * must not be null * @param pageName the name of the document reference * @param locale the locale of the document reference, may be null */ public DocumentReference(String wikiName, List<String> spaceNames, String pageName, Locale locale) { super(pageName, EntityType.DOCUMENT, new SpaceReference(wikiName, spaceNames)); setLocale(locale); } /** * Create a new Document reference from document name and parent space. * * @param pageName the name of the document * @param parent the parent space for the document */ public DocumentReference(String pageName, SpaceReference parent) { super(pageName, EntityType.DOCUMENT, parent); } /** * Create a new Document reference from local document reference and wiki reference. * * @param localDocumentReference the document reference without the wiki reference * @param wikiReference the wiki reference * @since 5.1M1 */ public DocumentReference(LocalDocumentReference localDocumentReference, WikiReference wikiReference) { super(localDocumentReference, null, wikiReference); } /** * Create a new Document reference from document name, parent space and locale. * * @param pageName the name of the document * @param parent the parent space for the document * @param locale the locale of the document reference, may be null */ public DocumentReference(String pageName, SpaceReference parent, Locale locale) { super(pageName, EntityType.DOCUMENT, parent); setLocale(locale); } /** * {@inheritDoc} * <p> * Overridden in order to verify the validity of the passed parent. * </p> * * @see org.xwiki.model.reference.EntityReference#setParent(EntityReference) * @exception IllegalArgumentException if the passed parent is not a valid document reference parent (ie a space * reference) */ @Override protected void setParent(EntityReference parent) { if (parent instanceof SpaceReference) { super.setParent(parent); return; } if (parent == null || parent.getType() != EntityType.SPACE) { throw new IllegalArgumentException("Invalid parent reference [" + parent + "] in a document reference"); } super.setParent(new SpaceReference(parent)); } /** * {@inheritDoc} * <p> * Overridden in order to verify the validity of the passed type. * </p> * * @see org.xwiki.model.reference.EntityReference#setType(org.xwiki.model.EntityType) * @exception IllegalArgumentException if the passed type is not a document type */ @Override protected void setType(EntityType type) { if (type != EntityType.DOCUMENT) { throw new IllegalArgumentException("Invalid type [" + type + "] for a document reference"); } super.setType(EntityType.DOCUMENT); } /** * Set the locale of this document reference. * * @param locale the locale of this document reference */ protected void setLocale(Locale locale) { setParameter(LOCALE, locale); } /** * @return the locale of this document reference */ public Locale getLocale() { return (Locale) getParameter(LOCALE); } /** * @return the wiki reference of this document reference */ @Transient public WikiReference getWikiReference() { return (WikiReference) extractReference(EntityType.WIKI); } /** * Create a new DocumentReference with passed wiki reference. * * @param wikiReference the wiki reference to use * @return a new document reference or the same if the passed wiki is already the current wiki * @since 7.2M1 */ @Transient public DocumentReference setWikiReference(WikiReference wikiReference) { WikiReference currentWikiReferene = getWikiReference(); if (currentWikiReferene.equals(wikiReference)) { return this; } return new DocumentReference(this, currentWikiReferene, wikiReference); } /** * @return the space reference of the last space containing this document */ @Transient public SpaceReference getLastSpaceReference() { return (SpaceReference) extractReference(EntityType.SPACE); } /** * @return space references of this document in an ordered list */ @Transient public List<SpaceReference> getSpaceReferences() { List<SpaceReference> references = new ArrayList<SpaceReference>(); EntityReference reference = this; while (reference != null) { if (reference.getType() == EntityType.SPACE) { references.add((SpaceReference) reference); } reference = reference.getParent(); } // Reverse the array so that the last entry is the parent of the Document Reference Collections.reverse(references); return references; } @Override public DocumentReference replaceParent(EntityReference oldParent, EntityReference newParent) { return new DocumentReference(this, oldParent, newParent); } /** * @return the {@link LocalDocumentReference} corresponding to this {@link DocumentReference} * @since 8.3 * @deprecated since 9.3RC1/8.4.5, use {@link #getLocalDocumentReference()} instead */ @Deprecated public LocalDocumentReference getLocaleDocumentReference() { return getLocalDocumentReference(); } /** * @return the {@link LocalDocumentReference} corresponding to this {@link DocumentReference} * @since 9.3RC1 * @since 8.4.5 */ public LocalDocumentReference getLocalDocumentReference() { if (this.localDocumentReference == null) { this.localDocumentReference = new LocalDocumentReference(this); } return this.localDocumentReference; } @Override public String toString() { // Compared to EntityReference we don't print the type since the type is already indicated by the fact that // this is a DocumentReference instance. return TOSTRING_SERIALIZER.serialize(this); } }