You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lenya.apache.org by an...@apache.org on 2006/12/14 18:00:31 UTC
svn commit: r487257 [2/2] - in /lenya/trunk/src:
impl/java/org/apache/lenya/cms/publication/
impl/test/org/apache/lenya/cms/site/ java/org/apache/lenya/cms/site/
java/org/apache/lenya/cms/site/simple/ java/org/apache/lenya/util/
modules/export/java/src...
Added: lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/TreeNodeImpl.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/TreeNodeImpl.java?view=auto&rev=487257
==============================================================================
--- lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/TreeNodeImpl.java (added)
+++ lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/TreeNodeImpl.java Thu Dec 14 09:00:30 2006
@@ -0,0 +1,328 @@
+/*
+ * 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.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.avalon.framework.container.ContainerUtil;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.lenya.cms.publication.DocumentFactory;
+import org.apache.lenya.cms.site.Link;
+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.SiteTreeNode;
+import org.apache.lenya.util.Assert;
+import org.apache.lenya.util.StringUtil;
+
+/**
+ * Site tree node.
+ */
+public class TreeNodeImpl extends AbstractLogEnabled implements TreeNode {
+
+ private TreeNode parent;
+ private String name;
+
+ /**
+ * A top level node.
+ * @param parent The parent.
+ * @param name The name.
+ * @param visible The navigation visibility.
+ * @param logger The logger.
+ */
+ public TreeNodeImpl(TreeNode parent, String name, boolean visible, Logger logger) {
+ ContainerUtil.enableLogging(this, logger);
+ Assert.notNull("name", name);
+ this.name = name;
+ this.parent = parent;
+ this.isVisible = visible;
+ }
+
+ /**
+ * Sets the UUID.
+ * @param uuid The UUID.
+ */
+ protected void setUuid(String uuid) {
+ Assert.notNull("uuid", uuid);
+ if (this.language2link.keySet().size() > 0) {
+ throw new RuntimeException("Can't set the UUID if the node has links.");
+ }
+ this.uuid = uuid;
+ }
+
+ public void delete() {
+ deleteInternal();
+ changed();
+ }
+
+ protected void deleteInternal() {
+ String[] languages = getLanguages();
+ for (int i = 0; i < languages.length; i++) {
+ removeLinkInternal(languages[i]);
+ }
+ SiteNode[] children = getChildren();
+ for (int i = 0; i < children.length; i++) {
+ ((TreeNodeImpl) children[i]).deleteInternal();
+ }
+ ((TreeNodeImpl) this.parent).removeChild(getName());
+ }
+
+ private Map language2link = new HashMap();
+ private String uuid;
+ private boolean isVisible;
+
+ public String[] getLanguages() {
+ Set languages = this.language2link.keySet();
+ return (String[]) languages.toArray(new String[languages.size()]);
+ }
+
+ public Link getLink(String language) throws SiteException {
+ Assert.notNull("language", language);
+ if (!this.language2link.containsKey(language)) {
+ throw new SiteException("No link contained for language [" + language + "]");
+ }
+ return (Link) this.language2link.get(language);
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public SiteNode getParent() throws SiteException {
+ if (isTopLevel()) {
+ throw new SiteException("This is a top level node.");
+ }
+ return (SiteNode) this.parent;
+ }
+
+ public String getPath() {
+ return this.parent.getPath() + "/" + getName();
+ }
+
+ public SiteStructure getStructure() {
+ return getTree();
+ }
+
+ public String getUuid() {
+ return this.uuid;
+ }
+
+ public boolean hasLink(String language) {
+ Assert.notNull("language", language);
+ return this.language2link.containsKey(language);
+ }
+
+ public boolean isTopLevel() {
+ return this.parent instanceof RootNode;
+ }
+
+ public boolean isVisible() {
+ return this.isVisible;
+ }
+
+ public void setVisible(boolean visibleInNav) {
+ this.isVisible = visibleInNav;
+ changed();
+ }
+
+ protected void changed() {
+ getTree().save();
+ }
+
+ public SiteTreeNode[] getPrecedingSiblings() {
+ SiteNode[] children = this.parent.getChildren();
+ int pos = Arrays.asList(children).indexOf(this);
+ List siblings = new ArrayList();
+ for (int i = 0; i < pos - 1; i++) {
+ siblings.add(children[i]);
+ }
+ return (SiteTreeNode[]) siblings.toArray(new TreeNodeImpl[siblings.size()]);
+ }
+
+ public SiteTreeNode[] getNextSiblings() {
+ SiteNode[] children = this.parent.getChildren();
+ int pos = Arrays.asList(children).indexOf(this);
+ List siblings = new ArrayList();
+ for (int i = pos + 1; i < children.length; i++) {
+ siblings.add(children[i]);
+ }
+ return (SiteTreeNode[]) siblings.toArray(new TreeNodeImpl[siblings.size()]);
+ }
+
+ public SiteTreeImpl getTree() {
+ return this.parent.getTree();
+ }
+
+ protected Link addLink(String lang, String label) {
+ Assert.notNull("language", lang);
+ Assert.notNull("label", label);
+ Link link = addLinkInternal(lang, label);
+ changed();
+ return link;
+ }
+
+ protected Link addLinkInternal(String lang, String label) {
+ Assert.notNull("language", lang);
+ Assert.notNull("label", label);
+ if (this.language2link.containsKey(lang)) {
+ throw new RuntimeException("The language [" + lang + "] is already contained.");
+ }
+ DocumentFactory factory = getTree().getPublication().getFactory();
+ Link link = new SiteTreeLink(factory, this, label, lang);
+ this.language2link.put(lang, link);
+ getTree().linkAdded(link);
+ return link;
+ }
+
+ protected void removeLink(String language) {
+ removeLinkInternal(language);
+ deleteIfEmpty();
+ changed();
+ }
+
+ protected void removeLinkInternal(String language) {
+ Assert.notNull("language", language);
+ this.language2link.remove(language);
+ getTree().linkRemoved(getUuid(), language);
+ }
+
+ protected void deleteIfEmpty() {
+ if (isEmpty()) {
+ deleteInternal();
+ }
+ }
+
+ protected boolean isEmpty() {
+ return this.language2link.isEmpty() && this.name2child.isEmpty();
+ }
+
+ public String toString() {
+ return getPath() + "[" + StringUtil.join(getLanguages(), ",") + "]";
+ }
+
+ private List children = new ArrayList();
+
+ public SiteNode[] getChildren() {
+ return (SiteNode[]) this.children.toArray(new SiteNode[this.children.size()]);
+ }
+
+ public SiteNode[] preOrder() {
+ List preOrder = new ArrayList();
+ preOrder.add(this);
+ SiteNode[] children = getChildren();
+ for (int i = 0; i < children.length; i++) {
+ TreeNode child = (TreeNode) children[i];
+ preOrder.addAll(Arrays.asList(child.preOrder()));
+ }
+ return (SiteNode[]) preOrder.toArray(new SiteNode[preOrder.size()]);
+ }
+
+ protected void removeChild(String name) {
+ Assert.notNull("name", name);
+ if (!this.name2child.containsKey(name)) {
+ throw new RuntimeException("The node [" + name + "] is not contained!");
+ }
+ SiteNode node = (SiteNode) this.name2child.get(name);
+ this.name2child.remove(node.getName());
+ this.children.remove(node);
+ getTree().nodeRemoved(getPath() + "/" + name);
+ deleteIfEmpty();
+ }
+
+ private Map name2child = new HashMap();
+
+ public SiteNode addChild(String name, boolean visible) {
+ Assert.notNull("name", name);
+ return addChild(name, this.children.size(), visible);
+ }
+
+ public SiteNode addChild(String name, String followingNodeName, boolean visible) {
+ Assert.notNull("name", name);
+ Assert.notNull("following node name", followingNodeName);
+ SiteNode followingSibling = getChild(followingNodeName);
+ int pos = this.children.indexOf(followingSibling);
+ return addChild(name, pos, visible);
+ }
+
+ protected SiteNode addChild(String name, int pos, boolean visible) {
+ Assert.notNull("name", name);
+
+ if (this.name2child.containsKey(name)) {
+ throw new RuntimeException("The child [" + name + "] is already contained.");
+ }
+
+ SiteNode node = new TreeNodeImpl(this, name, visible, getLogger());
+ this.children.add(pos, node);
+ this.name2child.put(name, node);
+ getTree().nodeAdded(node);
+ getTree().save();
+ return node;
+ }
+
+ protected SiteNode getChild(String name) {
+ Assert.notNull("name", name);
+ if (this.name2child.containsKey(name)) {
+ return (SiteNode) this.name2child.get(name);
+ } else {
+ throw new RuntimeException("No such child [" + name + "]");
+ }
+ }
+
+ protected int getPosition(SiteNode child) {
+ Assert.notNull("child", child);
+ Assert.isTrue("contains", this.children.contains(child));
+ return this.children.indexOf(child);
+ }
+
+ public void moveDown(String name) {
+ SiteNode child = getChild(name);
+ int pos = getPosition(child);
+ Assert.isTrue("not last", pos < this.children.size() - 1);
+ this.children.remove(child);
+ this.children.add(pos + 1, child);
+ changed();
+ }
+
+ public void moveUp(String name) {
+ SiteNode child = getChild(name);
+ int pos = getPosition(child);
+ Assert.isTrue("not first", pos > 0);
+ this.children.remove(child);
+ this.children.add(pos - 1, child);
+ changed();
+ }
+
+ public String getHref() {
+ return null;
+ }
+
+ public String getSuffix() {
+ return null;
+ }
+
+ public boolean hasLink() {
+ return false;
+ }
+
+}
Added: lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/TreeSiteManager.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/TreeSiteManager.java?view=auto&rev=487257
==============================================================================
--- lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/TreeSiteManager.java (added)
+++ lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/TreeSiteManager.java Thu Dec 14 09:00:30 2006
@@ -0,0 +1,290 @@
+/*
+ * 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.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 publication The publication.
+ * @param area The area.
+ * @return A site tree.
+ * @throws SiteException if an error occurs.
+ */
+ protected SiteTreeImpl getTree(Area area) throws SiteException {
+
+ String key = getKey(area);
+ SiteTreeImpl sitetree;
+ RepositoryItemFactory factory = new SiteTreeFactory(this.manager, getLogger());
+ try {
+ sitetree = (SiteTreeImpl) 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 {
+ SiteTreeImpl 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) {
+ destNode = destinationTree.add(destPath);
+ } else {
+ 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;
+ SiteTreeImpl 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;
+ if ((n < path.length()) && (n > 0)) {
+ lastToken = path.substring(n);
+ substring = path.substring(0, n);
+ }
+
+ int l = lastToken.length();
+ int index = lastToken.lastIndexOf("-");
+ if (0 < index && index < l) {
+ 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);
+ }
+ SiteTreeImpl 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);
+ SiteTreeImpl tree = ((TreeNodeImpl) resource).getTree();
+
+ TreeNodeImpl node = (TreeNodeImpl) 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++) {
+ TreeNodeImpl descendant = (TreeNodeImpl) 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 = getTree(document.area());
+ TreeNodeImpl node = (TreeNodeImpl) tree.getNode(path);
+ node.setUuid(document.getUUID());
+ tree.save();
+ }
+
+ public void setVisibleInNav(Document document, boolean visibleInNav) throws SiteException {
+ try {
+ document.getLink().getNode().setVisible(visibleInNav);
+ } catch (DocumentException e) {
+ throw new SiteException(e);
+ }
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@lenya.apache.org
For additional commands, e-mail: commits-help@lenya.apache.org