/src/main/java/org/andya/confluence/plugins/metadata/MetadataUtils.java
Java | 389 lines | 343 code | 10 blank | 36 comment | 15 complexity | 9431c3c27bb3ccc8ef8c3313bf8d1309 MD5 | raw file
- /*
- * Copyright (c) 2006, 2007 Andy Armstrong, Kelsey Grant and other contributors.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * The names of contributors may not
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
- package org.andya.confluence.plugins.metadata;
-
- import com.atlassian.confluence.core.ContentEntityObject;
- import com.atlassian.confluence.core.ContentPropertyManager;
- import com.atlassian.confluence.core.ConfluenceEntityObject;
- import com.atlassian.confluence.renderer.PageContext;
- import com.atlassian.renderer.RenderContext;
- import com.atlassian.renderer.RenderContextOutputType;
- import com.thoughtworks.xstream.XStream;
- import org.andya.confluence.plugins.metadata.model.MetadataContent;
- import org.andya.confluence.plugins.metadata.model.MetadataValue;
- import org.andya.confluence.utils.ContentService;
-
- import java.util.*;
-
- /**
- * Useful utilities for dealing with Confluence metadata.
- */
- public class MetadataUtils {
- public static final String METADATA_KEY = "metadata.";
- public static final String METADATA_NAMES_KEY = "metadatakeys";
-
- private static final String SEARCHABLE_PROPERTIES = "scaffold!searchableProps";
-
- public static final char METADATA_KEYS_SEPARATOR = '|';
- private static XStream xStream = null;
-
- /**
- * Returns the property key used for the specified metadata value.
- */
- public static String getMetadataKey(String valueName) {
- return METADATA_KEY + valueName.trim();
- }
-
- /**
- * Returns an array of the metadata names associated with the given content entity object.
- */
- public static String[] getMetadataNames(ContentService contentService, ContentEntityObject ceo) {
- ContentPropertyManager contentPropertyManager = contentService.getContentPropertyManager();
- String metadataKeysString = getMetadataNamesString(contentPropertyManager, ceo);
- String[] metadataKeys;
-
- if (metadataKeysString == null || metadataKeysString.length() == 0)
- metadataKeys = new String[0];
- else
- metadataKeys = metadataKeysString.split("\\" + METADATA_KEYS_SEPARATOR);
-
- String[] scaffoldingKeys = getScaffoldingNames(contentPropertyManager, ceo);
- String[] allKeys = new String[metadataKeys.length + scaffoldingKeys.length];
- System.arraycopy(metadataKeys, 0, allKeys, 0, metadataKeys.length);
- System.arraycopy(scaffoldingKeys, 0, allKeys, metadataKeys.length, scaffoldingKeys.length);
- return allKeys;
- }
-
- /**
- * Returns a string of the metadata names associated with the given content entity object.
- */
- public static String getMetadataNamesString(ContentPropertyManager contentPropertyManager, ContentEntityObject ceo) {
- return contentPropertyManager.getTextProperty(ceo, METADATA_NAMES_KEY);
- }
-
- /**
- * Returns an array of all the metadata values from the specified content entity object.
- */
- public static MetadataValue[] getMetadataValues(ContentService contentService, ContentEntityObject ceo) {
- String[] names = MetadataUtils.getMetadataNames(contentService, ceo);
- int count = names.length;
- MetadataValue[] values = new MetadataValue[count];
- for (int i = 0; i < count; i++) {
- String name = names[i];
- Object value = MetadataUtils.getMetadataValue(contentService, ceo, name, "");
- values[i] = contentService.createMetadataValue(name, value);
- }
- return values;
- }
-
- /**
- * Register that the specified content entity object uses a metadata name.
- *
- * @param contentPropertyManager The content property manager.
- * @param ceo The content object to attach metadata to.
- * @param valueName The name of the metadata value.
- */
- public static void registerMetadataName(ContentPropertyManager contentPropertyManager, ContentEntityObject ceo,
- String valueName) {
- String metadataNamesString = contentPropertyManager.getTextProperty(ceo, METADATA_NAMES_KEY);
- String newMetadataNamesString = addMetadataName(metadataNamesString, valueName);
- if (!newMetadataNamesString.equals(metadataNamesString))
- contentPropertyManager.setTextProperty(ceo, METADATA_NAMES_KEY, newMetadataNamesString);
- }
-
- /**
- * Clears any metadata names that are registered with the specified content entity object.
- *
- * @param contentPropertyManager The content property manager.
- * @param ceo The content object to attach metadata to.
- */
- public static void clearMetadataNames(ContentPropertyManager contentPropertyManager, ContentEntityObject ceo) {
- contentPropertyManager.removeProperty(ceo, METADATA_NAMES_KEY);
- }
-
- public static Map<String,String> getAllMetadata(ContentService contentService, ContentEntityObject ceo) {
- Map<String, String> results = new HashMap<String, String>();
- List<String> names = getMetadataNames(contentService.getContentPropertyManager(), ceo);
- for(String name : names) {
- MetadataValue v = getMetadataValue(contentService, ceo, name, null);
- results.put(name, v.getValue().toString());
- }
- return results;
- }
-
- /**Clears any metadata and unregister metadata names for a content entity
- *
- * @param contentPropertyManager The content property manager.
- * @param ceo The content object to attach metadata to.
- * */
- public static void clearMetadata(ContentPropertyManager contentPropertyManager, ContentEntityObject ceo) {
- List<String> names = getMetadataNames(contentPropertyManager, ceo);
- for(String name : names) {
- contentPropertyManager.removeProperty(ceo, getMetadataKey(name));
- }
- contentPropertyManager.removeProperty(ceo, METADATA_NAMES_KEY);
- }
-
- public static List<String> getMetadataNames(ContentPropertyManager contentPropertyManager, ContentEntityObject ceo) {
- List<String> names = new ArrayList<String>();
- String metadataNamesString = contentPropertyManager.getTextProperty(ceo, METADATA_NAMES_KEY);
- if (metadataNamesString != null && metadataNamesString.length() > 0)
- names = Arrays.asList(metadataNamesString.split("\\" + METADATA_KEYS_SEPARATOR));
- return names;
- }
-
- public static String addMetadataName(String namesString, String name) {
- if (name == null || name.length() == 0)
- return namesString;
- if (namesString == null || namesString.length() == 0)
- return name;
- List<String> names = Arrays.asList(namesString.split("\\" + METADATA_KEYS_SEPARATOR));
- if (!names.contains(name))
- return namesString + METADATA_KEYS_SEPARATOR + name;
- else
- return namesString;
- }
-
- /**
- * Returns a named metadata value from the specified content object. The value is returned
- * as unrendered Wiki content so that it can be rendered appropriately on another page.
- *
- * @param contentService The content service.
- * @param ceo The content object to return the metadata for.
- * @param valueName The name of the metadata value.
- * @param defaultValue The default value to return if no value is found.
- * @return The unrendered Wiki content for the metadata value.
- */
- public static MetadataValue getMetadataValue(ContentService contentService, ConfluenceEntityObject ceo,
- String valueName, Object defaultValue) {
- Object value = null;
- if (ceo instanceof ContentEntityObject) {
- value = getRawMetadataValue(contentService, (ContentEntityObject)ceo, valueName, null);
- if (value == null)
- value = getScaffoldingValue(contentService, (ContentEntityObject)ceo, valueName, null);
- }
- if (value == null)
- value = contentService.getContentValue(ceo, valueName);
- if (value instanceof MetadataValue)
- return (MetadataValue)value;
- return contentService.createMetadataValue(valueName, value, defaultValue);
- }
-
- /**
- * Returns a named metadata value from the specified content object. The value is returned
- * as unrendered Wiki content so that it can be rendered appropriately on another page.
- *
- * @param contentService The content service.
- * @param ceo The content object to return the metadata for.
- * @param valueName The name of the metadata value.
- * @param defaultValue The default value to return if no value is found.
- * @return The unrendered Wiki content for the metadata value.
- */
- public static MetadataValue getRawMetadataValue(ContentService contentService, ContentEntityObject ceo,
- String valueName, Object defaultValue) {
- if (ceo == null)
- throw new IllegalArgumentException("Attempted to fetch metadata value for null ContentEntityObject");
- String key = getMetadataKey(valueName);
- ContentPropertyManager contentPropertyManager = contentService.getContentPropertyManager();
- Object value = contentPropertyManager != null ? contentPropertyManager.getTextProperty(ceo, key) : null;
- return contentService.createMetadataValue(valueName, value, defaultValue);
- }
-
- /**
- * Sets a named metadata value for the specified content object. The value specified should
- * be unrendered Wiki content so that the user of the value can choose how to render it.
- *
- * @param contentPropertyManager The content property manager.
- * @param ceo The content object to attach metadata to.
- * @param valueName The name of the metadata value.
- * @param unrenderedValue The unrendered Wiki content to be stored.
- */
- public static void setMetadataValue(ContentPropertyManager contentPropertyManager, ContentEntityObject ceo,
- String valueName, String unrenderedValue) {
- if (ceo == null)
- throw new IllegalArgumentException("Attempted to set metadata value for null ContentEntityObject");
- String key = getMetadataKey(valueName);
- contentPropertyManager.setTextProperty(ceo, key, unrenderedValue);
- registerMetadataName(contentPropertyManager, ceo, valueName);
- }
-
- /**
- * Sets a named metadata value for the content object associated with the current render context.
- * The value specified should be unrendered Wiki content so that the user of the value can choose
- * how to render it.
- *
- * @param renderContext The render context in which this macro is executing.
- * @param valueName The name of the metadata value.
- * @param unrenderedValue The unrendered Wiki content to be stored.
- */
- public static void setMetadataValue(ContentPropertyManager contentPropertyManager,
- RenderContext renderContext, String valueName, String unrenderedValue) {
- String outputType = renderContext.getOutputType();
- if(outputType != null && outputType.equals(RenderContextOutputType.PREVIEW))
- return;
- if (renderContext instanceof PageContext) {
- PageContext pageContext = (PageContext)renderContext;
- ContentEntityObject ceo = pageContext.getEntity();
- // Ensure we're only recording excerpts of the base page and not on templates
- if (pageContext.getOriginalContext() == pageContext && ceo != null)
- setMetadataValue(contentPropertyManager, ceo, valueName, unrenderedValue);
- }
- }
-
- /**
- * This function creates a collection of {@link MetadataContent} objects for the specified entities.
- *
- * @param entities
- * @return The MetadataContent list.
- */
- public static List<MetadataContent> getMetadataContent(ContentService contentService, List<ConfluenceEntityObject> entities) {
- List<MetadataContent> content = new ArrayList<MetadataContent>();
- for (ConfluenceEntityObject entity : entities) {
- content.add(new MetadataContent(contentService, entity));
- }
- return content;
- }
-
- /**
- * This function returns a list of numbers from the specified {@link MetadataContent}. If matchingName
- * and matchingValue are provided, then numbers will only be returned for content with matching values.
- *
- * @param contents A list of {@link MetadataContent}.
- * @param valueName The metadata value to return.
- * @param matchingName The name of the metadata to match against.
- * @param matchingValue The value for the metadata match.
- * @return A list of numbers.
- */
- public static List<Number> getMetadataNumbers(List<MetadataContent> contents, String valueName,
- String matchingName, String matchingValue) {
- List<Number> numbers = new ArrayList<Number>();
- for (MetadataContent content : contents) {
- if (matchingName != null) {
- MetadataValue contentMetadataValue = content.getMetadataValue(matchingName);
- if (!matchingValue.equals(contentMetadataValue.getWikiSnippet()))
- continue;
- }
- MetadataValue value = content.getMetadataValue(valueName);
- if (value != null) {
- Number number = value.getValueAsNumber();
- if (number != null)
- numbers.add(number);
- }
- }
- return numbers;
- }
-
- public static String getScaffoldingValue(ContentService contentService, ContentEntityObject content,
- String key, String defaultValue) {
- if (content == null)
- throw new IllegalArgumentException("Attempted to fetch metadata value for null ContentEntityObject");
-
- key = getScaffoldingKey(key);
- ContentPropertyManager contentPropertyManager = contentService.getContentPropertyManager();
- String value = contentPropertyManager != null ? contentPropertyManager.getTextProperty(content, key) : null;
- return value != null ? value : defaultValue;
- }
-
- private static String getScaffoldingKey(String key) {
- return "scaffold." + key;
- }
-
- @SuppressWarnings("unchecked")
- public static String[] getScaffoldingNames(ContentPropertyManager contentPropertyManager, ContentEntityObject content) {
- Map props = getScaffoldingProperties(contentPropertyManager, content);
- if (props == null)
- return new String[0];
-
- String[] names = new String[props.size()];
- Iterator i = props.keySet().iterator();
- int j = 0;
-
- while (i.hasNext()) {
- // Trim 'scaffold.' from the property name.
- names[j++] = ((String)i.next()).substring(9);
- }
-
- return names;
- }
-
- @SuppressWarnings("unchecked")
- private static Map getScaffoldingProperties(ContentPropertyManager contentPropertyManager, ContentEntityObject content) {
- return getMapProperty(contentPropertyManager, content,
- SEARCHABLE_PROPERTIES);
- }
-
- @SuppressWarnings("unchecked")
- private static Map getMapProperty(ContentPropertyManager contentPropertyManager, ContentEntityObject contentEntityObject,
- String key) {
- return (Map)getObjectProperty(contentPropertyManager, contentEntityObject, key);
- }
-
- private static Object getObjectProperty(ContentPropertyManager contentPropertyManager, ContentEntityObject contentEntityObject,
- String key) {
- String xml = contentPropertyManager.getTextProperty(
- contentEntityObject, key);
- return xmlToObject(xml);
- }
-
- /**
- * @return the XStream instance.
- */
- private static XStream getXStream() {
- if (xStream == null) {
- xStream = new XStream();
- xStream.setClassLoader(MetadataUtils.class.getClassLoader());
- }
- return xStream;
- }
-
- /**
- * Converts the object to XML.
- *
- * @param value The object to convert.
- * @return The XML version of the object.
- */
- protected static String objectToXML(Object value) {
- if (value != null)
- return getXStream().toXML(value);
- return null;
- }
-
- /**
- * Converts the XML into an object.
- *
- * @param xml The XML to convert.
- * @return the object version of the XML
- */
- protected static Object xmlToObject(String xml) {
- if (xml != null)
- return getXStream().fromXML(xml);
- return null;
- }
-
- }