blob: 695e1adf3ecb60622ecb850cde6bd53673c41842 [file] [log] [blame]
/*
* 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.site.tree2;
import java.util.ArrayList;
import java.util.List;
import org.apache.lenya.cms.publication.Area;
import org.apache.lenya.cms.publication.Document;
import org.apache.lenya.cms.publication.DocumentException;
import org.apache.lenya.cms.publication.DocumentFactory;
import org.apache.lenya.cms.publication.DocumentLocator;
import org.apache.lenya.cms.publication.Publication;
import org.apache.lenya.cms.publication.PublicationException;
import org.apache.lenya.cms.repository.RepositoryItemFactory;
import org.apache.lenya.cms.site.AbstractSiteManager;
import org.apache.lenya.cms.site.Link;
import org.apache.lenya.cms.site.NodeSet;
import org.apache.lenya.cms.site.SiteException;
import org.apache.lenya.cms.site.SiteNode;
import org.apache.lenya.cms.site.SiteStructure;
import org.apache.lenya.cms.site.tree.SiteTree;
import org.apache.lenya.cms.site.tree.SiteTreeNode;
/**
* Tree-based site manager.
*/
public class TreeSiteManager extends AbstractSiteManager {
/**
* Returns the sitetree for a specific area of this publication. Sitetrees are created on demand
* and are cached.
*
* @param area The area.
* @return A site tree.
* @throws SiteException if an error occurs.
*/
protected SiteTree getTree(Area area) throws SiteException {
String key = getKey(area);
SiteTree sitetree;
RepositoryItemFactory factory = new SiteTreeFactory(this.manager, getLogger());
try {
sitetree = (SiteTree) area.getPublication().getFactory().getSession()
.getRepositoryItem(factory, key);
} catch (Exception e) {
throw new SiteException(e);
}
return sitetree;
}
/**
* @param area The area.
* @return The key to store sitetree objects in the identity map.
*/
protected String getKey(Area area) {
return area.getPublication().getId() + ":" + area.getName();
}
public void add(String path, Document doc) throws SiteException {
getTree(doc.area()).add(path, doc);
}
public boolean contains(Document doc) throws SiteException {
return getTree(doc.area()).containsByUuid(doc.getUUID(), doc.getLanguage());
}
public boolean containsInAnyLanguage(Document doc) throws SiteException {
return getTree(doc.area()).containsInAnyLanguage(doc.getUUID());
}
public void copy(Document srcDoc, Document destDoc) throws SiteException {
SiteTree destinationTree = getTree(destDoc.area());
try {
TreeNodeImpl sourceNode = (TreeNodeImpl) srcDoc.getLink().getNode();
SiteTreeNode[] siblings = sourceNode.getNextSiblings();
SiteNode parent = sourceNode.getParent();
String parentId = "";
if (parent != null) {
parentId = parent.getPath();
}
TreeNodeImpl sibling = null;
String siblingPath = null;
// same UUID -> insert at the same position
if (srcDoc.getUUID().equals(destDoc.getUUID())) {
for (int i = 0; i < siblings.length; i++) {
String path = parentId + "/" + siblings[i].getName();
sibling = (TreeNodeImpl) destinationTree.getNode(path);
if (sibling != null) {
siblingPath = path;
break;
}
}
}
if (!sourceNode.hasLink(srcDoc.getLanguage())) {
// the node that we're trying to publish
// doesn't have this language
throw new SiteException("The node " + srcDoc.getPath()
+ " doesn't contain a label for language " + srcDoc.getLanguage());
}
String destPath = destDoc.getPath();
Link link = sourceNode.getLink(srcDoc.getLanguage());
SiteNode destNode = destinationTree.getNode(destPath);
if (destNode == null) {
if (siblingPath == null) {
// called for side effect of add, not return result
destNode = destinationTree.add(destPath);
} else {
// called for side effect of add, not return result
destNode = destinationTree.add(destPath, siblingPath);
}
destinationTree.add(destPath, destDoc);
} else {
destDoc.getLink().setLabel(link.getLabel());
}
} catch (DocumentException e) {
throw new SiteException(e);
}
}
public DocumentLocator getAvailableLocator(DocumentFactory factory, DocumentLocator locator)
throws SiteException {
return DocumentLocator.getLocator(locator.getPublicationId(), locator.getArea(),
computeUniquePath(factory, locator), locator.getLanguage());
}
/**
* compute an unique document id
* @param factory The factory.
* @param locator The locator.
* @return the unique documentid
* @throws SiteException if an error occurs.
*/
protected String computeUniquePath(DocumentFactory factory, DocumentLocator locator)
throws SiteException {
String path = locator.getPath();
Publication pub;
SiteTree tree;
try {
pub = factory.getPublication(locator.getPublicationId());
tree = getTree(pub.getArea(locator.getArea()));
} catch (PublicationException e) {
throw new SiteException(e);
}
String suffix = null;
int version = 0;
String idwithoutsuffix = null;
if (tree.contains(path)) {
int n = path.lastIndexOf("/");
String lastToken = "";
String substring = path;
lastToken = path.substring(n);
substring = path.substring(0, n);
int l = lastToken.length();
int index = lastToken.lastIndexOf("-");
if (0 < index && index < l && lastToken.substring(index + 1).matches("[\\d]*")) {
suffix = lastToken.substring(index + 1);
idwithoutsuffix = substring + lastToken.substring(0, index);
version = Integer.parseInt(suffix);
} else {
idwithoutsuffix = substring + lastToken;
}
while (tree.contains(path)) {
version = version + 1;
path = idwithoutsuffix + "-" + version;
}
}
return path;
}
public Document[] getDocuments(DocumentFactory factory, Publication pub, String area)
throws SiteException {
Area areaObj;
try {
areaObj = pub.getArea(area);
} catch (PublicationException e) {
throw new SiteException(e);
}
SiteTree tree = getTree(areaObj);
SiteNode[] preOrder = tree.preOrder();
List docs = new ArrayList();
for (int i = 0; i < preOrder.length; i++) {
String[] langs = preOrder[i].getLanguages();
for (int l = 0; l < langs.length; l++) {
docs.add(preOrder[i].getLink(langs[l]).getDocument());
}
}
return (Document[]) docs.toArray(new Document[docs.size()]);
}
public DocumentLocator[] getRequiredResources(DocumentFactory map, DocumentLocator loc)
throws SiteException {
List ancestors = new ArrayList();
DocumentLocator locator = loc;
while (locator.getParent() != null) {
DocumentLocator parent = locator.getParent();
ancestors.add(parent);
locator = parent;
}
return (DocumentLocator[]) ancestors.toArray(new DocumentLocator[ancestors.size()]);
}
public SiteNode[] getRequiringResources(DocumentFactory map, SiteNode resource)
throws SiteException {
NodeSet nodes = new NodeSet(this.manager);
SiteTree tree = (SiteTree) resource.getStructure();
TreeNode node = (TreeNode) tree.getNode(resource.getPath());
if (node != null) {
SiteNode[] preOrder = node.preOrder();
// exclude original resource (does not require itself)
for (int i = 1; i < preOrder.length; i++) {
TreeNode descendant = (TreeNode) preOrder[i];
nodes.add(descendant);
}
}
return nodes.getNodes();
}
public SiteStructure getSiteStructure(DocumentFactory map, Publication publication, String area)
throws SiteException {
try {
return getTree(publication.getArea(area));
} catch (PublicationException e) {
throw new SiteException(e);
}
}
public boolean isVisibleInNav(Document document) throws SiteException {
try {
return document.getLink().getNode().isVisible();
} catch (DocumentException e) {
throw new SiteException(e);
}
}
public boolean requires(DocumentFactory map, SiteNode depending, SiteNode required)
throws SiteException {
return depending.getPath().startsWith(required.getPath() + "/");
}
public void set(String path, Document document) throws SiteException {
if (contains(document)) {
throw new SiteException("The document [" + document + "] is already contained!");
}
SiteTreeImpl tree = (SiteTreeImpl) getTree(document.area());
TreeNodeImpl node = (TreeNodeImpl) tree.getNode(path);
node.setUuid(document.getUUID());
tree.changed();
}
public void setVisibleInNav(Document document, boolean visibleInNav) throws SiteException {
try {
document.getLink().getNode().setVisible(visibleInNav);
} catch (DocumentException e) {
throw new SiteException(e);
}
}
}