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