001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.relations;
029
030import org.dom4j.Attribute;
031import org.dom4j.Element;
032import org.htmlparser.util.Translate;
033
034/**
035 * An utility class for updating the link xml node.<p>
036 *
037 * @since 6.0.0
038 */
039public final class CmsLinkUpdateUtil {
040
041    /**
042     * Prevents the instanciation of this utility class.<p>
043     */
044    private CmsLinkUpdateUtil() {
045
046        // no-op
047    }
048
049    /**
050     * Updates the type for a link xml element node.<p>
051     *
052     * @param element the link element node to update
053     * @param type the relation type to set
054     */
055    public static void updateType(Element element, CmsRelationType type) {
056
057        updateAttribute(element, CmsLink.ATTRIBUTE_TYPE, type.getNameForXml());
058    }
059
060    /**
061     * Updates the link node in the underlying XML page document.<p>
062     *
063     * @param link the link to update
064     * @param element the &lt;link&gt; element to update
065     * @param updateOnly if set and the element has no {@link CmsLink#NODE_TARGET} subelement, so no action if executed at all
066     */
067    public static void updateXml(CmsLink link, Element element, boolean updateOnly) {
068
069        // if element is not null
070        if (element != null) {
071            if (!updateOnly || (element.element(CmsLink.NODE_TARGET) != null)) {
072                String strId = (link.getStructureId() == null ? null : link.getStructureId().toString());
073                // there may still be entities in the target, so we decode it
074                updateNode(element, CmsLink.NODE_TARGET, link.getTarget(), true);
075                updateNode(element, CmsLink.NODE_UUID, strId, false);
076                updateNode(element, CmsLink.NODE_ANCHOR, link.getAnchor(), true);
077                updateNode(element, CmsLink.NODE_QUERY, link.getQuery(), true);
078            }
079        }
080    }
081
082    /**
083     * Updates the given xml element with this link information.<p>
084     *
085     * @param link the link to get the information from
086     * @param name the (optional) name of the link
087     * @param element the &lt;link&gt; element to update
088     */
089    public static void updateXmlForHtmlValue(CmsLink link, String name, Element element) {
090
091        // if element is not null
092        if (element != null) {
093            // update the additional attributes
094            if (name != null) {
095                updateAttribute(element, CmsLink.ATTRIBUTE_NAME, link.getName());
096            }
097            updateAttribute(element, CmsLink.ATTRIBUTE_INTERNAL, Boolean.toString(link.isInternal()));
098            // update the common sub-elements and attributes
099            updateXmlForVfsFile(link, element);
100        }
101    }
102
103    /**
104     * Updates the given xml element with this link information.<p>
105     *
106     * @param link the link to get the information from
107     * @param element the &lt;link&gt; element to update
108     */
109    public static void updateXmlForVfsFile(CmsLink link, Element element) {
110
111        // if element is not null
112        if (element != null) {
113            // update the type attribute
114            updateAttribute(element, CmsLink.ATTRIBUTE_TYPE, link.getType().getNameForXml());
115            // update the sub-elements
116            updateXml(link, element, false);
117        }
118    }
119
120    /**
121     * Decodes entities in a string if it isn't null.<p>
122     *
123     * @param value the string for which to decode entities
124     *
125     * @return the string with the decoded entities
126     */
127    protected static String decodeEntities(String value) {
128
129        if (value != null) {
130            value = Translate.decode(value);
131        }
132        return value;
133    }
134
135    /**
136     * Updates the given xml element attribute with the given value.<p>
137     *
138     * @param parent the element to set the attribute for
139     * @param attrName the attribute name
140     * @param value the value to set, or <code>null</code> to remove
141     */
142    private static void updateAttribute(Element parent, String attrName, String value) {
143
144        if (parent != null) {
145            Attribute attribute = parent.attribute(attrName);
146            if (value != null) {
147                if (attribute == null) {
148                    parent.addAttribute(attrName, value);
149                } else {
150                    attribute.setValue(value);
151                }
152            } else {
153                // remove only if exists
154                if (attribute != null) {
155                    parent.remove(attribute);
156                }
157            }
158        }
159    }
160
161    /**
162     * Updates the given xml node with the given value.<p>
163     *
164     * @param parent the parent node
165     * @param nodeName the node to update
166     * @param value the value to use to update the given node, can be <code>null</code>
167     * @param cdata if the value should be in a CDATA section or not
168     */
169    private static void updateNode(Element parent, String nodeName, String value, boolean cdata) {
170
171        // get current node element
172        Element nodeElement = parent.element(nodeName);
173        if (value != null) {
174            if (nodeElement == null) {
175                // element wasn't there before, add element and set value
176                nodeElement = parent.addElement(nodeName);
177            }
178            // element is there, update element value
179            nodeElement.clearContent();
180            if (cdata) {
181                nodeElement.addCDATA(value);
182            } else {
183                nodeElement.addText(value);
184            }
185        } else {
186            // remove only if element exists
187            if (nodeElement != null) {
188                // remove element
189                parent.remove(nodeElement);
190            }
191        }
192    }
193}