You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xmlgraphics.apache.org by je...@apache.org on 2006/06/19 21:22:04 UTC

svn commit: r415389 [1/2] - in /xmlgraphics/commons/trunk: examples/java/xmp/ src/java/org/apache/xmlgraphics/util/ src/java/org/apache/xmlgraphics/xmp/ src/java/org/apache/xmlgraphics/xmp/merge/ src/java/org/apache/xmlgraphics/xmp/schemas/ src/java/or...

Author: jeremias
Date: Mon Jun 19 12:22:02 2006
New Revision: 415389

URL: http://svn.apache.org/viewvc?rev=415389&view=rev
Log:
Initial upload of the XMP metadata framework plus example code.
Current functionality currently covers what is necessary to support the PDF/A-1b standard in Apache FOP.
util.QName and util.XMLizable ported from FOP.

Added:
    xmlgraphics/commons/trunk/examples/java/xmp/
    xmlgraphics/commons/trunk/examples/java/xmp/MergeMetadata.java   (with props)
    xmlgraphics/commons/trunk/examples/java/xmp/MetadataFromScratch.java   (with props)
    xmlgraphics/commons/trunk/examples/java/xmp/ParseMetadata.java   (with props)
    xmlgraphics/commons/trunk/examples/java/xmp/pdf-example.xmp   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/util/QName.java
      - copied, changed from r411813, xmlgraphics/fop/trunk/src/java/org/apache/fop/util/QName.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/util/XMLizable.java
      - copied, changed from r415110, xmlgraphics/fop/trunk/src/java/org/apache/fop/util/XMLizable.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/Metadata.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPArray.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPArrayType.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPComplexValue.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPConstants.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPHandler.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPParser.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPProperty.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchema.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchemaAdapter.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchemaRegistry.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSerializer.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/ArrayAddPropertyMerger.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/MergeRuleSet.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/NoReplacePropertyMerger.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/PropertyMerger.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/ReplacePropertyMerger.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/schemas/
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/schemas/DublinCoreAdapter.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/schemas/DublinCoreSchema.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/schemas/XMPBasicAdapter.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/schemas/XMPBasicSchema.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/schemas/pdf/
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/schemas/pdf/AdobePDFAdapter.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/schemas/pdf/AdobePDFSchema.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/schemas/pdf/PDFAAdapter.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/schemas/pdf/PDFAOldXMPSchema.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/schemas/pdf/PDFAXMPSchema.java   (with props)

Added: xmlgraphics/commons/trunk/examples/java/xmp/MergeMetadata.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/examples/java/xmp/MergeMetadata.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/examples/java/xmp/MergeMetadata.java (added)
+++ xmlgraphics/commons/trunk/examples/java/xmp/MergeMetadata.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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$ */
+
+package xmp;
+
+import java.net.URL;
+import java.util.Date;
+
+import javax.xml.transform.TransformerException;
+
+import org.apache.xmlgraphics.xmp.Metadata;
+import org.apache.xmlgraphics.xmp.XMPConstants;
+import org.apache.xmlgraphics.xmp.XMPParser;
+import org.apache.xmlgraphics.xmp.XMPProperty;
+import org.apache.xmlgraphics.xmp.XMPSerializer;
+import org.apache.xmlgraphics.xmp.schemas.DublinCoreAdapter;
+import org.xml.sax.SAXException;
+
+/**
+ * This example shows how to parse an XMP metadata file.
+ */
+public class MergeMetadata {
+
+    private static void mergeMetadata() throws TransformerException, SAXException {
+        URL url = MergeMetadata.class.getResource("pdf-example.xmp");
+        Metadata meta1 = XMPParser.parseXMP(url);
+        
+        Metadata meta2 = new Metadata();
+        DublinCoreAdapter dc = new DublinCoreAdapter(meta2);
+        dc.setTitle("de", "Der Herr der Ringe");
+        dc.setTitle("en", "Lord of the Rings");
+        dc.addCreator("J.R.R. Tolkien"); //Will replace creator from pdf-example.xmp
+        dc.addDate(new Date());
+        
+        meta2.mergeInto(meta1);
+        
+        Metadata meta = meta1;
+        XMPProperty prop;
+        dc = new DublinCoreAdapter(meta);
+        String[] creators = dc.getCreators();
+        for (int i = 0, c = creators.length; i < c; i++) {
+            System.out.println("Creator: " + creators[i]);
+        }
+        System.out.println("Title: " + dc.getTitle());
+        System.out.println("Title de: " + dc.getTitle("de"));
+        System.out.println("Title en: " + dc.getTitle("en"));
+        prop = meta.getProperty(XMPConstants.XMP_BASIC_NAMESPACE, "CreateDate");
+        System.out.println("Creation Date: " + prop.getValue());
+        prop = meta.getProperty(XMPConstants.XMP_BASIC_NAMESPACE, "CreatorTool");
+        System.out.println("Creator Tool: " + prop.getValue());
+        prop = meta.getProperty(XMPConstants.ADOBE_PDF_NAMESPACE, "Producer");
+        System.out.println("Producer: " + prop.getValue());
+        prop = meta.getProperty(XMPConstants.ADOBE_PDF_NAMESPACE, "PDFVersion");
+        System.out.println("PDF version: " + prop.getValue());
+        
+        XMPSerializer.writeXMPPacket(meta, System.out, false);
+    }
+
+    /**
+     * Command-line interface.
+     * @param args the command-line arguments
+     */
+    public static void main(String[] args) {
+        try {
+            mergeMetadata();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+}

Propchange: xmlgraphics/commons/trunk/examples/java/xmp/MergeMetadata.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/examples/java/xmp/MergeMetadata.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/examples/java/xmp/MetadataFromScratch.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/examples/java/xmp/MetadataFromScratch.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/examples/java/xmp/MetadataFromScratch.java (added)
+++ xmlgraphics/commons/trunk/examples/java/xmp/MetadataFromScratch.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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$ */
+
+package xmp;
+
+import java.util.Date;
+
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.xmlgraphics.xmp.Metadata;
+import org.apache.xmlgraphics.xmp.XMPSerializer;
+import org.apache.xmlgraphics.xmp.schemas.DublinCoreAdapter;
+import org.xml.sax.SAXException;
+
+/**
+ * This example shows how to build an XMP metadata file from scratch in Java.
+ */
+public class MetadataFromScratch {
+
+    private static void buildAndPrintMetadata() 
+                throws TransformerConfigurationException, SAXException {
+        Metadata meta = new Metadata();
+        DublinCoreAdapter dc = new DublinCoreAdapter(meta);
+        dc.setTitle("de", "Der Herr der Ringe");
+        dc.setTitle("en", "Lord of the Rings");
+        dc.addDate(new Date());
+        
+        StreamResult res = new StreamResult(System.out);
+        XMPSerializer.writeXML(meta, res);
+        
+    }
+
+    /**
+     * Command-line interface.
+     * @param args the command-line arguments
+     */
+    public static void main(String[] args) {
+        try {
+            buildAndPrintMetadata();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+}

Propchange: xmlgraphics/commons/trunk/examples/java/xmp/MetadataFromScratch.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/examples/java/xmp/MetadataFromScratch.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/examples/java/xmp/ParseMetadata.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/examples/java/xmp/ParseMetadata.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/examples/java/xmp/ParseMetadata.java (added)
+++ xmlgraphics/commons/trunk/examples/java/xmp/ParseMetadata.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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$ */
+
+package xmp;
+
+import java.net.URL;
+
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.xmlgraphics.xmp.Metadata;
+import org.apache.xmlgraphics.xmp.XMPArray;
+import org.apache.xmlgraphics.xmp.XMPConstants;
+import org.apache.xmlgraphics.xmp.XMPParser;
+import org.apache.xmlgraphics.xmp.XMPProperty;
+import org.apache.xmlgraphics.xmp.XMPSerializer;
+import org.xml.sax.SAXException;
+
+/**
+ * This example shows how to parse an XMP metadata file.
+ */
+public class ParseMetadata {
+
+    private static void parseMetadata() throws TransformerException, SAXException {
+        URL url = ParseMetadata.class.getResource("pdf-example.xmp");
+        Metadata meta = XMPParser.parseXMP(url);
+        XMPProperty prop;
+        prop = meta.getProperty(XMPConstants.DUBLIN_CORE_NAMESPACE, "creator");
+        XMPArray array;
+        array = prop.getArrayValue();
+        for (int i = 0, c = array.getSize(); i < c; i++) {
+            System.out.println("Creator: " + array.getValue(i));
+        }
+        prop = meta.getProperty(XMPConstants.DUBLIN_CORE_NAMESPACE, "title");
+        System.out.println("Title: " + prop.getValue());
+        prop = meta.getProperty(XMPConstants.XMP_BASIC_NAMESPACE, "CreateDate");
+        System.out.println("Creation Date: " + prop.getValue());
+        prop = meta.getProperty(XMPConstants.XMP_BASIC_NAMESPACE, "CreatorTool");
+        System.out.println("Creator Tool: " + prop.getValue());
+        prop = meta.getProperty(XMPConstants.ADOBE_PDF_NAMESPACE, "Producer");
+        System.out.println("Producer: " + prop.getValue());
+        prop = meta.getProperty(XMPConstants.ADOBE_PDF_NAMESPACE, "PDFVersion");
+        System.out.println("PDF version: " + prop.getValue());
+        
+        StreamResult res = new StreamResult(System.out);
+        XMPSerializer.writeXML(meta, res);
+    }
+
+    /**
+     * Command-line interface.
+     * @param args the command-line arguments
+     */
+    public static void main(String[] args) {
+        try {
+            parseMetadata();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+}

Propchange: xmlgraphics/commons/trunk/examples/java/xmp/ParseMetadata.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/examples/java/xmp/ParseMetadata.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/examples/java/xmp/pdf-example.xmp
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/examples/java/xmp/pdf-example.xmp?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/examples/java/xmp/pdf-example.xmp (added)
+++ xmlgraphics/commons/trunk/examples/java/xmp/pdf-example.xmp Mon Jun 19 12:22:02 2006
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<x:xmpmeta xmlns:x="adobe:ns:meta/">
+  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+    <rdf:Description xmlns:dc="http://purl.org/dc/elements/1.1/" rdf:about="">
+      <dc:creator>
+        <rdf:Seq>
+          <rdf:li>John Doe</rdf:li>
+        </rdf:Seq>
+      </dc:creator>
+      <dc:title>Example document</dc:title>
+      <dc:date>2006-06-02T10:36:40+02:00</dc:date>
+    </rdf:Description>
+    <rdf:Description xmlns:xmp="http://ns.adobe.com/xap/1.0/" rdf:about="">
+      <xmp:CreateDate>2006-06-02T10:36:40+02:00</xmp:CreateDate>
+      <xmp:CreatorTool>An XML editor</xmp:CreatorTool>
+    </rdf:Description>
+    <rdf:Description xmlns:pdf="http://ns.adobe.com/pdf/1.3/" rdf:about="">
+      <pdf:Producer>Apache FOP Version SVN trunk</pdf:Producer>
+      <pdf:PDFVersion>1.4</pdf:PDFVersion>
+    </rdf:Description>
+  </rdf:RDF>
+</x:xmpmeta>

Propchange: xmlgraphics/commons/trunk/examples/java/xmp/pdf-example.xmp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/examples/java/xmp/pdf-example.xmp
------------------------------------------------------------------------------
    svn:keywords = Id

Copied: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/util/QName.java (from r411813, xmlgraphics/fop/trunk/src/java/org/apache/fop/util/QName.java)
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/util/QName.java?p2=xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/util/QName.java&p1=xmlgraphics/fop/trunk/src/java/org/apache/fop/util/QName.java&r1=411813&r2=415389&rev=415389&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/util/QName.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/util/QName.java Mon Jun 19 12:22:02 2006
@@ -16,7 +16,7 @@
 
 /* $Id$ */
 
-package org.apache.fop.util;
+package org.apache.xmlgraphics.util;
 
 import java.io.Serializable;
 

Copied: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/util/XMLizable.java (from r415110, xmlgraphics/fop/trunk/src/java/org/apache/fop/util/XMLizable.java)
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/util/XMLizable.java?p2=xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/util/XMLizable.java&p1=xmlgraphics/fop/trunk/src/java/org/apache/fop/util/XMLizable.java&r1=415110&r2=415389&rev=415389&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/util/XMLizable.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/util/XMLizable.java Mon Jun 19 12:22:02 2006
@@ -16,7 +16,7 @@
 
 /* $Id$ */
 
-package org.apache.fop.util;
+package org.apache.xmlgraphics.util;
 
 /* 
  * Copied from Apache Excalibur:

Added: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/Metadata.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/Metadata.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/Metadata.java (added)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/Metadata.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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$ */
+
+package org.apache.xmlgraphics.xmp;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.xmlgraphics.util.QName;
+import org.apache.xmlgraphics.util.XMLizable;
+import org.apache.xmlgraphics.xmp.merge.MergeRuleSet;
+import org.apache.xmlgraphics.xmp.merge.PropertyMerger;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * This class represents the root of an XMP metadata tree. It's more or less equivalent to the
+ * x:xmpmeta element together with its nested rdf:RDF element.
+ */
+public class Metadata implements XMLizable {
+
+    private Map properties = new java.util.HashMap();
+
+    /**
+     * Sets a property.
+     * @param prop the property
+     */
+    public void setProperty(XMPProperty prop) {
+        properties.put(prop.getName(), prop);
+    }
+    
+    /**
+     * Returns a property
+     * @param uri the namespace URI of the property
+     * @param localName the local name of the property
+     * @return the requested property or null if it's not available
+     */
+    public XMPProperty getProperty(String uri, String localName) {
+        return getProperty(new QName(uri, localName));
+    }
+    
+    /**
+     * Returns a property.
+     * @param name the name of the property
+     * @return the requested property or null if it's not available
+     */
+    public XMPProperty getProperty(QName name) {
+        XMPProperty prop = (XMPProperty)properties.get(name);
+        return prop;
+    }
+    
+    /** @return the number of properties in this metadata object. */
+    public int getPropertyCount() {
+        return this.properties.size();
+    }
+    
+    /**
+     * Merges this metadata object into a given target metadata object. The merge rule set provided
+     * by each schema is used for the merge.
+     * @param target the target metadata to merge the local metadata into
+     */
+    public void mergeInto(Metadata target) {
+        XMPSchemaRegistry registry = XMPSchemaRegistry.getInstance();
+        Iterator iter = properties.values().iterator();
+        while (iter.hasNext()) {
+            XMPProperty prop = (XMPProperty)iter.next();
+            XMPSchema schema = registry.getSchema(prop.getNamespace());
+            MergeRuleSet rules = schema.getDefaultMergeRuleSet();
+            PropertyMerger merger = rules.getPropertyMergerFor(prop);
+            merger.merge(prop, target);
+        }
+    }
+    
+    /** @see org.apache.xmlgraphics.util.XMLizable#toSAX(org.xml.sax.ContentHandler) */
+    public void toSAX(ContentHandler handler) throws SAXException {
+        AttributesImpl atts = new AttributesImpl();
+        handler.startElement(XMPConstants.XMP_NAMESPACE, "xmpmeta", "x:xmpmeta", atts);
+        handler.startElement(XMPConstants.RDF_NAMESPACE, "RDF", "rdf:RDF", atts);
+        //Get all property namespaces
+        Set namespaces = new java.util.HashSet();
+        Iterator iter = properties.keySet().iterator();
+        while (iter.hasNext()) {
+            namespaces.add(((QName)iter.next()).getNamespaceURI());
+        }
+        //One Description element per namespace
+        iter = namespaces.iterator();
+        while (iter.hasNext()) {
+            String ns = (String)iter.next();
+            XMPSchema schema = XMPSchemaRegistry.getInstance().getSchema(ns);
+            String prefix = (schema != null ? schema.getPreferredPrefix() : null);
+            if (prefix != null) {
+                handler.startPrefixMapping(prefix, ns);
+            }
+            
+            atts.clear();
+            atts.addAttribute(XMPConstants.RDF_NAMESPACE, "about", "rdf:about", "CDATA", "");
+            handler.startElement(XMPConstants.RDF_NAMESPACE, "RDF", "rdf:Description", atts);
+            
+            Iterator props = properties.values().iterator();
+            while (props.hasNext()) {
+                XMPProperty prop = (XMPProperty)props.next();
+                if (prop.getName().getNamespaceURI().equals(ns)) {
+                    prop.toSAX(handler);
+                }
+            }
+            handler.endElement(XMPConstants.RDF_NAMESPACE, "RDF", "rdf:Description");
+            if (prefix != null) {
+                handler.endPrefixMapping(prefix);
+            }
+        }
+        
+        handler.endElement(XMPConstants.RDF_NAMESPACE, "RDF", "rdf:RDF");
+        handler.endElement(XMPConstants.XMP_NAMESPACE, "xmpmeta", "x:xmpmeta");
+    }
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/Metadata.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/Metadata.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPArray.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPArray.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPArray.java (added)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPArray.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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$ */
+
+package org.apache.xmlgraphics.xmp;
+
+import java.util.List;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * Represents an XMP array as defined by the XMP specification.
+ * @todo Property qualifiers are currently not supported, yet. 
+ */
+public class XMPArray extends XMPComplexValue {
+
+    private XMPArrayType type;
+    private List values = new java.util.ArrayList();
+    private List xmllang = new java.util.ArrayList();
+    
+    /**
+     * Main constructor
+     * @param type the intended type of array
+     */
+    public XMPArray(XMPArrayType type) {
+        this.type = type;
+    }
+    
+    /** @return the type of array */
+    public XMPArrayType getType() {
+        return this.type;
+    }
+    
+    /**
+     * Returns the value at a given position
+     * @param idx the index of the requested value
+     * @return the value at the given position
+     */
+    public Object getValue(int idx) {
+        return this.values.get(idx);
+    }
+
+    /** @see org.apache.xmlgraphics.xmp.XMPComplexValue#getSimpleValue() */
+    public Object getSimpleValue() {
+        if (values.size() == 1) {
+            return getValue(0);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns a language-dependant values (available for alternative arrays).
+     * @param lang the language ("x-default" for the default value)
+     * @return the requested value
+     */
+    public String getLangValue(String lang) {
+        String v = null;
+        for (int i = 0, c = values.size(); i < c; i++) {
+            String l = (String)xmllang.get(i);
+            if ((l == null && lang == null) || (l != null && l.equals(lang))) {
+                v = values.get(i).toString();
+                break;
+            }
+        }
+        if (lang == null && v == null) {
+            v = getLangValue(XMPConstants.DEFAULT_LANGUAGE);
+            if (v == null && values.size() > 0) {
+                v = getValue(0).toString(); //get first
+            }
+        }
+        return v;
+    }
+    
+    /**
+     * Removes a language-dependant value
+     * @param lang the language ("x-default" for the default value)
+     */
+    public void removeLangValue(String lang) {
+        if (lang == null && "".equals(lang)) {
+            return;
+        }
+        for (int i = 0, c = values.size(); i < c; i++) {
+            String l = (String)xmllang.get(i);
+            if (lang.equals(l)) {
+                values.remove(i);
+                xmllang.remove(i);
+                return;
+            }
+        }
+    }
+    
+    /**
+     * Adds a new value to the array
+     * @param value the value
+     */
+    public void add(Object value) {
+        values.add(value);
+        xmllang.add(null);
+    }
+
+    /**
+     * Adds a language-dependant value to the array. Make sure not to add the same language twice.
+     * @param value the value
+     * @param lang the language ("x-default" for the default value)
+     */
+    public void add(String value, String lang) {
+        values.add(value);
+        xmllang.add(lang);
+    }
+
+    /** @return the current number of value in the array */
+    public int getSize() {
+        return this.values.size();
+    }
+    
+    /**
+     * Converts the array to an object array.
+     * @return an object array of all values in the array
+     */
+    public Object[] toObjectArray() {
+        Object[] res = new Object[getSize()];
+        for (int i = 0, c = res.length; i < c; i++) {
+            res[i] = getValue(i);
+        }
+        return res;
+    }
+
+    /** @see org.apache.xmlgraphics.util.XMLizable#toSAX(org.xml.sax.ContentHandler) */
+    public void toSAX(ContentHandler handler) throws SAXException {
+        AttributesImpl atts = new AttributesImpl();
+        handler.startElement(XMPConstants.RDF_NAMESPACE, 
+                type.getName(), "rdf:" + type.getName(), atts);
+        for (int i = 0, c = values.size(); i < c; i++) {
+            String value = (String)values.get(i);
+            String lang = (String)xmllang.get(i);
+            atts.clear();
+            if (lang != null) {
+                atts.addAttribute(XMPConstants.XML_NS, "lang", "xml:lang", "CDATA", lang);
+            }
+            handler.startElement(XMPConstants.RDF_NAMESPACE, 
+                    "li", "rdf:li", atts);
+            char[] chars = value.toCharArray();
+            handler.characters(chars, 0, chars.length);
+            handler.endElement(XMPConstants.RDF_NAMESPACE, 
+                    "li", "rdf:li");
+        }
+        handler.endElement(XMPConstants.RDF_NAMESPACE, 
+                type.getName(), "rdf:" + type.getName());
+    }
+
+    /** @see java.lang.Object#toString() */
+    public String toString() {
+        return "XMP array: " + type + ", " + getSize();
+    }
+
+    
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPArray.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPArray.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPArrayType.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPArrayType.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPArrayType.java (added)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPArrayType.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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$ */
+
+package org.apache.xmlgraphics.xmp;
+
+/** Enum class for XMP array types. */
+public final class XMPArrayType {
+
+    /** the unordered array */
+    public static final XMPArrayType BAG = new XMPArrayType("Bag");
+    /** the ordered array */
+    public static final XMPArrayType SEQ = new XMPArrayType("Seq");
+    /** the alternative array */
+    public static final XMPArrayType ALT = new XMPArrayType("Alt");
+    
+    private String name;
+
+    /**
+     * Constructor to add a new named item.
+     * @param name Name of the item.
+     */
+    private XMPArrayType(String name) {
+        this.name = name;
+    }
+
+    /** @return the name of the enum */
+    public String getName() {
+        return this.name;
+    }
+    
+    /** @see java.lang.Object#toString() */
+    public String toString() {
+        return "rdf:" + name;
+    }
+    
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPArrayType.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPArrayType.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPComplexValue.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPComplexValue.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPComplexValue.java (added)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPComplexValue.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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$ */
+
+package org.apache.xmlgraphics.xmp;
+
+import org.apache.xmlgraphics.util.XMLizable;
+
+/**
+ * Base class for complex data types in XMP.
+ */
+public abstract class XMPComplexValue implements XMLizable {
+
+    /**
+     * Returns a normal Java object representing the value if it is available.
+     * @return a simple object value or null if no such value can be returned (for example,
+     *          because the value is an array and has multiple entries.
+     */
+    public abstract Object getSimpleValue();
+    
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPComplexValue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPComplexValue.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPConstants.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPConstants.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPConstants.java (added)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPConstants.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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$ */
+
+package org.apache.xmlgraphics.xmp;
+
+/**
+ * Constants used in XMP metadata.
+ */
+public interface XMPConstants {
+
+    /** Namespace URI for the xml: prefix */
+    String XML_NS = "http://www.w3.org/XML/1998/namespace";
+    
+    /** Namespace URI for XMP */
+    String XMP_NAMESPACE = "adobe:ns:meta/";
+    
+    /** Namespace URI for RDF */
+    String RDF_NAMESPACE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+
+    /** Namespace URI for Dublin Core */ 
+    String DUBLIN_CORE_NAMESPACE = "http://purl.org/dc/elements/1.1/";
+    
+    /** Namespace URI for the XMP Basic Schema */
+    String XMP_BASIC_NAMESPACE = "http://ns.adobe.com/xap/1.0/";
+    
+    /** Namespace URI for the Adobe PDF Schema */
+    String ADOBE_PDF_NAMESPACE = "http://ns.adobe.com/pdf/1.3/";
+
+    /** Namespace URI for the PDF/A Identification Schema */
+    String PDF_A_IDENTIFICATION = "http://www.aiim.org/pdfa/ns/id";
+    
+    /**
+     * Namespace URI for the PDF/A Identification Schema
+     * (from an older draft of ISO 19005-1, used by Adobe Acrobat)
+     */
+    String PDF_A_IDENTIFICATION_OLD = "http://www.aiim.org/pdfa/ns/id.html";
+
+    /** Default language for the xml:lang property */
+    String DEFAULT_LANGUAGE = "x-default";
+    
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPConstants.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPConstants.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPHandler.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPHandler.java (added)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPHandler.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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$ */
+
+package org.apache.xmlgraphics.xmp;
+
+import java.util.Stack;
+
+import org.apache.xmlgraphics.util.QName;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * Passive XMP parser implemented as a SAX DefaultHandler. After the XML document has been parsed
+ * the Metadata object can be retrieved.
+ */
+public class XMPHandler extends DefaultHandler {
+
+    private Metadata meta;
+    
+    private StringBuffer content = new StringBuffer();
+    //private Attributes lastAttributes;
+    private Stack attributesStack = new Stack();
+    //private Stack contextStack = new Stack();
+    
+    private QName currentPropertyName;
+    private XMPProperty currentProperty;
+    private XMPComplexValue currentComplexValue;
+    
+    /** @return the parsed metadata, available after the parsing. */
+    public Metadata getMetadata() {
+        return this.meta;
+    }
+
+    // --- Overrides ---
+    
+    /**
+     * @see org.xml.sax.helpers.DefaultHandler#startElement(
+     *      java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
+     */
+    public void startElement(String uri, String localName, String qName, Attributes attributes) 
+                throws SAXException {
+        super.startElement(uri, localName, qName, attributes);
+        content.setLength(0); //Reset text buffer (see characters())
+        attributesStack.push(new AttributesImpl(attributes));
+        
+        if (XMPConstants.XMP_NAMESPACE.equals(uri)) {
+            if (!"xmpmeta".equals(localName)) {
+                throw new SAXException("Expected x:xmpmeta element, not " + qName);
+            }
+            if (this.meta != null) {
+                throw new SAXException("Invalid XMP document. Root already received earlier.");
+            }
+            this.meta = new Metadata();
+        } else if (XMPConstants.RDF_NAMESPACE.equals(uri)) {
+            if ("RDF".equals(localName)) {
+                if (this.meta == null) {
+                    this.meta = new Metadata();
+                }
+            } else if ("Description".equals(localName)) {
+                if (currentPropertyName == null) {
+                    //rdf:RDF is the parent
+                    String about = attributes.getValue(XMPConstants.RDF_NAMESPACE, "about");
+                } else {
+                    //a structured property is the parent
+                }
+            } else if ("Seq".equals(localName)) {
+                this.currentComplexValue = new XMPArray(XMPArrayType.SEQ);
+            } else if ("Bag".equals(localName)) {
+                this.currentComplexValue = new XMPArray(XMPArrayType.BAG);
+            } else if ("Alt".equals(localName)) {
+                this.currentComplexValue = new XMPArray(XMPArrayType.ALT);
+            } else if ("li".equals(localName)) {
+            }
+        } else {
+            this.currentPropertyName = new QName(uri, qName);
+        }
+    }
+    
+    /**
+     * @see org.xml.sax.helpers.DefaultHandler#endElement(
+     *      java.lang.String, java.lang.String, java.lang.String)
+     */
+    public void endElement(String uri, String localName, String qName) throws SAXException {
+        Attributes atts = (Attributes)attributesStack.pop();
+        if (XMPConstants.XMP_NAMESPACE.equals(uri)) {
+            //nop
+        } else if (XMPConstants.RDF_NAMESPACE.equals(uri)) {
+            if ("li".equals(localName)) {
+                String s = content.toString().trim();
+                if (s.length() > 0) {
+                    getCurrentArray().add(s);
+                }
+            } else {
+                //nop
+            }
+        } else {
+            if (this.currentComplexValue != null) {
+                this.currentProperty = new XMPProperty(this.currentPropertyName, 
+                                this.currentComplexValue);
+                this.currentComplexValue = null;
+            } else {
+                String s = content.toString().trim();
+                this.currentProperty = new XMPProperty(this.currentPropertyName, s);
+                String lang = atts.getValue(XMPConstants.XML_NS, "lang");
+                if (lang != null) {
+                    this.currentProperty.setXMLLang(lang);
+                }
+            }
+            this.meta.setProperty(this.currentProperty);
+            this.currentProperty = null;
+            this.currentPropertyName = null;
+        }
+        content.setLength(0); //Reset text buffer (see characters())
+        super.endElement(uri, localName, qName);
+    }
+
+    private XMPArray getCurrentArray() {
+        return (XMPArray)this.currentComplexValue;
+    }
+
+    /** @see org.xml.sax.ContentHandler#characters(char[], int, int) */
+    public void characters(char[] ch, int start, int length) throws SAXException {
+        content.append(ch, start, length);
+    }
+
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPHandler.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPParser.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPParser.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPParser.java (added)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPParser.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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$ */
+
+package org.apache.xmlgraphics.xmp;
+
+import java.net.URL;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.stream.StreamSource;
+
+/**
+ * The XMP parser.
+ */
+public class XMPParser {
+
+    /**
+     * Parses an XMP file.
+     * @param url the URL to load the file from
+     * @return the parsed Metadata object
+     * @throws TransformerException if an error occurs while parsing the file
+     */
+    public static Metadata parseXMP(URL url) throws TransformerException {
+        return parseXMP(new StreamSource(url.toExternalForm()));
+    }
+    
+    /**
+     * Parses an XMP file.
+     * @param src a JAXP Source object where the XMP file can be loaded from
+     * @return the parsed Metadata object
+     * @throws TransformerException if an error occurs while parsing the file
+     */
+    public static Metadata parseXMP(Source src) throws TransformerException {
+        TransformerFactory tFactory = TransformerFactory.newInstance();
+        Transformer transformer = tFactory.newTransformer();
+        XMPHandler handler = createXMPHandler();
+        SAXResult res = new SAXResult(handler);
+        transformer.transform(src, res);
+        return handler.getMetadata();
+    }
+
+    /**
+     * Creates and returns an XMPHandler for passive XMP parsing.
+     * @return the requested XMPHandler
+     */
+    public static XMPHandler createXMPHandler() {
+        return new XMPHandler();
+    }
+    
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPParser.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPParser.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPProperty.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPProperty.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPProperty.java (added)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPProperty.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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$ */
+
+package org.apache.xmlgraphics.xmp;
+
+import org.apache.xmlgraphics.util.QName;
+import org.apache.xmlgraphics.util.XMLizable;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * This class is the base class for all XMP properties.
+ */
+public class XMPProperty implements XMLizable {
+
+    private QName name;
+    private Object value;
+    private String xmllang;
+
+    /**
+     * Creates a new XMP property.
+     * @param name the name of the property
+     * @param value the value for the property
+     */
+    public XMPProperty(QName name, Object value) {
+        this.name = name;
+        this.value = value;
+    }
+    
+    /** @return the qualified name of the property (namespace URI + local name) */
+    public QName getName() {
+        return this.name;
+    }
+    
+    /** @return the namespace URI of the property */
+    public String getNamespace() {
+        return getName().getNamespaceURI();
+    }
+    
+    /**
+     * Sets the value of the property
+     * @param value the new value
+     */
+    public void setValue(Object value) {
+        this.value = value;
+    }
+    
+    /**
+     * @return the property value (can be a normal Java object (normally a String) or a descendant
+     *         of XMPComplexValue.
+     */
+    public Object getValue() {
+        return this.value;
+    }
+    
+    /**
+     * Sets the xml:lang value for this property
+     * @param lang the language ("x-default" for the default language, null to make the value
+     *             language-independent)
+     */
+    public void setXMLLang(String lang) {
+        this.xmllang = lang;
+    }
+    
+    /**
+     * @return the language for language-dependent values ("x-default" for the default language)
+     */
+    public String getXMLLang() {
+        return this.xmllang;
+    }
+    
+    /** @return the XMPArray for an array or null if the value is not an array. */
+    public XMPArray getArrayValue() {
+        return (value instanceof XMPArray ? (XMPArray)value : null);
+    }
+    
+    /**
+     * Converts a simple value to an array of a given type if the value is not already an array.
+     * @param type the desired type of array
+     */
+    public void convertSimpleValueToArray(XMPArrayType type) {
+        if (getArrayValue() == null) {
+            XMPArray array = new XMPArray(type);
+            if (getXMLLang() != null) {
+                array.add(getValue().toString(), getXMLLang());
+            } else {
+                array.add(getValue());
+            }
+            setValue(array);
+            setXMLLang(null);
+        }
+    }
+    
+    private String getEffectiveQName() {
+        String prefix = getName().getPrefix();
+        if (prefix == null || "".equals(prefix)) {
+            XMPSchema schema = XMPSchemaRegistry.getInstance().getSchema(getNamespace());
+            prefix = schema.getPreferredPrefix();
+        }
+        return prefix + ":" + getName().getLocalName();
+    }
+    
+    /** @see org.apache.xmlgraphics.util.XMLizable#toSAX(org.xml.sax.ContentHandler) */
+    public void toSAX(ContentHandler handler) throws SAXException {
+        AttributesImpl atts = new AttributesImpl();
+        String qName = getEffectiveQName();
+        handler.startElement(getName().getNamespaceURI(), 
+                getName().getLocalName(), qName, atts);
+        if (value instanceof XMPComplexValue) {
+            XMPComplexValue cv = ((XMPComplexValue)value);
+            Object obj = cv.getSimpleValue();
+            if (obj != null) {
+                char[] chars = obj.toString().toCharArray();
+                handler.characters(chars, 0, chars.length);
+            } else {
+                cv.toSAX(handler);
+            }
+        } else {
+            char[] chars = value.toString().toCharArray();
+            handler.characters(chars, 0, chars.length);
+        }
+        handler.endElement(getName().getNamespaceURI(), 
+                getName().getLocalName(), qName);
+    }
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPProperty.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPProperty.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchema.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchema.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchema.java (added)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchema.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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$ */
+
+package org.apache.xmlgraphics.xmp;
+
+import org.apache.xmlgraphics.util.QName;
+import org.apache.xmlgraphics.xmp.merge.MergeRuleSet;
+
+/**
+ * Base class for schema implementations that provide user-friendly access to XMP values.
+ */
+public class XMPSchema {
+
+    private static MergeRuleSet defaultMergeRuleSet = new MergeRuleSet();
+
+    private String namespace;
+    private String prefix;
+    
+    /**
+     * Constructs a new XMP schema object.
+     * @param namespace the namespace URI for the schema
+     * @param preferredPrefix the preferred prefix for the schema
+     */
+    public XMPSchema(String namespace, String preferredPrefix) {
+        this.namespace = namespace;
+        this.prefix = preferredPrefix;
+    }
+    
+    /** @return the namespace URI of the schema */
+    public String getNamespace() {
+        return this.namespace;
+    }
+    
+    /** @return the preferred prefix of the schema */
+    public String getPreferredPrefix() {
+        return this.prefix;
+    }
+    
+    /**
+     * Returns the QName for a property of this schema.
+     * @param propName the property name
+     * @return the QName for the property
+     */
+    protected QName getQName(String propName) {
+        return new QName(getNamespace(), propName);
+    }
+
+    /** @return the default merge rule set for this XMP schema. */
+    public MergeRuleSet getDefaultMergeRuleSet() {
+        return defaultMergeRuleSet;
+    }
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchema.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchema.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchemaAdapter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchemaAdapter.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchemaAdapter.java (added)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchemaAdapter.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,297 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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$ */
+
+package org.apache.xmlgraphics.xmp;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+import org.apache.xmlgraphics.util.QName;
+
+/**
+ * Base class for schema-specific adapters that provide user-friendly access to XMP values.
+ */
+public class XMPSchemaAdapter {
+
+    private static DateFormat pseudoISO8601DateFormat = new SimpleDateFormat(
+                                                            "yyyy'-'MM'-'dd'T'HH':'mm':'ss");
+
+    /** the Metadata object this schema instance operates on */
+    protected Metadata meta;
+    private XMPSchema schema;
+    
+    /**
+     * Main constructor.
+     * @param meta the Metadata object to wrao
+     * @param schema the XMP schema for which this adapter was written
+     */
+    public XMPSchemaAdapter(Metadata meta, XMPSchema schema) {
+        if (meta == null) {
+            throw new NullPointerException("Parameter meta must not be null");
+        }
+        if (schema == null) {
+            throw new NullPointerException("Parameter schema must not be null");
+        }
+        this.meta = meta;
+        this.schema = schema;
+    }
+    
+    /** @return the XMP schema associated with this adapter */
+    public XMPSchema getSchema() {
+        return this.schema;
+    }
+    
+    /**
+     * Returns the QName for a given property
+     * @param propName the property name
+     * @return the resulting QName
+     */
+    protected QName getQName(String propName) {
+        return new QName(getSchema().getNamespace(), propName);
+    }
+
+    /**
+     * Adds a String value to an array.
+     * @param propName the property name
+     * @param value the String value
+     * @param arrayType the type of array to operate on
+     */
+    private void addStringToArray(String propName, String value, XMPArrayType arrayType) {
+        QName name = getQName(propName);
+        XMPProperty prop = meta.getProperty(name);
+        XMPArray array;
+        if (prop == null) {
+            array = new XMPArray(arrayType);
+            array.add(value);
+            prop = new XMPProperty(name, array);
+            meta.setProperty(prop);
+        } else {
+            prop.convertSimpleValueToArray(arrayType);
+            prop.getArrayValue().add(value);
+        }
+    }
+
+    /**
+     * Adds a String value to an ordered array.
+     * @param propName the property name
+     * @param value the String value
+     */
+    protected void addStringToSeq(String propName, String value) {
+        addStringToArray(propName, value, XMPArrayType.SEQ);
+    }
+
+    /**
+     * Adds a String value to an unordered array.
+     * @param propName the property name
+     * @param value the String value
+     */
+    protected void addStringToBag(String propName, String value) {
+        addStringToArray(propName, value, XMPArrayType.BAG);
+    }
+
+    /**
+     * Formats a Date using ISO 8601 format in the default time zone.
+     * @param dt the date
+     * @return the formatted date
+     */
+    public static String formatISO8601Date(Date dt) {
+        //ISO 8601 cannot be expressed directly using SimpleDateFormat
+        StringBuffer sb = new StringBuffer(pseudoISO8601DateFormat.format(dt));
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(dt);
+        int offset = cal.get(Calendar.ZONE_OFFSET);
+        offset += cal.get(Calendar.DST_OFFSET);
+        offset /= (1000 * 60); //Convert to minutes
+        
+        if (offset == 0) {
+            sb.append('Z');
+        } else {
+            int zoneOffsetHours = offset / 60;
+            int zoneOffsetMinutes = Math.abs(offset % 60);
+            if (zoneOffsetHours > 0) {
+                sb.append('+');
+            } else {
+                sb.append('-');
+            }
+            if (zoneOffsetHours < 10) {
+                sb.append('0');
+            }
+            sb.append(zoneOffsetHours);
+            sb.append(':');
+            if (zoneOffsetMinutes < 10) {
+                sb.append('0');
+            }
+            sb.append(zoneOffsetMinutes);
+        }
+        
+        return sb.toString();
+    }
+    
+    /**
+     * Adds a date value to an ordered array.
+     * @param propName the property name
+     * @param value the date value
+     */
+    protected void addDateToSeq(String propName, Date value) {
+        String dt = formatISO8601Date(value);
+        addStringToSeq(propName, dt);
+    }
+    
+    /**
+     * Set a date value.
+     * @param propName the property name
+     * @param value the date value
+     */
+    protected void setDateValue(String propName, Date value) {
+        String dt = formatISO8601Date(value);
+        setValue(propName, dt);
+    }
+
+    /**
+     * Sets a language-dependent value.
+     * @param propName the property name
+     * @param lang the language ("x-default" or null for the default language)
+     * @param value the value
+     */
+    protected void setLangAlt(String propName, String lang, String value) {
+        if (lang == null) {
+            lang = XMPConstants.DEFAULT_LANGUAGE;
+        }
+        QName name = getQName(propName);
+        XMPProperty prop = meta.getProperty(name);
+        XMPArray array;
+        if (prop == null) {
+            array = new XMPArray(XMPArrayType.ALT);
+            array.add(value, lang);
+            prop = new XMPProperty(name, array);
+            meta.setProperty(prop);
+        } else {
+            prop.convertSimpleValueToArray(XMPArrayType.ALT);
+            removeLangAlt(lang, propName);
+            prop.getArrayValue().add(value, lang);
+        }
+    }
+
+    /**
+     * Sets a simple value.
+     * @param propName the property name
+     * @param value the value
+     */
+    protected void setValue(String propName, String value) {
+        QName name = getQName(propName);
+        XMPProperty prop = meta.getProperty(name);
+        if (prop == null) {
+            prop = new XMPProperty(name, value);
+            meta.setProperty(prop);
+        } else {
+            prop.setValue(value);
+        }
+    }
+
+    /**
+     * Returns a simple value.
+     * @param propName the property name
+     * @return the requested value or null if it isn't set
+     */
+    protected String getValue(String propName) {
+        QName name = getQName(propName);
+        XMPProperty prop = meta.getProperty(name);
+        if (prop == null) {
+            return null;
+        } else {
+            return prop.getValue().toString();
+        }
+    }
+
+    /**
+     * Removes a language-dependent value from an alternative array.
+     * @param lang the language ("x-default" for the default language)
+     * @param propName the property name
+     */
+    protected void removeLangAlt(String lang, String propName) {
+        XMPProperty prop = meta.getProperty(getQName(propName));
+        XMPArray array;
+        if (prop != null && lang != null) {
+            array = prop.getArrayValue();
+            if (array != null) {
+                array.removeLangValue(lang);
+            } else {
+                if (lang.equals(prop.getXMLLang())) {
+                    prop.setValue(null);
+                    prop.setXMLLang(null);
+                }
+            }
+        }
+    }
+    
+    /**
+     * Returns a language-dependent value. If the value in the requested language is not available
+     * the value for the default language is returned.
+     * @param lang the language ("x-default" for the default language)
+     * @param propName the property name
+     * @return the requested value
+     */
+    protected String getLangAlt(String lang, String propName) {
+        XMPProperty prop = meta.getProperty(getQName(propName));
+        XMPArray array;
+        if (prop == null) {
+            return null;
+        } else {
+            array = prop.getArrayValue();
+            if (array != null) {
+                return array.getLangValue(lang);
+            } else {
+                return prop.getValue().toString();
+            }
+        }
+    }
+
+    /**
+     * Returns an object array representation of the property's values.
+     * @param propName the property name
+     * @return the object array
+     */
+    protected Object[] getObjectArray(String propName) {
+        XMPProperty prop = meta.getProperty(getQName(propName));
+        XMPArray array = prop.getArrayValue();
+        if (array != null) {
+            return array.toObjectArray();
+        } else {
+            return new Object[] {prop.getValue()};
+        }
+    }
+
+    /**
+     * Returns a String array representation of the property's values. Complex values to converted
+     * to Strings using the toString() method.
+     * @param propName the property name
+     * @return the String array
+     */
+    protected String[] getStringArray(String propName) {
+        Object[] arr = getObjectArray(propName);
+        String[] res = new String[arr.length];
+        for (int i = 0, c = res.length; i < c; i++) {
+            res[i] = arr[i].toString();
+        }
+        return res;
+    }
+
+    
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchemaAdapter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchemaAdapter.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchemaRegistry.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchemaRegistry.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchemaRegistry.java (added)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchemaRegistry.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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$ */
+
+package org.apache.xmlgraphics.xmp;
+
+import java.util.Map;
+
+import org.apache.xmlgraphics.xmp.schemas.DublinCoreSchema;
+import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema;
+import org.apache.xmlgraphics.xmp.schemas.pdf.AdobePDFSchema;
+import org.apache.xmlgraphics.xmp.schemas.pdf.PDFAOldXMPSchema;
+import org.apache.xmlgraphics.xmp.schemas.pdf.PDFAXMPSchema;
+
+/**
+ * This class is a registry of XMP schemas. It's implemented as a singleton.
+ */
+public class XMPSchemaRegistry {
+
+    private static XMPSchemaRegistry instance = null;
+
+    private Map schemas = new java.util.HashMap(); 
+    
+    private XMPSchemaRegistry() {
+        init();
+    }
+    
+    /** @return the singleton instance of the XMP schema registry. */
+    public static XMPSchemaRegistry getInstance() {
+        if (instance == null) {
+            instance = new XMPSchemaRegistry();
+        }
+        return instance;
+    }
+    
+    private void init() {
+        addSchema(new DublinCoreSchema());
+        addSchema(new PDFAXMPSchema());
+        addSchema(new PDFAOldXMPSchema());
+        addSchema(new XMPBasicSchema());
+        addSchema(new AdobePDFSchema());
+    }
+    
+    /**
+     * Adds an XMP schema to the registry.
+     * @param schema the XMP schema
+     */
+    public void addSchema(XMPSchema schema) {
+        schemas.put(schema.getNamespace(), schema);
+    }
+    
+    /**
+     * Returns the XMP schema object for a given namespace.
+     * @param namespace the namespace URI
+     * @return the XMP schema or null if none is available
+     */
+    public XMPSchema getSchema(String namespace) {
+        return (XMPSchema)schemas.get(namespace);
+    }
+    
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchemaRegistry.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSchemaRegistry.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSerializer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSerializer.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSerializer.java (added)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSerializer.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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$ */
+
+package org.apache.xmlgraphics.xmp;
+
+import java.io.OutputStream;
+
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Result;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+
+import org.xml.sax.SAXException;
+
+/**
+ * Serializes an XMP tree to XML or to an XMP packet.
+ */
+public class XMPSerializer {
+
+    private static final String DEFAULT_ENCODING = "UTF-8";
+    
+    /**
+     * Writes the in-memory representation of the XMP metadata to a JAXP Result.
+     * @param meta the metadata
+     * @param res the JAXP Result to write to
+     * @throws TransformerConfigurationException if an error occurs setting up the XML 
+     *              infrastructure.
+     * @throws SAXException if a SAX-related problem occurs while writing the XML
+     */
+    public static void writeXML(Metadata meta, Result res) 
+            throws TransformerConfigurationException, SAXException {
+        writeXML(meta, res, false, false);
+    }
+    
+    /**
+     * Writes the in-memory representation of the XMP metadata to an OutputStream as an XMP packet.
+     * @param meta the metadata
+     * @param out the stream to write to
+     * @param readOnlyXMP true if the generated XMP packet should be read-only
+     * @throws TransformerConfigurationException if an error occurs setting up the XML 
+     *              infrastructure.
+     * @throws SAXException if a SAX-related problem occurs while writing the XML
+     */
+    public static void writeXMPPacket(Metadata meta, OutputStream out, boolean readOnlyXMP) 
+            throws TransformerConfigurationException, SAXException {
+        StreamResult res = new StreamResult(out);
+        writeXML(meta, res, true, readOnlyXMP);
+        
+    }
+    
+    private static void writeXML(Metadata meta, Result res, 
+                    boolean asXMPPacket, boolean readOnlyXMP) 
+                            throws TransformerConfigurationException, SAXException {
+        SAXTransformerFactory tFactory = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
+        TransformerHandler handler = tFactory.newTransformerHandler();
+        Transformer transformer = handler.getTransformer();
+        if (asXMPPacket) {
+            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+        }
+        transformer.setOutputProperty(OutputKeys.ENCODING, DEFAULT_ENCODING);
+        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+        handler.setResult(res);
+        handler.startDocument();
+        if (asXMPPacket) {
+            handler.processingInstruction("xpacket", 
+                    "begin=\"\uFEFF\" id=\"W5M0MpCehiHzreSzNTczkc9d\"");
+        }
+        meta.toSAX(handler);
+        if (asXMPPacket) {
+            if (readOnlyXMP) {
+                handler.processingInstruction("xpacket", "end=\"r\"");
+            } else {
+                //Create padding string (40 * 101 characters is more or less the recommended 4KB)
+                StringBuffer sb = new StringBuffer(101);
+                sb.append('\n');
+                for (int i = 0; i < 100; i++) {
+                    sb.append(" ");
+                }
+                char[] padding = sb.toString().toCharArray();
+                for (int i = 0; i < 40; i++) {
+                    handler.characters(padding, 0, padding.length);
+                }
+                handler.characters(new char[] {'\n'}, 0, 1);
+                handler.processingInstruction("xpacket", "end=\"w\"");
+            }
+
+        }
+        handler.endDocument();
+    }
+    
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSerializer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/XMPSerializer.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/ArrayAddPropertyMerger.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/ArrayAddPropertyMerger.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/ArrayAddPropertyMerger.java (added)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/ArrayAddPropertyMerger.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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$ */
+
+package org.apache.xmlgraphics.xmp.merge;
+
+import org.apache.xmlgraphics.xmp.Metadata;
+import org.apache.xmlgraphics.xmp.XMPArray;
+import org.apache.xmlgraphics.xmp.XMPArrayType;
+import org.apache.xmlgraphics.xmp.XMPProperty;
+
+/**
+ * Merges properties by adding up all items from both ends into one SEQ array.
+ */
+public class ArrayAddPropertyMerger implements PropertyMerger {
+
+    /**
+     * @see org.apache.xmlgraphics.xmp.merge.PropertyMerger#merge(
+     *          org.apache.xmlgraphics.xmp.XMPProperty, org.apache.xmlgraphics.xmp.Metadata)
+     */
+    public void merge(XMPProperty sourceProp, Metadata target) {
+        XMPProperty existing = target.getProperty(sourceProp.getName());
+        if (existing == null) {
+            //simply copy over
+            target.setProperty(sourceProp);
+        } else {
+            existing.convertSimpleValueToArray(XMPArrayType.SEQ);
+            XMPArray array = existing.getArrayValue();
+            XMPArray otherArray = sourceProp.getArrayValue();
+            if (otherArray == null) {
+                if (sourceProp.getXMLLang() != null) {
+                    array.add(sourceProp.getValue().toString(), sourceProp.getXMLLang());
+                } else {
+                    array.add(sourceProp.getValue());
+                }
+            } else {
+                //TODO should be refined (xml:lang etc.)
+                for (int i = 0, c = otherArray.getSize(); i < c; i++) {
+                    array.add(otherArray.getValue(i));
+                }
+            }
+        }
+    }
+
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/ArrayAddPropertyMerger.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/ArrayAddPropertyMerger.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/MergeRuleSet.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/MergeRuleSet.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/MergeRuleSet.java (added)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/MergeRuleSet.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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$ */
+
+package org.apache.xmlgraphics.xmp.merge;
+
+import java.util.Map;
+
+import org.apache.xmlgraphics.util.QName;
+import org.apache.xmlgraphics.xmp.XMPProperty;
+
+/**
+ * Represents a set of rules used to merge to XMP properties. By default, all properties are
+ * merged by replacing any existing values with the value from the source XMP.
+ */
+public class MergeRuleSet {
+
+    private Map rules = new java.util.HashMap();
+    private PropertyMerger defaultMerger = new ReplacePropertyMerger();
+    
+    /** Main constructor. */
+    public MergeRuleSet() {
+    }
+
+    /**
+     * Returns the PropertyMerger that shall be used when merging the given property.
+     * @param prop the property to be merged
+     * @return the PropertyMerger to be used for merging the property
+     */
+    public PropertyMerger getPropertyMergerFor(XMPProperty prop) {
+        PropertyMerger merger = (PropertyMerger)rules.get(prop.getName());
+        return (merger != null ? merger : defaultMerger);
+    }
+    
+    /**
+     * Adds a merge rule to this set.
+     * @param propName the name of the property
+     * @param merger the property merger to be used for this property
+     */
+    public void addRule(QName propName, PropertyMerger merger) {
+        rules.put(propName, merger);
+    }
+    
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/MergeRuleSet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/MergeRuleSet.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/NoReplacePropertyMerger.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/NoReplacePropertyMerger.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/NoReplacePropertyMerger.java (added)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/NoReplacePropertyMerger.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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$ */
+
+package org.apache.xmlgraphics.xmp.merge;
+
+import org.apache.xmlgraphics.xmp.Metadata;
+import org.apache.xmlgraphics.xmp.XMPProperty;
+
+/**
+ * A basic PropertyMerger which only sets a value in the target metadata if there's not already
+ * another value.
+ */
+public class NoReplacePropertyMerger implements PropertyMerger {
+
+    /**
+     * @see org.apache.xmlgraphics.xmp.merge.PropertyMerger#merge(
+     *          org.apache.xmlgraphics.xmp.XMPProperty, org.apache.xmlgraphics.xmp.Metadata)
+     */
+    public void merge(XMPProperty sourceProp, Metadata target) {
+        XMPProperty prop = target.getProperty(sourceProp.getName());
+        if (prop == null) {
+            target.setProperty(sourceProp);
+        }
+    }
+
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/NoReplacePropertyMerger.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/NoReplacePropertyMerger.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/PropertyMerger.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/PropertyMerger.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/PropertyMerger.java (added)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/PropertyMerger.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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$ */
+
+package org.apache.xmlgraphics.xmp.merge;
+
+import org.apache.xmlgraphics.xmp.Metadata;
+import org.apache.xmlgraphics.xmp.XMPProperty;
+
+/**
+ * Defines an interface the classes can implement to provide special property merging behaviour.
+ */
+public interface PropertyMerger {
+
+    /**
+     * Merges a property into a given metadata object
+     * @param sourceProp the source property
+     * @param target the target metadata object
+     */
+    void merge(XMPProperty sourceProp, Metadata target);
+    
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/PropertyMerger.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/PropertyMerger.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/ReplacePropertyMerger.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/ReplacePropertyMerger.java?rev=415389&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/ReplacePropertyMerger.java (added)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/ReplacePropertyMerger.java Mon Jun 19 12:22:02 2006
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed 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$ */
+
+package org.apache.xmlgraphics.xmp.merge;
+
+import org.apache.xmlgraphics.xmp.Metadata;
+import org.apache.xmlgraphics.xmp.XMPProperty;
+
+/**
+ * The most basic PropertyMerger which simply overwrites any existing value in the target metadata.
+ */
+public class ReplacePropertyMerger implements PropertyMerger {
+
+    /**
+     * @see org.apache.xmlgraphics.xmp.merge.PropertyMerger#merge(
+     *          org.apache.xmlgraphics.xmp.XMPProperty, org.apache.xmlgraphics.xmp.Metadata)
+     */
+    public void merge(XMPProperty sourceProp, Metadata target) {
+        target.setProperty(sourceProp);
+    }
+
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/ReplacePropertyMerger.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/xmp/merge/ReplacePropertyMerger.java
------------------------------------------------------------------------------
    svn:keywords = Id



---------------------------------------------------------------------
Apache XML Graphics Project URL: http://xmlgraphics.apache.org/
To unsubscribe, e-mail: commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: commits-help@xmlgraphics.apache.org