Package org.apache.xindice.core.meta

Source Code of org.apache.xindice.core.meta.MetaData

/*
* 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.
*
* $Id: MetaData.java 511426 2007-02-25 03:25:02Z vgritsenko $
*/

package org.apache.xindice.core.meta;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xindice.xml.TextWriter;
import org.apache.xindice.xml.XMLSerializable;
import org.apache.xindice.xml.dom.DocumentImpl;

import org.w3c.dom.Comment;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

/**
* Implements the MetaData interface.
*
* <pre>
* &lt;meta&gt;
*   &lt;system [type="doc|col"] [href="uri"]/&gt;
*   &lt;attrs&gt;
*     &lt;attr name="name" value="value"/&gt;
*     &lt;attr name="name" value="value"/&gt;
*   &lt;/attrs&gt;
*   &lt;custom&gt;
*     ...
*   &lt;/custom&gt;
* &lt;/meta&gt;
* </pre>
*
* @author ku
* @author Dave Viner <dviner@apache.org>
* @version $Revision: 511426 $, $Date: 2007-02-24 22:25:02 -0500 (Sat, 24 Feb 2007) $
*/
public class MetaData implements XMLSerializable {

    private static Log log = LogFactory.getLog(MetaData.class);

    public final static short UNKNOWN = 0;
    public final static short COLLECTION = 1;
    public final static short DOCUMENT = 2;
    public final static short LINK = 3;

    public final static String NS_URI = "http://apache.org/xindice/metadata";
    //public final static String NS_PREFIX    = "md";
    public final static boolean USE_NS = true;

    private static final String E_META = "meta";
    private static final String E_SYSTEM = "system";
    private static final String E_ATTRS = "attrs";
    private static final String E_ATTR = "attr";
    private static final String E_CUSTOM = "custom";
    private static final String E_CREATED = "created";
    private static final String E_MODIFIED = "modified";

    private static final String A_NAME = "name";
    private static final String A_VALUE = "value";
    private static final String A_TYPE = "type";
    private static final String A_HREF = "href";

    private static final Enumeration EMPTY =
            (new Vector()).elements();

    private transient boolean dirty;
    private transient long created;
    private transient long modified;
    private transient String owner;

    private short type = UNKNOWN;
    private String link;
    private Hashtable attrs;
    private Document custom;


    public MetaData() {
    }

    /**
     * @param owner the owner of this metadata.
     */
    public MetaData(String owner) {
        this.owner = owner;
    }


    /**
     * @param type the type of object for this metadata
     * @param owner the owner of this metadata
     * @param created the time when this was created
     * @param modified the time when this was modified.
     */
    public MetaData(short type, String owner, long created, long modified) {
        this.type = type;
        this.owner = owner;
        this.created = created;
        this.modified = modified;
    }

    /**
     * @param elem an XML representation of the desired metadata.
     */
    public MetaData(Element elem) {
        streamFromXML(elem);
    }

    /**
     * Returns whether this MetaData is dirty
     *
     * @return boolean
     */
    public final boolean isDirty() {
        return dirty;
    }

    /**
     * Reset the dirtiness of this object
     *
     * @param dirty
     */
    public final void setDirty(boolean dirty) {
        this.dirty = dirty;
    }

    /**
     * Returns the time of creation
     * @return long creation time
     */
    public long getCreatedTime() {
        return created;
    }

    /**
     * Returns the time of last modification
     * @return long last modified time
     */
    public long getLastModifiedTime() {
        return modified;
    }

    /**
     * Returns the type of the owner object, e.g., COLLECTION,
     * DOCUMENT, or LINK
     * @return short the object type
     */
    public short getType() {
        return type;
    }

    /**
     * Returns the canonical name of the owner object.
     * @return String the canonical name of the owner object
     */
    public String getOwner() {
        return owner;
    }

    /**
     * Returns enumeration of all attributes
     * @return Enumeration of attributes
     */
    public Enumeration getAttributeKeys() {
        if (null == attrs) {
            return EMPTY;
        }

        return attrs.keys();
    }

    /**
     * Retrieves the attribute by name
     * @param name the attribute name
     * @return String the value of attribute, or null if not found
     */
    public Object getAttribute(final Object name) {
        if (null == attrs) {
            return null;
        }

        return attrs.get(name);
    }

    public Boolean getAttributeAsBoolean(final Object name) {
        Object o = getAttribute(name);
        if (null == o) {
            return null;
        }

        if (o instanceof Boolean) {
            return (Boolean) o;
        }

        if (o instanceof Number) {
            Number n = (Number) o;
            return new Boolean(n.intValue() != 0);
        }

        return Boolean.valueOf(o.toString());
    }

    public Integer getAttributeAsInteger(final Object name) {
        Object o = getAttribute(name);
        if (null == o) {
            return null;
        }

        if (o instanceof Integer) {
            return (Integer) o;
        }

        if (o instanceof Number) {
            Number n = (Number) o;
            return new Integer(n.intValue());
        }

        try {
            int v = Integer.parseInt(o.toString());
            return new Integer(v);
        } catch (Exception e) {
            return null;
        }
    }

    public Long getAttributeAsLong(final Object name) {
        Object o = getAttribute(name);
        if (null == o) {
            return null;
        }

        if (o instanceof Long) {
            return (Long) o;
        }

        if (o instanceof Number) {
            Number n = (Number) o;
            return new Long(n.longValue());
        }

        try {
            long v = Long.parseLong(o.toString());
            return new Long(v);
        } catch (Exception e) {
            return null;
        }
    }

    public Short getAttributeAsShort(final Object name) {
        Object o = getAttribute(name);
        if (null == o) {
            return null;
        }

        if (o instanceof Short) {
            return (Short) o;
        }

        if (o instanceof Number) {
            Number n = (Number) o;
            return new Short(n.shortValue());
        }

        try {
            short v = Short.parseShort(o.toString());
            return new Short(v);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * Sets the attribute by name
     * @param name the attribute name
     * @param value the attribute value
     * @return Object the old value, if any
     */
    public Object setAttribute(final Object name, final Object value) {
        if (null == attrs) {
            attrs = new Hashtable();
            dirty = true;
        }
        Object prev = attrs.put(name, value);
        if (prev == null || !prev.equals(value)) {
            dirty = true;
        }

        return prev;
    }

    /**
     * Remove an attribute by name
     * @param name the attribute to remove
     * @return Object the removed value
     */
    public Object removeAttribute(final Object name) {
        if (null == attrs) {
            return null;
        }

        Object prev = attrs.remove(name);
        if (null != prev) {
            dirty = true;
        }

        return prev;
    }

    /**
     * Returns the (optional) custom meta document
     * @return Document the custom meta document
     */
    public Document getCustomDocument() {
        return custom;
    }

    /**
     * Sets the (optional) custom meta document
     * @param doc the Document
     */
    public void setCustomDocument(Document doc) {
        this.custom = doc;
        this.dirty = true;
    }

    /**
     * Copies from another meta data
     * @param meta the meta to copy from
     */
    public void copyFrom(final MetaData meta) {
        this.created = meta.getCreatedTime();
        this.modified = meta.getLastModifiedTime();
        this.owner = meta.getOwner();
        this.type = meta.getType();
        copyDataFrom(meta);
    }

    /**
     * Copies only user data (link, attributes, custom document) from another meta data
     * @param meta the meta to copy from
     */
    public void copyDataFrom(final MetaData meta) {
        this.link = meta.getLinkTargetURI();
        this.attrs = null;
        for (Enumeration e = meta.getAttributeKeys(); e.hasMoreElements();) {
            Object key = e.nextElement();
            Object value = meta.getAttribute(key);
            if (null == this.attrs) {
                this.attrs = new Hashtable();
            }
            this.attrs.put(key, value);
        }

        this.custom = null;
        Document doc = meta.getCustomDocument();
        if (null != doc) {
            this.custom = new DocumentImpl();
            this.custom.appendChild(
                    this.custom.importNode(doc.getDocumentElement(), true));
        }
        this.dirty = false;
    }

    /**
     * Returns the linked target URI, if this is a link
     * @return String the URI of the linked target
     */
    public String getLinkTargetURI() {
        return link;
    }

    //
    // Serialization to/from XML
    //

    /**
     * Stream this MetaData into an xml document
     * @param doc the xml document to be populated.
     */
    public final Element streamToXML(Document doc) throws DOMException {

        return streamToXML(doc, true);
    }

    /**
     * Stream this MetaData into an xml document
     * @param doc the xml document to populate
     * @param includeTime whether or not to include the create/modified times
     * @return Element the root element
     */
    public final Element streamToXML(Document doc, boolean includeTime)
            throws DOMException {

        Element root = null;
        if (!USE_NS) {
            root = doc.createElement(E_META);
        } else {
            root = doc.createElementNS(NS_URI, E_META);
            root.setAttribute("xmlns", NS_URI);
        }

        Element systemElement = null;
        if (!USE_NS) {
            systemElement = doc.createElement(E_SYSTEM);
        } else {
            systemElement = doc.createElementNS(NS_URI, E_SYSTEM);
        }
        systemElement.setAttribute(A_TYPE, getTypeString(type));
        root.appendChild(systemElement);
        if (includeTime) {
            if (created > 0) {
                String message = "Create time is " + (new Date(created));
                Comment comment = doc.createComment(message);
                systemElement.appendChild(comment);
            }

            Element timeElement = null;
            if (!USE_NS) {
                timeElement = doc.createElement(E_ATTR);
            } else {
                timeElement = doc.createElementNS(NS_URI, E_ATTR);
            }
            timeElement.setAttribute(A_NAME, E_CREATED);
            timeElement.setAttribute(A_VALUE, Long.toString(created));
            systemElement.appendChild(timeElement);

            if (modified > 0) {
                String message = "Modified time is " + (new Date(modified));
                Comment comment = doc.createComment(message);
                systemElement.appendChild(comment);
            }
            if (!USE_NS) {
                timeElement = doc.createElement(E_ATTR);
            } else {
                timeElement = doc.createElementNS(NS_URI, E_ATTR);
            }
            timeElement.setAttribute(A_NAME, E_MODIFIED);
            timeElement.setAttribute(A_VALUE, Long.toString(modified));
            systemElement.appendChild(timeElement);
        }
        if (null != link) {
            systemElement.setAttribute(A_HREF, link);
        }

        if (null != attrs && attrs.size() > 0) {
            Element attrsElement = null;
            if (!USE_NS) {
                attrsElement = doc.createElement(E_ATTRS);
            } else {
                attrsElement = doc.createElementNS(NS_URI, E_ATTRS);
            }
            root.appendChild(attrsElement);

            for (Enumeration e = attrs.keys(); e.hasMoreElements();) {
                Object key = e.nextElement();
                Object value = attrs.get(key);

                if (null == key) {
                    continue;
                }

                Element attrElement = null;
                if (!USE_NS) {
                    attrElement = doc.createElement(E_ATTR);
                } else {
                    attrElement = doc.createElementNS(NS_URI, E_ATTR);
                }
                attrsElement.appendChild(attrElement);

                attrElement.setAttribute(A_NAME, key.toString());
                if (null != value) {
                    attrElement.setAttribute(A_VALUE, value.toString());
                }
            }
        }

        if (null != custom) {
            Element customElement = null;
            if (!USE_NS) {
                customElement = doc.createElement(E_CUSTOM);
            } else {
                customElement = doc.createElementNS(NS_URI, E_CUSTOM);
            }

            customElement.appendChild(
                    doc.importNode(custom.getDocumentElement(), true));
            root.appendChild(customElement);
        }

        return root;
    }

    /**
     * Given some xml, populate the metadata.
     * @param source The xml to populate metadata with
     */
    public final void streamFromXML(Element source)
            throws DOMException {
        streamFromXML(source, true);
    }

    /**
     * Given some xml, populate the metadata.
     * @param source The xml to populate the metadata with
     * @param includeTime Whether or not to reset the create/modified times
     */
    public final void streamFromXML(Element source, boolean includeTime)
            throws DOMException {
        this.link = null;
        this.attrs = null;
        this.custom = null;

        NodeList list = source.getChildNodes();
        for (int i = 0; i < list.getLength(); i++) {
            Node node = list.item(i);
            if (node.getNodeType() != Node.ELEMENT_NODE) {
                continue;
            }

            Element element = (Element) node;
            String elementName = element.getNodeName();
            // String prefix = element.getPrefix();

            if (E_SYSTEM.equals(elementName)) {
                String attrStr = element.getAttribute(A_TYPE);
                if (null != attrStr) {
                    this.type = parseTypeString(attrStr);
                }

                if (this.type == LINK) {
                    this.link = element.getAttribute(A_HREF);
                }

                if (includeTime) {
                    NodeList children = element.getChildNodes();
                    for (int j = 0; j < children.getLength(); j++) {
                        Node childNode = children.item(j);
                        if (!(childNode instanceof Element)) {
                            continue;
                        }

                        Element child = (Element) childNode;
                        String childName = child.getNodeName();


                        if (E_ATTR.equals(childName)) {
                            String nameStr = child.getAttribute(A_NAME);
                            String valueStr = child.getAttribute(A_VALUE);
                            if (null != nameStr && null != valueStr) {
                                if (E_CREATED.equals(nameStr)) {
                                    this.created = Long.parseLong(valueStr);
                                } else if (E_MODIFIED.equals(nameStr)) {
                                    this.modified = Long.parseLong(valueStr);
                                }
                            }
                        } else {
                            if (log.isDebugEnabled()) {
                                log.debug("Ignorning unknown child elem " + childName);
                            }
                        }
                    }
                }
            } else if (E_ATTRS.equals(elementName)) {
                NodeList attrList = element.getElementsByTagName(E_ATTR);
                for (int j = 0; j < attrList.getLength(); j++) {
                    Element e = (Element) attrList.item(j);

                    String attrName = e.getAttribute(A_NAME);
                    if (null == attrName) {
                        continue;
                    }

                    if (null == this.attrs) {
                        this.attrs = new Hashtable();
                    }
                    this.attrs.put(attrName, e.getAttribute(A_VALUE));
                }
            } else if (E_CUSTOM.equals(elementName)) {
                this.custom = new DocumentImpl();
                Node custdoc = this.custom.importNode(element.getFirstChild(), true);

                /* if you want really verbose debugging try this */
                if (log.isTraceEnabled()) {
                    log.trace("Appending custom element " + elementName
                              + "\nwhose complete original content is: \n" + TextWriter.toString(source)
                              + "\nwhose original content is: \n" + TextWriter.toString(element)
                              + "\nwhose imported content is: \n" + TextWriter.toString(custdoc));
                }
                this.custom.appendChild(custdoc);
            } else {
                // ignore
                if (log.isDebugEnabled()) {
                    log.debug("ignoring unknown xml element " + elementName);
                }
            }
        }
    }

    //
    // Support methods
    //

    /**
     * Return a string representing which type passed in.
     * It will be either doc, col, link, none.
     * @param type The type you want translated.
     * @return String representing this type
     */
    public static String getTypeString(short type) {
        switch (type) {
            case DOCUMENT:
                return "doc";
            case COLLECTION:
                return "col";
            case LINK:
                return "link";
            default:
                return "none";
        }
    }

    /**
     * Return a short representing the string given.
     * The string should be doc, col, or link.
     * @param str The string to parse
     * @return short The short for this string.
     */
    public static short parseTypeString(final String str) {
        if (str.equalsIgnoreCase("doc")) {
            return DOCUMENT;
        }
        if (str.equalsIgnoreCase("col")) {
            return COLLECTION;
        }
        if (str.equalsIgnoreCase("link")) {
            return LINK;
        }

        return UNKNOWN;
    }

    //
    // Modifiers
    //

    /**
     * Determine whether this obect has created or modified times set
     * @return boolean
     */
    public boolean hasContext() {
        return (created > 0 || modified > 0);
    }

    /**
     * Set the created and modified times. If 0 value is passed,
     * time is not changed.
     *
     * @param created the new creation time
     * @param modified the new modified time
     */
    public void setContext(long created, long modified) {
        if (created > 0) {
            this.created = created;
        }
        if (modified > 0) {
            this.modified = modified;
        }
    }

    /**
     * Set the type for this object.
     * If the type is already set to the value passed in, nothing is changed.
     * @param type the type for this object.
     */
    public void setType(short type) {
        if (this.type != type) {
            this.type = type;
            this.dirty = true;
        }
    }

    /**
     * Set the owner of this object
     * @param owner the owner to be ass
     */
    public void setOwner(String owner) {
        if (owner != this.owner ||
                null == owner ||
                null == this.owner ||
                !owner.equals(this.owner)) {
            this.owner = owner;
            this.dirty = true;
        }
    }

    public void setLinkTargetURI(String link) {
        if (link != this.link ||
                null == link ||
                null == this.link ||
                !link.equals(this.link)) {
            this.link = link;
            this.dirty = true;
        }
    }

    /**
     * Return a string representing this MetaData
     * It will look like:
     *  META[doc owner=OWNER created=CREATED modified=MODIFIED link=LINK
     *      attrs=ATTRS]
     *
     * @return String
     */
    public String toString() {
        StringBuffer buffer = new StringBuffer();
        buffer.append("META[");
        buffer.append(getTypeString(type));
        if (owner != null) {
            buffer.append(" owner=").append(owner);
        }
        if (created > 0) {
            buffer.append(" created=").append(new Date(created));
        }
        if (modified > 0) {
            buffer.append(" modified=").append(new Date(modified));
        }
        if (link != null) {
            buffer.append(" link=").append(link);
        }
        if (attrs != null) {
            buffer.append(" attrs=").append(attrs);
        }
        buffer.append("]");
        return buffer.toString();
    }
}
TOP

Related Classes of org.apache.xindice.core.meta.MetaData

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.