/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */
package org.apache.lenya.cms.publication;

import java.util.Arrays;
import java.util.StringTokenizer;

import org.apache.commons.lang.Validate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.excalibur.source.SourceResolver;
import org.apache.lenya.cms.metadata.MetaDataCache;
import org.apache.lenya.cms.repository.NodeFactory;
import org.apache.lenya.cms.repository.RepositoryException;
import org.apache.lenya.cms.repository.RepositoryItem;
import org.apache.lenya.cms.repository.RepositoryItemFactory;
import org.apache.lenya.cms.repository.SessionHolder;
import org.apache.lenya.utils.URLInformation;
/**
 * A DocumentIdentityMap avoids the multiple instanciation of a document object.
 * 
 * @version $Id: DocumentIdentityMap.java 264153 2005-08-29 15:11:14Z andreas $
 */
public class DocumentFactoryImpl implements DocumentFactory, RepositoryItemFactory {

    private static final Log logger = LogFactory.getLog(DocumentFactoryImpl.class);

    private Session session;
    private MetaDataCache metaDataCache;
    private SourceResolver sourceResolver;
    private NodeFactory nodeFactory;
    private ResourceTypeResolver resourceTypeResolver;
    
    /**
     * @return The session.
     */
    public Session getSession() {
        return this.session;
    }

    /**
     * Ctor.
     * @param session The session to use.
     */
    public DocumentFactoryImpl(Session session) {
        this.session = session;
    }

    /**
     * Returns a document.
     * @param publication The publication.
     * @param area The area.
     * @param uuid The document UUID.
     * @param language The language.
     * @return A document.
     * @throws ResourceNotFoundException if an error occurs.
     */
    public Document get(Publication publication, String area, String uuid, String language)
            throws ResourceNotFoundException {
        return get(publication, area, uuid, language, -1);
    }

    public Document get(Publication publication, String area, String uuid, String language,
            int revision) throws ResourceNotFoundException {
        if (logger.isDebugEnabled())
            logger.debug(
                    "DocumentIdentityMap::get() called on publication [" + publication.getId()
                            + "], area [" + area + "], UUID [" + uuid + "], language [" + language
                            + "]");

        String key = getKey(publication, area, uuid, language, revision);

        if (logger.isDebugEnabled())
            logger.debug(
                    "DocumentIdentityMap::get() got key [" + key + "] from DocumentFactory");

        try {
            return (Document) getRepositorySession().getRepositoryItem(this, key);
        } catch (RepositoryException e) {
            throw new ResourceNotFoundException(e);
        }
    }

    protected org.apache.lenya.cms.repository.Session getRepositorySession() {
        SessionHolder holder = (SessionHolder) this.session;
        return holder.getRepositorySession();
    }

    /**
     * Returns the document identified by a certain web application URL.
     * @param webappUrl The web application URL.
     * @return A document.
     * @throws ResourceNotFoundException if an error occurs.
     */
    public Document getFromURL(String webappUrl) throws ResourceNotFoundException {
        String key = getKey(webappUrl);
        try {
            return (Document) getRepositorySession().getRepositoryItem(this, key);
        } catch (RepositoryException e) {
            throw new ResourceNotFoundException(e);
        }
    }

    /**
     * Builds a clone of a document for another language.
     * @param document The document to clone.
     * @param language The language of the target document.
     * @return A document.
     * @throws DocumentBuildException if an error occurs.
     */
  //florent : seems never use, imply cyclic dependencies
    /*
    public Document getLanguageVersion(Document document, String language)
            throws DocumentBuildException {
        return get(document.getPublication(), document.getArea(), document.getUUID(), language);
    }*/

    /**
     * Builds a clone of a document for another area.
     * @param document The document to clone.
     * @param area The area of the target document.
     * @return A document.
     * @throws ResourceNotFoundException if an error occurs.
     */
    //florent : seems never use, imply cyclic dependencies
    /*
    public Document getAreaVersion(Document document, String area) throws ResourceNotFoundException {
        return get(document.getPublication(), area, document.getUUID(), document.getLanguage());
    }*/

    /**
     * Builds a document for the default language.
     * @param publication The publication.
     * @param area The area.
     * @param documentId The document ID.
     * @return A document.
     * @throws ResourceNotFoundException if an error occurs.
     */
    public Document get(Publication publication, String area, String documentId)
            throws ResourceNotFoundException {
        return get(publication, area, documentId, publication.getDefaultLanguage());
    }

    /**
     * Checks if a string represents a valid document ID.
     * @param id The string.
     * @return A boolean value.
     */
    public boolean isValidDocumentId(String id) {

        if (!id.startsWith("/")) {
            return false;
        }

        String[] snippets = id.split("/");

        if (snippets.length < 2) {
            return false;
        }

        for (int i = 1; i < snippets.length; i++) {
            if (!snippets[i].matches("[a-zA-Z0-9\\-]+")) {
                return false;
            }
        }

        return true;
    }

    /**
     * Checks if a webapp URL represents a document.
     * @param webappUrl A web application URL.
     * @return A boolean value.
     * @throws ResourceNotFoundException if an error occurs.
     */
    public boolean isDocument(String webappUrl) throws ResourceNotFoundException {
        Validate.notNull(webappUrl);
        try {
            //florent URLInformation info = new URLInformation(webappUrl);
        	URLInformation info = new URLInformation();
            String pubId = info.getPublicationId();
            String[] pubIds = getPublicationIds();
            if (pubId != null && Arrays.asList(pubIds).contains(pubId)) {
                Publication pub = getPublication(pubId);
                DocumentBuilder builder = pub.getDocumentBuilder();
                return builder.isDocument(this.session, webappUrl);
            } else {
                return false;
            }
        } catch (PublicationException e) {
            throw new ResourceNotFoundException(e);
        }
    }

    /**
     * Builds a document key.
     * @param publication The publication.
     * @param area The area.
     * @param uuid The document UUID.
     * @param language The language.
     * @param revision
     * @return A key.
     */
    public String getKey(Publication publication, String area, String uuid, String language,
            int revision) {
        Validate.notNull(publication);
        Validate.notNull(area);
        Validate.notNull(uuid);
        Validate.notNull(language);
        return publication.getId() + ":" + area + ":" + uuid + ":" + language + ":" + revision;
    }

    /**
     * Builds a document key.
     * @param webappUrl The web application URL.
     * @return A key.
     */
    public String getKey(String webappUrl) {
        Validate.notNull(webappUrl);
        try {
            if (!isDocument(webappUrl)) {
                throw new RuntimeException("No document for URL [" + webappUrl + "] found.");
            }
            DocumentLocator locator = getLocator(webappUrl);
            Publication publication = getPublication(locator.getPublicationId());
            String area = locator.getArea();
            String uuid = publication.getArea(area).getSite().getNode(locator.getPath()).getUuid();
            return getKey(publication, area, uuid, locator.getLanguage(), -1);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    protected DocumentLocator getLocator(String webappUrl) {
        DocumentLocator locator;
        try {
            //florent URLInformation info = new URLInformation(webappUrl);
        	URLInformation info = new URLInformation();
            Publication publication = getPublication(info.getPublicationId());
            DocumentBuilder builder = publication.getDocumentBuilder();
            locator = builder.getLocator(this.session, webappUrl);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return locator;
    }

    /**
     * @see org.apache.lenya.transaction.IdentifiableFactory#build(org.apache.lenya.transaction.IdentityMap,
     *      java.lang.String)
     */
    public RepositoryItem buildItem(org.apache.lenya.cms.repository.Session session, String key) throws RepositoryException {
        if (logger.isDebugEnabled())
            logger.debug("DocumentFactory::build() called with key [" + key + "]");

        StringTokenizer tokenizer = new StringTokenizer(key, ":");
        String publicationId = tokenizer.nextToken();
        String area = tokenizer.nextToken();
        String uuid = tokenizer.nextToken();
        String language = tokenizer.nextToken();
        String revisionString = tokenizer.nextToken();
        int revision = Integer.valueOf(revisionString).intValue();

        DocumentImpl document;
        try {
            Publication publication = getPublication(publicationId);
            DocumentBuilder builder = publication.getDocumentBuilder();
            DocumentIdentifier identifier = new DocumentIdentifierImpl(publicationId, area, uuid,
                    language);
            document = buildDocument(identifier, revision, builder);
        } catch (Exception e) {
            throw new RepositoryException(e);
        }
        if (logger.isDebugEnabled())
            logger.debug("DocumentFactory::build() done.");

        return document;
    }

    protected DocumentImpl buildDocument(DocumentIdentifier identifier, int revision,
            DocumentBuilder builder) throws DocumentBuildException {
        return createDocument(identifier, revision, builder);
    }

    /**
     * Creates a new document object. Override this method to create specific document objects,
     * e.g., for different document IDs.
     * @param identifier The identifier.
     * @param revision The revision or -1 for the latest revision.
     * @param builder The document builder.
     * @return A document.
     * @throws DocumentBuildException when something went wrong.
     */
    protected DocumentImpl createDocument(DocumentIdentifier identifier, int revision,
            DocumentBuilder builder) throws DocumentBuildException {
        DocumentImpl doc = new DocumentImpl(session, identifier, revision);
        doc.setMetaDataCache(getMetaDataCache());
        doc.setSourceResolver(getSourceResolver());
        doc.setNodeFactory(this.nodeFactory);
        doc.setResourceTypeResolver(this.resourceTypeResolver);
        return doc;
    }

    public Document get(DocumentIdentifier identifier) throws ResourceNotFoundException {
        try {
            Publication pub = getPublication(identifier.getPublicationId());
            return get(pub, identifier.getArea(), identifier.getUUID(), identifier.getLanguage());
        } catch (PublicationException e) {
            throw new ResourceNotFoundException(e);
        }
    }

    public String getItemType() {
        return Document.TRANSACTIONABLE_TYPE;
    }

    public Publication getPublication(String id) throws PublicationException {
        return getPublicationManager().getPublication(this, id);
    }

    public String[] getPublicationIds() {
        return getPublicationManager().getPublicationIds();
    }

    private PublicationManager pubManager;

    public void setPublicationManager(PublicationManager pubManager) {
        this.pubManager = pubManager;
    }

    public PublicationManager getPublicationManager() {
        return this.pubManager;
    }

    public boolean existsPublication(String id) {
        return Arrays.asList(getPublicationManager().getPublicationIds()).contains(id);
    }

    protected MetaDataCache getMetaDataCache() {
        return metaDataCache;
    }

    public void setMetaDataCache(MetaDataCache metaDataCache) {
        this.metaDataCache = metaDataCache;
    }

    public SourceResolver getSourceResolver() {
        return sourceResolver;
    }

    public void setSourceResolver(SourceResolver sourceResolver) {
        this.sourceResolver = sourceResolver;
    }

    public void setNodeFactory(NodeFactory nodeFactory) {
        Validate.notNull(nodeFactory, "node factory");
        this.nodeFactory = nodeFactory;
    }

    public void setResourceTypeResolver(ResourceTypeResolver resourceTypeResolver) {
        this.resourceTypeResolver = resourceTypeResolver;
    }

}