/*****************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
package org.apache.padaf.xmpbox.parser;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.apache.padaf.xmpbox.CreateXMPMetadataException;
import org.apache.padaf.xmpbox.XMPMetadata;
import org.apache.padaf.xmpbox.schema.PDFAExtensionSchema;
import org.apache.padaf.xmpbox.schema.PDFAFieldDescription;
import org.apache.padaf.xmpbox.schema.SchemaDescription;
import org.apache.padaf.xmpbox.schema.XMPSchema;
import org.apache.padaf.xmpbox.type.AbstractSimpleProperty;
import org.apache.padaf.xmpbox.type.Attribute;
import org.apache.padaf.xmpbox.type.BadFieldValueException;
import org.apache.padaf.xmpbox.type.BooleanType;
import org.apache.padaf.xmpbox.type.ComplexProperty;
import org.apache.padaf.xmpbox.type.ComplexPropertyContainer;
import org.apache.padaf.xmpbox.type.DateType;
import org.apache.padaf.xmpbox.type.IntegerType;
import org.apache.padaf.xmpbox.type.RealType;
import org.apache.padaf.xmpbox.type.TextType;
import org.apache.padaf.xmpbox.type.ThumbnailType;
import org.apache.pdfbox.io.IOUtils;
/**
* Parse serialized XMP (in XML/RDF Format) to the XmpBox representation.
*
* @author a183132
*
*/
public class XMPDocumentBuilder {
protected NSMapping nsMap;
protected ThreadLocal<XMLStreamReader> reader = new ThreadLocal<XMLStreamReader>();
protected List<XMPDocumentPreprocessor> preprocessors = new ArrayList<XMPDocumentPreprocessor>();
public static final String BAG_NAME = "Bag";
public static final String SEQ_NAME = "Seq";
public static final String ALT_NAME = "Alt";
public static final String VALUE_TYPE_NAME = "valueType";
/**
* Constructor of a XMPDocumentBuilder
*
* @throws XmpSchemaException
* When instancing schema object failed or in PDF/A Extension
* case, if its namespace miss
*/
public XMPDocumentBuilder() throws XmpSchemaException {
nsMap = new NSMapping();
}
/**
* Parsing method. Return a XMPMetadata object with all elements read
*
* @param xmp
* serialized XMP
* @return Metadata with all information read
* @throws XmpParsingException
* When element expected not found
* @throws XmpSchemaException
* When instancing schema object failed or in PDF/A Extension
* case, if its namespace miss
* @throws XmpUnknownValueTypeException
* When ValueType found not correspond to basic type and not has
* been declared in current schema
* @throws XmpExpectedRdfAboutAttribute
* When rdf:Description not contains rdf:about attribute
* @throws XmpXpacketEndException
* When xpacket end Processing Instruction is missing or is
* incorrect
* @throws BadFieldValueException
* When treat a Schema associed to a schema Description in PDF/A
* Extension schema
*/
public XMPMetadata parse(byte[] xmp) throws XmpParsingException,
XmpSchemaException, XmpUnknownValueTypeException,
XmpExpectedRdfAboutAttribute, XmpXpacketEndException,
BadFieldValueException {
if (!(this instanceof XMPDocumentPreprocessor)) {
for (XMPDocumentPreprocessor processor : preprocessors) {
NSMapping additionalNSMapping = processor.process(xmp);
this.nsMap.importNSMapping(additionalNSMapping);
}
}
ByteArrayInputStream is = new ByteArrayInputStream(xmp);
try {
XMLInputFactory factory = XMLInputFactory.newInstance();
reader.set(factory.createXMLStreamReader(is));
// expect xpacket processing instruction
expectNext(XMLStreamReader.PROCESSING_INSTRUCTION,
"Did not find initial xpacket processing instruction");
XMPMetadata metadata = parseInitialXpacket(reader.get().getPIData());
// expect x:xmpmeta
expectNextTag(XMLStreamReader.START_ELEMENT,
"Did not find initial x:xmpmeta");
expectName("adobe:ns:meta/", "xmpmeta");
// expect rdf:RDF
expectNextTag(XMLStreamReader.START_ELEMENT,
"Did not find initial rdf:RDF");
expectName("http://www.w3.org/1999/02/22-rdf-syntax-ns#", "RDF");
nsMap.resetComplexBasicTypesDeclarationInEntireXMPLevel();
// add all namespaces which could declare nsURI of a basicValueType
// all others declarations are ignored
int nsCount = reader.get().getNamespaceCount();
for (int i = 0; i < nsCount; i++) {
if (nsMap.isComplexBasicTypes(reader.get().getNamespaceURI(i))) {
nsMap.setComplexBasicTypesDeclarationForLevelXMP(
reader.get().getNamespaceURI(i),
reader.get().getNamespacePrefix(i));
}
}
// now work on each rdf:Description
int type = reader.get().nextTag();
while (type == XMLStreamReader.START_ELEMENT) {
parseDescription(metadata);
type = reader.get().nextTag();
}
// all description are finished
// expect end of rdf:RDF
expectType(XMLStreamReader.END_ELEMENT,
"Expected end of descriptions");
expectName("http://www.w3.org/1999/02/22-rdf-syntax-ns#", "RDF");
// expect ending xmpmeta
expectNextTag(XMLStreamReader.END_ELEMENT,
"Did not find initial x:xmpmeta");
expectName("adobe:ns:meta/", "xmpmeta");
// expect final processing instruction
expectNext(XMLStreamReader.PROCESSING_INSTRUCTION,
"Did not find final xpacket processing instruction");
// treats xpacket end
if (!reader.get().getPITarget().equals("xpacket")) {
throw new XmpXpacketEndException("Excepted PI xpacket");
}
String xpackData = reader.get().getPIData();
// end attribute must be present and placed in first
// xmp spec says Other unrecognized attributes can follow, but
// should be ignored
if (xpackData.startsWith("end=")) {
// check value (5 for end='X')
if (xpackData.charAt(5)!='r' && xpackData.charAt(5)!='w') {
throw new XmpXpacketEndException(
"Excepted xpacket 'end' attribute with value 'r' or 'w' ");
}
} else {
// should find end='r/w'
throw new XmpXpacketEndException(
"Excepted xpacket 'end' attribute (must be present and placed in first)");
}
metadata.setEndXPacket(xpackData);
// return constructed object
return metadata;
} catch (XMLStreamException e) {
throw new XmpParsingException("An error has occured when processing the underlying XMP source", e);
} finally {
reader.remove();
IOUtils.closeQuietly(is);
}
}
/**
* Parsing method using serialized xmp read from a stream
*
* @param is
* The stream to read
* @return Metadata with all information read
* @throws XmpParsingException
* When element expected not found When element expected not
* found
* @throws XmpSchemaException
* When instancing schema object failed or in PDF/A Extension
* case, if its namespace miss
* @throws XmpUnknownValueTypeException
* When ValueType found not correspond to basic type and not has
* been declared in current schema
* @throws XmpExpectedRdfAboutAttribute
* When rdf:Description not contains rdf:about attribute
* @throws XmpXpacketEndException
* When xpacket end Processing Instruction is missing or is
* incorrect
* @throws BadFieldValueException
* When treat a Schema associed to a schema Description in PDF/A
* Extension schema
*/
public XMPMetadata parse(InputStream input) throws XmpParsingException,
XmpSchemaException, XmpUnknownValueTypeException,
XmpExpectedRdfAboutAttribute, XmpXpacketEndException,
BadFieldValueException {
byte[] bos = getStreamAsByteArray(input);
return parse(bos);
}
private byte[] getStreamAsByteArray(InputStream input) throws XmpParsingException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
IOUtils.copy(input, bos);
} catch (IOException e) {
throw new XmpParsingException("An error has occured when processing the underlying XMP source", e);
} finally {
IOUtils.closeQuietly(bos);
IOUtils.closeQuietly(input);
}
return bos.toByteArray();
}
public void addPreprocessor(XMPDocumentPreprocessor processor) {
this.preprocessors.add(processor);
}
/**
* Check InitialXPacket and build metadata object with these information
*
* @param data
* data corresponding to Initial XPacket Processing Instruction
* Processing Information corresponding to Inital XPacket data
* @return Metadata with specified information
* @throws XmpInitialXPacketParsingException
* When Initial XPacket missing or is incorrect
* @throws CreateXMPMetadataException
* If DOM Document associated could not be created
*/
protected XMPMetadata parseInitialXpacket(String data)
throws XmpInitialXPacketParsingException,
CreateXMPMetadataException {
StringTokenizer tokens = new StringTokenizer(data, " ");
String id = null;
String begin = null;
String bytes = null;
String encoding = null;
while (tokens.hasMoreTokens()) {
String token = tokens.nextToken();
if (!token.endsWith("\"") && !token.endsWith("\'")) {
throw new XmpInitialXPacketParsingException(
"Cannot understand PI data part : '" + token + "'");
}
String quote = token.substring(token.length()-1);
int pos = token.indexOf("="+quote);
if (pos <= 0) {
throw new XmpInitialXPacketParsingException(
"Cannot understand PI data part : '" + token + "'");
}
String name = token.substring(0, pos);
String value = token.substring(pos + 2, token.length() - 1);
if ("id".equals(name)) {
id = value;
} else if ("begin".equals(name)) {
begin = value;
} else if ("bytes".equals(name)) {
bytes = value;
} else if ("encoding".equals(name)) {
encoding = value;
} else {
throw new XmpInitialXPacketParsingException(
"Unknown attribute in xpacket PI : '" + token + "'");
}
}
return new XMPMetadata(begin, id, bytes, encoding);
}
/**
* Check the next element type. all comments are ignored.
*
* @param expectType
* Type of xml element expected
* @param message
* Error message if problems occur
* @throws XmpParsingException
* When element expected not found
* @throws XmpUnexpectedTypeException
* When DOM Element type found unexpected When DOM Element type
* found unexpected
* @throws XMLStreamException
* When error during reading the rest of xmp stream When error
* during reading the rest of xmp stream
*/
private void expectNext(int expectType, String message)
throws XmpParsingException, XmpUnexpectedTypeException,
XMLStreamException {
try {
int type = reader.get().next();
while (type == XMLStreamReader.COMMENT || type == XMLStreamReader.SPACE) {
type = reader.get().next();
}
if (type != expectType) {
throw new XmpUnexpectedTypeException(message);
}
} catch (NoSuchElementException e) {
// unexpected end of stream
throw new XmpParsingException(
"XMP Stream did not end in a good way, invalid content");
}
}
/**
* Check the next element type. White spaces , Comments and Processing
* Instructions are ignored.
*
* @param type
* Type of xml element expected
* @param message
* Error message if problems occur
* @throws XmpParsingException
* When element expected not found
* @throws XmpUnexpectedTypeException
* When DOM Element type found unexpected
* @throws XMLStreamException
* When error during reading the rest of xmp stream
*/
private void expectNextTag(int type, String message)
throws XmpParsingException, XmpUnexpectedTypeException,
XMLStreamException {
try {
if (!(reader.get().nextTag() == type)) {
throw new XmpUnexpectedTypeException(message);
}
} catch (NoSuchElementException e) {
// unexpected end of stream
throw new XmpParsingException(
"XMP Stream did not end in a good way, invalid content");
}
}
/**
* check if qualified name of current element is what is expected
*
* @param namespace
* namespace URI
* @param name
* current element name
* @throws XmpUnexpectedElementQualifiedNameException
* When a qualifiedName found and is not that expected
*
*/
private void expectName(String namespace, String name)
throws XmpUnexpectedElementQualifiedNameException {
if (!reader.get().getNamespaceURI().equals(namespace)) {
throw new XmpUnexpectedElementQualifiedNameException("Expected '"
+ namespace + "' and found '"
+ reader.get().getNamespaceURI() + "'");
}
if (!reader.get().getLocalName().equals(name)) {
throw new XmpUnexpectedElementQualifiedNameException("Expected '"
+ name + "' and found '" + reader.get().getLocalName()
+ "'");
}
}
/**
* Check the current element type.
*
* @param type
* XML element type expected
* @param message
* Error Message if problems occur
* @throws XmpUnexpectedTypeException
* When DOM Element type found unexpected
*/
private void expectType(int type, String message)
throws XmpUnexpectedTypeException {
if (!(type == reader.get().getEventType())) {
throw new XmpUnexpectedTypeException("Expected type " + type
+ " and found " + reader.get().getEventType() + " : "
+ message);
}
}
/**
* Check if rdf:about attribute is declared for rdf description and add all
* attributes to the schema
*
* @param metadata
* Metadata to attach new elements
* @param schema
* Schema corresponding to the rdf:Description use
* @throws XmpExpectedRdfAboutAttribute
* When rdf:Description not contains rdf:about attribute
* @throws XmpUnexpectedTypeException if the attribute is known
* as an expected property but the property type isn't a Simple type.
*/
protected final void treatDescriptionAttributes(XMPMetadata metadata, XMPSchema schema)
throws XmpExpectedRdfAboutAttribute, XmpUnexpectedTypeException {
int cptAtt = reader.get().getAttributeCount();
int i = 0;
boolean rdfAboutFound = false;
String prefix;
while (i < cptAtt) {
if (reader.get().getAttributeLocalName(i).equals("about")) {
prefix = reader.get().getAttributePrefix(i);
if (prefix != null) {
if (!prefix.equals("") && !prefix.equals("rdf")) {
// System.out.println("prefix de l'attribut "+reader.get().getAttributeLocalName(i)+": "+prefix);
throw new XmpExpectedRdfAboutAttribute(
"An about attribute is present but have an invalid prefix (it must be 'rdf')");
}
}
rdfAboutFound = true;
}
Attribute attr = new Attribute(null, reader.get()
.getAttributePrefix(i), reader.get()
.getAttributeLocalName(i), reader.get()
.getAttributeValue(i));
if (!addAttributeAsProperty(metadata, schema, attr)) {
// attribute isn't a property, so add the attribute
schema.setAttribute(attr);
}
i++;
}
if (!rdfAboutFound) {
// create rdf:about if not found
Attribute attr = new Attribute(null,"rdf","about","");
schema.setAttribute(attr);
}
}
/**
* If the attribute has same the name as an expected property of the Schema, then the property is created using the attributes fields.
*
* @param metadata Metadata to attach new elements
* @param schema Schema corresponding to the rdf:Description use
* @param attr the attribute used to create the property
* @return true if the attribute has been converted into Property
*/
private boolean addAttributeAsProperty(XMPMetadata metadata, XMPSchema schema, Attribute attr) {
boolean added = false;
String schemaNamespace = schema.getNamespaceValue();
String prefix = attr.getPrefix() != null ? attr.getPrefix() : schema.getPrefix();
String type = this.nsMap.getSpecifiedPropertyType(schemaNamespace, new QName(schemaNamespace, attr.getLocalName(), prefix));
if (type != null) {
if (type.equals("Text")) {
schema.getContent().addProperty(new TextType(metadata, prefix, attr.getLocalName(), attr.getValue()));
added = true;
} else if (type.equals("Integer")) {
schema.getContent().addProperty(new IntegerType(metadata, prefix, attr.getLocalName(), attr.getValue()));
added = true;
} else if (type.equals("Boolean")) {
schema.getContent().addProperty(new BooleanType(metadata, prefix, attr.getLocalName(), attr.getValue()));
added = true;
} else if (type.equals("Real")) {
schema.getContent().addProperty(new RealType(metadata, prefix, attr.getLocalName(), attr.getValue()));
added = true;
} else if (type.equals("Date")) {
schema.getContent().addProperty(new DateType(metadata, prefix, attr.getLocalName(), attr.getValue()));
added = true;
} else if (type.equals("URI")) {
schema.getContent().addProperty(new TextType(metadata, prefix, attr.getLocalName(), attr.getValue()));
added = true;
} else if (type.equals("URL")) {
schema.getContent().addProperty(new TextType(metadata, prefix, attr.getLocalName(), attr.getValue()));
added = true;
}
}
return added;
}
/**
* Treat each rdf:Description (which must represent a schema), instanciate
* class representation of this schema and add it to metadata
*
* @param metadata
* Metadata to attach new elements
* @throws XmpParsingException
* When element expected not found
* @throws XMLStreamException
* When error during reading the rest of xmp stream
* @throws XmpSchemaException
* When instancing schema object failed or in PDF/A Extension
* case, if its namespace miss
* @throws XmpUnknownValueTypeException
* When ValueType found not correspond to basic type and not has
* been declared in current schema
* @throws XmpExpectedRdfAboutAttribute
* When rdf:Description not contains rdf:about attribute
* @throws BadFieldValueException
* When a bad value found in Schema description content
*/
protected void parseDescription(XMPMetadata metadata)
throws XmpParsingException, XMLStreamException, XmpSchemaException,
XmpUnknownValueTypeException, XmpExpectedRdfAboutAttribute,
BadFieldValueException {
nsMap.resetComplexBasicTypesDeclarationInSchemaLevel();
int cptNS = reader.get().getNamespaceCount();
HashMap<String, String> namespaces = new HashMap<String, String>();
for (int i = 0; i < cptNS; i++) {
namespaces.put(reader.get().getNamespacePrefix(i), reader.get()
.getNamespaceURI(i));
if (nsMap.isComplexBasicTypes(reader.get().getNamespaceURI(i))) {
// System.out.println("in parseDesc method: prefix:"+reader.get().getNamespacePrefix(i)+", nsURI:"+reader.get().getNamespaceURI(i));
nsMap.setComplexBasicTypesDeclarationForLevelSchema(reader
.get().getNamespaceURI(i), reader.get()
.getNamespacePrefix(i));
}
}
// Different treatment for PDF/A Extension schema
// System.out.println(PDFAExtensionSchema.PDFAEXTENSION+";"+PDFAExtensionSchema.PDFAPROPERTY+";"+PDFAExtensionSchema.PDFASCHEMA);
if (namespaces.containsKey(PDFAExtensionSchema.PDFAEXTENSION)) {
if (namespaces.containsKey(PDFAExtensionSchema.PDFAPROPERTY)
&& namespaces.containsKey(PDFAExtensionSchema.PDFASCHEMA)) {
if (namespaces
.containsValue(PDFAExtensionSchema.PDFAEXTENSIONURI)
&& namespaces
.containsValue(PDFAExtensionSchema.PDFAPROPERTYURI)
&& namespaces
.containsValue(PDFAExtensionSchema.PDFASCHEMAURI)) {
PDFAExtensionSchema schema = metadata
.createAndAddPDFAExtensionSchemaWithNS(namespaces);
treatDescriptionAttributes(metadata, schema);
parseExtensionSchema(schema, metadata);
} else {
throw new XmpUnexpectedNamespaceURIException(
"Unexpected namespaceURI in PDFA Extension Schema encountered");
}
} else {
throw new XmpUnexpectedNamespacePrefixException(
"Unexpected namespace Prefix in PDFA Extension Schema");
}
} else {
int c = 0;
String namespaceUri = reader.get().getNamespaceURI(c);
String namespacePrefix = reader.get().getNamespacePrefix(c);
c++;
XMPSchema schema = nsMap.getAssociatedSchemaObject(metadata, namespaceUri, namespacePrefix);
while (c<reader.get().getNamespaceCount() && schema==null) {
// try next
namespaceUri = reader.get().getNamespaceURI(c);
namespacePrefix = reader.get().getNamespacePrefix(c);
schema = nsMap.getAssociatedSchemaObject(metadata, namespaceUri, namespacePrefix);
c++;
}
if (schema != null) {
namespaces.remove(namespacePrefix);
} else {
schema = metadata.createAndAddDefaultSchema(namespacePrefix,namespaceUri);
}
for (int i = 1; i < cptNS; i++) {
schema.setAttribute(new Attribute(XMPSchema.NS_NAMESPACE,
"xmlns", reader.get().getNamespacePrefix(i), reader.get().getNamespaceURI(i)));
}
treatDescriptionAttributes(metadata, schema);
while (reader.get().nextTag() == XMLStreamReader.START_ELEMENT) {
parseProperty(schema, metadata);
}
}
}
/**
* Check the next element type and its expected value
*
* @param type
* expected type of xml element
* @param localNameExpected
* The property name (local) expected
* @param message
* Error message if problems occur
* @throws XmpUnexpectedTypeException
* When DOM Element type found unexpected
* @throws XmpParsingException
* When element expected not found
* @throws XMLStreamException
* When error during reading the rest of xmp stream
*/
private void expectNextSpecificTag(int type, String localNameExpected,
String message) throws XmpUnexpectedTypeException,
XmpParsingException, XMLStreamException {
expectNextTag(type, message);
expectCurrentLocalName(localNameExpected);
}
/**
* check that the current local name is that expected
*
* @param localNameExpected
* The name expected
* @throws XmpUnexpectedElementException
* When Element is not that expected
*/
protected void expectCurrentLocalName(String localNameExpected)
throws XmpUnexpectedElementException {
if (!reader.get().getLocalName().equals(localNameExpected)) {
throw new XmpUnexpectedElementException("'" + localNameExpected
+ "' expected and '" + reader.get().getLocalName()
+ "' found at "+reader.get().getLocation());
}
}
/**
* Treat a PDFAExtension schema
*
* @param schema
* PDFA/Extension schema where save information found
* @param metadata
* Metadata to attach new elements
* @throws XmpParsingException
* When element expected not found
* @throws XMLStreamException
* When error during reading the rest of xmp stream
* @throws XmpUnknownValueTypeException
* When ValueType found not correspond to basic type and not has
* been declared in current schema
* @throws BadFieldValueException
* When one of a field property include to describe a property
* in Schema Description contain an incorrect value
*/
protected final void parseExtensionSchema(PDFAExtensionSchema schema,
XMPMetadata metadata) throws XmpParsingException,
XMLStreamException, XmpUnknownValueTypeException,
BadFieldValueException {
// <pdfaExtension:schemas>
expectNextSpecificTag(XMLStreamReader.START_ELEMENT, "schemas",
"Cannot find container declaration of schemas descriptions ");
// <rdf:Bag>
expectNextSpecificTag(XMLStreamReader.START_ELEMENT, BAG_NAME,
"Cannot find bag declaration for container of schemas descriptions");
// now work on each rdf:li corresponding to each schema description
int type = reader.get().nextTag();
while (type == XMLStreamReader.START_ELEMENT) {
parseSchemaDescription(schema, metadata);
type = reader.get().nextTag();
}
expectNextSpecificTag(XMLStreamReader.END_ELEMENT, "schemas",
"Cannot find end of container declaration in schemas descriptions ");
expectNextSpecificTag(XMLStreamReader.END_ELEMENT, "Description",
"Cannot find end of PDF/A Extension definition ");
}
/**
* Treat one Schema description defined in the extension Schema found
*
* @param schema
* PDFA/Extension schema where save information found
* @param metadata
* Metadata to attach new elements
* @throws XMLStreamException
* When error during reading the rest of xmp stream
* @throws XmpParsingException
* When element expected not found
* @throws XmpUnknownValueTypeException
* When ValueType found not correspond to basic type and not has
* been declared in current schema
* @throws BadFieldValueException
* When one of a field property contain an incorrect value
*/
private void parseSchemaDescription(PDFAExtensionSchema schema,
XMPMetadata metadata) throws XMLStreamException,
XmpParsingException, XmpUnknownValueTypeException,
BadFieldValueException {
expectCurrentLocalName("li");
SchemaDescription desc = schema.createSchemaDescription();
if ("Resource".equals(reader.get().getAttributeValue("http://www.w3.org/1999/02/22-rdf-syntax-ns#", "parseType"))) {
fillSchemaDescription(desc, metadata);
} else {
int type = reader.get().nextTag();
if (type == XMLStreamReader.START_ELEMENT && reader.get().getLocalName().equals("Description")) {
fillSchemaDescription(desc, metadata);
// read the end tag
reader.get().nextTag();
} else {
// ?? TODO
}
}
schema.addSchemaDescription(desc);
nsMap.setNamespaceDefinition(desc);
}
protected void fillSchemaDescription(SchemaDescription desc, XMPMetadata metadata)
throws XMLStreamException, XmpParsingException,
XmpUnknownValueTypeException, BadFieldValueException {
int type = reader.get().nextTag();
while (type == XMLStreamReader.START_ELEMENT) {
if (reader.get().getLocalName().equals("schema")
|| reader.get().getLocalName().equals("namespaceURI")
|| reader.get().getLocalName().equals("prefix")) {
try {
// System.out.println(reader.get().getPrefix()+";"+reader.get().getLocalName()+";"+reader.get().getElementText());
desc.addProperty(new TextType(metadata, reader.get()
.getPrefix(), reader.get().getLocalName(), reader
.get().getElementText()));
} catch (IllegalArgumentException e) {
throw new XmpPropertyFormatException(
"Unexpected value for '"
+ reader.get().getLocalName()
+ "' property");
}
} else if (reader.get().getLocalName().equals("property")) {
parsePropertyDefinition(desc);
} else if (reader.get().getLocalName().equals(VALUE_TYPE_NAME)) {
parseValueTypeDefinition(desc, metadata);
} else {
throw new XmpUnexpectedElementException(
"Unexpected property definition in one of PDF/A Extension schemas description");
}
type = reader.get().nextTag();
}
}
/**
* Treat value type definition for a specific Schema Description
*
* @param desc
* the current Schema Description analyzed
* @param metadata
* Metadata to attach new elements
* @throws XmpParsingException
* When element expected not found
* @throws XMLStreamException
* When error during reading the rest of xmp stream
*/
private void parseValueTypeDefinition(SchemaDescription desc,
XMPMetadata metadata) throws XmpParsingException,
XMLStreamException {
// <rdf:Seq>
expectNextSpecificTag(XMLStreamReader.START_ELEMENT, SEQ_NAME,
"Expected Seq Declaration");
int elmtType = reader.get().nextTag();
String type, namespaceURI, prefix, description;
List<PDFAFieldDescription> fields;
while (elmtType == XMLStreamReader.START_ELEMENT) {
type = null;
namespaceURI = null;
prefix = null;
description = null;
fields = null;
expectCurrentLocalName("li");
elmtType = reader.get().nextTag();
while (elmtType == XMLStreamReader.START_ELEMENT) {
if (reader.get().getLocalName().equals("type")) {
type = reader.get().getElementText();
} else if (reader.get().getLocalName().equals("namespaceURI")) {
namespaceURI = reader.get().getElementText();
} else if (reader.get().getLocalName().equals("prefix")) {
prefix = reader.get().getElementText();
} else if (reader.get().getLocalName().equals("description")) {
description = reader.get().getElementText();
} else if (reader.get().getLocalName().equals("field")) {
fields = parseFieldDescription(metadata);
} else {
throw new XmpUnexpectedElementException(
"Unexpected property definition in one of ValueType Descriptions of PDF/A Extension schemas description");
}
elmtType = reader.get().nextTag();
}
if ((type != null) && (namespaceURI != null) && (prefix != null)
&& (description != null)) {
desc.addValueType(type, namespaceURI, prefix, description,
fields);
} else {
throw new XmpRequiredPropertyException(
"one property declaration in PDF/A Extension is not complete");
}
elmtType = reader.get().nextTag();
}
expectNextSpecificTag(XMLStreamReader.END_ELEMENT, VALUE_TYPE_NAME,
"Expected End of ValueType Declaration");
}
/**
* Treat field description on the current analyzed value type description
*
* @param metadata
* Metadata to attach new elements
* @return A list of parsed fields
* @throws XMLStreamException
* When error during reading the rest of xmp stream
* @throws XmpParsingException
* When element expected not found
*/
private List<PDFAFieldDescription> parseFieldDescription(
XMPMetadata metadata) throws XmpParsingException,
XMLStreamException {
List<PDFAFieldDescription> fields = new ArrayList<PDFAFieldDescription>();
// <rdf:Seq>
expectNextSpecificTag(XMLStreamReader.START_ELEMENT, SEQ_NAME,
"Expected Seq Declaration");
int elmtType = reader.get().nextTag();
String name, type, description;
while (elmtType == XMLStreamReader.START_ELEMENT) {
expectCurrentLocalName("li");
elmtType = reader.get().nextTag();
name = null;
type = null;
description = null;
while (elmtType == XMLStreamReader.START_ELEMENT) {
if (reader.get().getLocalName().equals("name")) {
name = reader.get().getElementText();
} else if (reader.get().getLocalName().equals(VALUE_TYPE_NAME)) {
type = reader.get().getElementText();
} else if (reader.get().getLocalName().equals("description")) {
description = reader.get().getElementText();
} else {
throw new XmpUnexpectedElementException(
"Unexpected property definition in one of ValueType Field Descriptions of PDF/A Extension schemas description");
}
elmtType = reader.get().nextTag();
}
if ((name != null) && (type != null) && (description != null)) {
PDFAFieldDescription tmp = new PDFAFieldDescription(metadata);
tmp.setNameValue(name);
tmp.setValueTypeValue(type);
tmp.setDescriptionValue(description);
fields.add(tmp);
} else {
throw new XmpRequiredPropertyException(
"One valuetype field declaration in PDF/A Extension is not complete");
}
// expectNextTag(XMLStreamReader.END_ELEMENT,"Expected element end");
elmtType = reader.get().nextTag();
}
expectNextSpecificTag(XMLStreamReader.END_ELEMENT, "field",
"Expected End of Properties Declaration");
if (fields.size() != 0) {
return fields;
}
return null;
}
/**
* Treat a property definition for a specific Schema Description
*
* @param desc
* the current Schema Description analyzed
* @throws XmpParsingException
* When element expected not found
* @throws XMLStreamException
* When error during reading the rest of xmp stream
* @throws BadFieldValueException
* When one of a field property contain an incorrect value
*/
private void parsePropertyDefinition(SchemaDescription desc)
throws XmpParsingException, XMLStreamException, BadFieldValueException {
// <rdf:Seq>
expectNextSpecificTag(XMLStreamReader.START_ELEMENT, SEQ_NAME, "Expected Seq Declaration");
// Each property definition
int elmtType = reader.get().nextTag();
while (elmtType == XMLStreamReader.START_ELEMENT) {
expectCurrentLocalName("li");
if ("Resource".equals(reader.get().getAttributeValue("http://www.w3.org/1999/02/22-rdf-syntax-ns#", "parseType"))) {
fillDescription(desc);
} else {
elmtType = reader.get().nextTag();
if (elmtType == XMLStreamReader.START_ELEMENT && reader.get().getLocalName().equals("Description")) {
fillDescription(desc);
// read the end tag
reader.get().nextTag();
} else {
// ?? TODO
}
}
// expectNextTag(XMLStreamReader.END_ELEMENT,"Expected element end");
elmtType = reader.get().nextTag();
}
expectNextSpecificTag(XMLStreamReader.END_ELEMENT, "property",
"Expected End of Properties Declaration");
}
protected void fillDescription(SchemaDescription desc)
throws XmpParsingException, XMLStreamException, BadFieldValueException {
int elmtType = reader.get().nextTag();
String name = null;
String type = null;
String category = null;
String description = null;
while (elmtType == XMLStreamReader.START_ELEMENT) {
if (reader.get().getLocalName().equals("name")) {
name = reader.get().getElementText();
} else if (reader.get().getLocalName().equals(VALUE_TYPE_NAME)) {
type = reader.get().getElementText();
} else if (reader.get().getLocalName().equals("category")) {
category = reader.get().getElementText();
} else if (reader.get().getLocalName().equals("description")) {
description = reader.get().getElementText();
} else {
throw new XmpUnexpectedElementException(
"Unexpected property definition in one of Properties Descriptions of PDF/A Extension schemas description");
}
elmtType = reader.get().nextTag();
}
if ((name != null) && (type != null) && (category != null)&& (description != null)) {
desc.addProperty(name, type, category, description);
} else {
throw new XmpRequiredPropertyException("one property declaration in PDF/A Extension is not complete");
}
}
/**
* Check for all namespaces declared for the specified schema if the
* property searched exists and return its type or null
*
* @param schema
* The Schema to analyze
* @param prop
* The property Qualified Name
* @return The property value type or null if not found in schema
* @throws XmpParsingException
* When element expected not found
*/
private String getPropertyDeclarationInNamespaces(XMPSchema schema,
QName prop) throws XmpParsingException {
Iterator<Attribute> it = schema.getAllAttributes().iterator();
Attribute tmp;
ArrayList<Attribute> list = new ArrayList<Attribute>();
while (it.hasNext()) {
tmp = it.next();
if (tmp.getPrefix() != null) {
if (tmp.getPrefix().equals("xmlns")) {
list.add(tmp);
}
}
}
it = list.iterator();
String type;
StringBuffer unknownNS = new StringBuffer();
while (it.hasNext()) {
String namespace = it.next().getValue();
if (!nsMap.isContainedNamespace(namespace)) {
unknownNS.append(" '").append(namespace).append("' ");
continue;
}
type = nsMap.getSpecifiedPropertyType(namespace, prop);
if (type != null) {
return type;
}
}
String uns = unknownNS.toString().trim();
if ((uns == null) || "".equals(uns)) {
throw new XmpUnknownPropertyException(
"Cannot find a description for '" + prop.getLocalPart()
+ "' property");
} else {
throw new XmpUnknownSchemaException(
"Cannot find a definition for the namespace " + uns + " ");
}
}
/**
* Build a property with the specific type defined in schema or complex
* property and add it to the object representation
*
* @param metadata
* Metadata to attach new elements
* @param propertyName
* The fully qualified name of the property
* @param stype
* Type of the property
* @param container
* the entity where place the property representation
* @throws XmpUnknownPropertyTypeException
* Value Type property is incorrect or the basic value type
* can't be treat at the moment
* @throws XmpPropertyFormatException
* Unexpected type found (IllegalArgumentException)
* @throws XMLStreamException
* When error during reading the rest of xmp stream
*/
protected void parseXmpSimpleProperty(XMPMetadata metadata, QName propertyName, XmpPropertyType stype, ComplexPropertyContainer container)
throws XmpUnknownPropertyTypeException, XmpPropertyFormatException, XMLStreamException {
try {
AbstractSimpleProperty prop = null;
ArrayList<Attribute> attributes = new ArrayList<Attribute>();
int cpt = reader.get().getAttributeCount();
for (int i = 0; i < cpt; i++) {
attributes.add(new Attribute(null, reader.get()
.getAttributePrefix(i), reader.get()
.getAttributeLocalName(i), reader.get()
.getAttributeValue(i)));
}
if (stype == XmpPropertyType.Text) {
prop = new TextType(metadata, propertyName.getPrefix(),
propertyName.getLocalPart(), reader.get()
.getElementText());
} else if (stype == XmpPropertyType.Integer) {
prop = new IntegerType(metadata, propertyName.getPrefix(),
propertyName.getLocalPart(), reader.get()
.getElementText());
} else if (stype == XmpPropertyType.Date) {
prop = new DateType(metadata, propertyName.getPrefix(),
propertyName.getLocalPart(), reader.get()
.getElementText());
} else if (stype == XmpPropertyType.Boolean) {
prop = new BooleanType(metadata, propertyName.getPrefix(),
propertyName.getLocalPart(), reader.get()
.getElementText());
} else if (stype == XmpPropertyType.Real) {
prop = new RealType(metadata, propertyName.getPrefix(),
propertyName.getLocalPart(), reader.get()
.getElementText());
}
if (prop != null) {
container.addProperty(prop);
// ADD ATTRIBUTES
for (Attribute att : attributes) {
prop.setAttribute(att);
}
} else {
throw new XmpUnknownPropertyTypeException(
"Unknown simple type found");
}
} catch (IllegalArgumentException e) {
throw new XmpPropertyFormatException(
"Unexpected type found for the property '"
+ propertyName.getLocalPart() + "'", e);
}
}
/**
* Parse a bag property (unordered array) with the specific type defined in
* schema or complex property and add it to the object representation
*
* @param metadata
* Metadata to attach new elements
* @param bagName
* name of bag property
* @param stype
* type of values contained in this bag
* @param container
* the entity where place the property representation
* @throws XmpUnexpectedTypeException
* When DOM Element type found unexpected
* @throws XmpParsingException
* When element expected not found
* @throws XMLStreamException
* When error during reading the rest of xmp stream
* @throws XmpUnknownPropertyTypeException
* Value Type property is incorrect or the basic value type
* can't be treat at the moment
* @throws XmpPropertyFormatException
* Unexpected type found (IllegalArgumentException)
*/
protected void parseBagProperty(XMPMetadata metadata, QName bagName,
XmpPropertyType stype, ComplexPropertyContainer container)
throws XmpUnexpectedTypeException, XmpParsingException,
XMLStreamException, XmpUnknownPropertyTypeException,
XmpPropertyFormatException {
ComplexProperty bag = new ComplexProperty(metadata,
bagName.getPrefix(), bagName.getLocalPart(),
ComplexProperty.UNORDERED_ARRAY);
container.addProperty(bag);
// <rdf:Bag>
expectNextSpecificTag(XMLStreamReader.START_ELEMENT, BAG_NAME, "Expected Bag Declaration");
// Each property definition
int elmtType = reader.get().nextTag();
while ((elmtType != XMLStreamReader.END_ELEMENT)
&& !reader.get().getName().getLocalPart().equals(BAG_NAME)) {
parseXmpSimpleProperty(metadata, reader.get().getName(), stype, bag.getContainer());
elmtType = reader.get().nextTag();
}
expectNextSpecificTag(XMLStreamReader.END_ELEMENT, bagName
.getLocalPart(), "Expected end of Bag property");
}
protected void parseComplexBagProperty(XMPMetadata metadata, QName bagName, StructuredPropertyParser complexParser,
ComplexPropertyContainer container)
throws XmpUnexpectedTypeException, XmpParsingException,
XMLStreamException, XmpUnknownPropertyTypeException,
XmpPropertyFormatException {
ComplexProperty bag = new ComplexProperty(metadata,
bagName.getPrefix(), bagName.getLocalPart(),
ComplexProperty.UNORDERED_ARRAY);
container.addProperty(bag);
// <rdf:Bag>
expectNextSpecificTag(XMLStreamReader.START_ELEMENT, BAG_NAME,
"Expected Bag Declaration");
// Each property definition
int elmtType = reader.get().nextTag();
while ((elmtType != XMLStreamReader.END_ELEMENT)
&& !reader.get().getName().getLocalPart().equals(BAG_NAME)) {
complexParser.parse(metadata, reader.get().getName(), bag.getContainer());
elmtType = reader.get().nextTag();
}
expectNextSpecificTag(XMLStreamReader.END_ELEMENT, bagName
.getLocalPart(), "Expected end of Bag property");
}
/**
* Parse a seq property (ordered array) with the specific type defined in
* schema or complex property and add it to the object representation
*
* @param metadata
* Metadata to attach new elements
* @param seqName
* name of the seq
* @param stype
* type of values contained in this bag
* @param container
* the entity where place the property representation
* @throws XmpUnexpectedTypeException
* When DOM Element type found unexpected
* @throws XmpParsingException
* When element expected not found
* @throws XMLStreamException
* When error during reading the rest of xmp stream
* @throws XmpUnknownPropertyTypeException
* Value Type property is incorrect or the basic value type
* can't be treat at the moment
* @throws XmpPropertyFormatException
* Unexpected type found (IllegalArgumentException)
*/
protected void parseSeqProperty(XMPMetadata metadata, QName seqName,
XmpPropertyType stype, ComplexPropertyContainer container)
throws XmpUnexpectedTypeException, XmpParsingException,
XMLStreamException, XmpUnknownPropertyTypeException,
XmpPropertyFormatException {
ComplexProperty seq = new ComplexProperty(metadata,
seqName.getPrefix(), seqName.getLocalPart(),
ComplexProperty.ORDERED_ARRAY);
container.addProperty(seq);
// <rdf:Bag>
expectNextSpecificTag(XMLStreamReader.START_ELEMENT, SEQ_NAME,
"Expected Seq Declaration");
// Each property definition
int elmtType = reader.get().nextTag();
while ((elmtType != XMLStreamReader.END_ELEMENT)
&& !reader.get().getName().getLocalPart().equals(SEQ_NAME)) {
parseXmpSimpleProperty(metadata, reader.get().getName(), stype, seq
.getContainer());
elmtType = reader.get().nextTag();
}
expectNextSpecificTag(XMLStreamReader.END_ELEMENT, seqName
.getLocalPart(), "Expected end of Seq property");
}
/**
* Parse Alt property (Alternative language property) with the specific type
* defined in schema or complex property and add it to the object
* representation
*
* @param metadata
* Metadata to attach new elements
* @param altName
* name of Alt property
* @param stype
* type of values contained in this bag
* @param container
* the entity where place the property representation
* @throws XmpUnexpectedTypeException
* When DOM Element type found unexpected
* @throws XmpParsingException
* When element expected not found
* @throws XMLStreamException
* When error during reading the rest of xmp stream
* @throws XmpUnknownPropertyTypeException
* Value Type property is incorrect or the basic value type
* can't be treat at the moment
* @throws XmpPropertyFormatException
* Unexpected type found (IllegalArgumentException)
*/
protected void parseAltProperty(XMPMetadata metadata, QName altName,
XmpPropertyType stype, ComplexPropertyContainer container)
throws XmpUnexpectedTypeException, XmpParsingException,
XMLStreamException, XmpUnknownPropertyTypeException,
XmpPropertyFormatException {
ComplexProperty alt = new ComplexProperty(metadata,
altName.getPrefix(), altName.getLocalPart(),
ComplexProperty.ALTERNATIVE_ARRAY);
container.addProperty(alt);
// <rdf:Alt>
expectNextSpecificTag(XMLStreamReader.START_ELEMENT, ALT_NAME,
"Expected Alt Declaration");
int elmtType = reader.get().nextTag();
while (!((elmtType == XMLStreamReader.END_ELEMENT) && reader.get()
.getName().getLocalPart().equals(ALT_NAME))) {
parseXmpSimpleProperty(metadata, reader.get().getName(), stype, alt
.getContainer());
elmtType = reader.get().nextTag();
}
// <dc:description><rdf:Alt><rdf:li>sujet</rdf:li></rdf:Alt></dc:description>
expectNextSpecificTag(XMLStreamReader.END_ELEMENT, altName
.getLocalPart(), "Expected end of alt property");
}
/**
* Create a property in a specified container (complexproperty or schema)
*
* @param metadata
* Metadata to attach new elements
* @param type
* type of value contained in the property
* @param container
* the entity where place the property representation
* @return True if property has been treated (according to its type)
* @throws XmpParsingException
* When element expected not found
* @throws XmpUnexpectedTypeException
* When DOM Element type found unexpected
* @throws XmpUnknownPropertyTypeException
* Value Type property is incorrect or the basic value type
* can't be treat at the moment
* @throws XmpPropertyFormatException
* Unexpected type found (IllegalArgumentException)
* @throws XMLStreamException
* When error during reading the rest of xmp stream
*/
private boolean createAndAddPropertyToContainer(XMPMetadata metadata,
String type, ComplexPropertyContainer container)
throws XmpParsingException, XmpUnexpectedTypeException,
XmpUnknownPropertyTypeException, XmpPropertyFormatException,
XMLStreamException {
if (type.equals("Text")) {
parseXmpSimpleProperty(metadata, reader.get().getName(),
XmpPropertyType.Text, container);
} else if (type.equals("Integer")) {
parseXmpSimpleProperty(metadata, reader.get().getName(),
XmpPropertyType.Integer, container);
} else if (type.equals("Boolean")) {
parseXmpSimpleProperty(metadata, reader.get().getName(),
XmpPropertyType.Boolean, container);
} else if (type.equals("Real")) {
parseXmpSimpleProperty(metadata, reader.get().getName(),
XmpPropertyType.Real, container);
} else if (type.equals("Date")) {
parseXmpSimpleProperty(metadata, reader.get().getName(),
XmpPropertyType.Date, container);
} else if (type.equals("URI")) {
parseXmpSimpleProperty(metadata, reader.get().getName(),
XmpPropertyType.Text, container);
} else if (type.equals("URL")) {
parseXmpSimpleProperty(metadata, reader.get().getName(),
XmpPropertyType.Text, container);
} else if (type.equals("bag Text")) {
parseBagProperty(metadata, reader.get().getName(),
XmpPropertyType.Text, container);
} else if (type.equals("bag ProperName")) {
parseBagProperty(metadata, reader.get().getName(),
XmpPropertyType.Text, container);
} else if (type.equals("bag Job")) {
parseComplexBagProperty(metadata, reader.get().getName(), new JobParser(this), container);
} else if (type.equals("bag Xpath")) {
parseBagProperty(metadata, reader.get().getName(),
XmpPropertyType.Text, container);
} else if (type.equals("seq Text")) {
parseSeqProperty(metadata, reader.get().getName(),
XmpPropertyType.Text, container);
} else if (type.equals("seq Field")) {
parseSeqProperty(metadata, reader.get().getName(),
XmpPropertyType.Text, container);
} else if (type.equals("seq Date")) {
parseSeqProperty(metadata, reader.get().getName(),
XmpPropertyType.Date, container);
} else if (type.equals("Lang Alt")) {
parseAltProperty(metadata, reader.get().getName(),
XmpPropertyType.Text, container);
} else {
return false;
}
return true;
}
/**
* Parse a specific field
*
* @param metadata
* Metadata to attach new elements
* @param propertyName
* the full qualified name of this property
* @param schema
* The schema where save this property
* @throws XmpUnexpectedTypeException
* When DOM Element type found unexpected
* @throws XmpParsingException
* When element expected not found
* @throws XMLStreamException
* When error during reading the rest of xmp stream
* @throws XmpUnknownPropertyTypeException
* Value Type property is incorrect or the basic value type
* can't be treat at the moment
* @throws XmpPropertyFormatException
* Unexpected type found (IllegalArgumentException)
*/
protected void parseFieldProperty(XMPMetadata metadata, QName propertyName,
XMPSchema schema) throws XmpUnexpectedTypeException,
XmpPropertyFormatException, XmpParsingException,
XMLStreamException, XmpUnknownPropertyTypeException {
ComplexPropertyContainer field = new ComplexPropertyContainer(metadata,
propertyName.getPrefix(), propertyName.getLocalPart());
schema.addProperty(field);
field.setAttribute(new Attribute(null, "rdf", "parseType", "Resource"));
String type;
int elmtType = reader.get().nextTag();
while ((elmtType != XMLStreamReader.END_ELEMENT)
&& !reader.get().getName().getLocalPart().equals(SEQ_NAME)) {
type = getPropertyDeclarationInNamespaces(schema, reader.get()
.getName());
if (!createAndAddPropertyToContainer(metadata, type, field)) {
if (type.equals("Field")) {
String stype = getPropertyDeclarationInNamespaces(schema,
reader.get().getName());
createAndAddPropertyToContainer(metadata, stype, field);
} else {
throw new XmpUnknownPropertyTypeException("Unknown type : "
+ type);
}
}
elmtType = reader.get().nextTag();
}
expectCurrentLocalName(propertyName.getLocalPart());
// expectNextSpecificTag(XMLStreamReader.END_ELEMENT,
// propertyName.getLocalPart(), "Expected end of field declaration");
}
/**
* analyze one property in the stream, retrieve its type according to the
* schema information and call its object representation building
*
* @param schema
* The schema where find information
* @param metadata
* Metadata to attach new elements
* @throws XmpParsingException
* When element expected not found
* @throws XMPUnexpectedTypeException
* When DOM Element type found unexpected
* @throws XMLStreamException
* When error during reading the rest of xmp stream
* @throws XmpUnknownPropertyTypeException
* Value Type property is incorrect or the basic value type
* can't be treat at the moment
* @throws XmpPropertyFormatException
* Unexpected type found (IllegalArgumentException)
*/
protected void parseProperty(XMPSchema schema, XMPMetadata metadata)
throws XmpParsingException, XmpPropertyFormatException,
XmpUnexpectedTypeException, XMLStreamException,
XmpUnknownPropertyTypeException {
QName propertyName = reader.get().getName();
nsMap.resetComplexBasicTypesDeclarationInPropertyLevel();
int cptNs = reader.get().getNamespaceCount();
for (int i = 0; i < cptNs; i++) {
if (nsMap.isComplexBasicTypes(reader.get().getNamespaceURI(i))) {
nsMap.setComplexBasicTypesDeclarationForLevelSchema(reader
.get().getNamespaceURI(i), reader.get()
.getNamespacePrefix(i));
}
}
String type = getPropertyDeclarationInNamespaces(schema, propertyName);
if (type.equals("Unmanaged")) {
// do not parse the property, no validation, no reserialization
boolean cont = true;
while (cont) {
int t = reader.get().next();
if (t==XMLStreamReader.END_ELEMENT) {
if (propertyName.equals(reader.get().getName())) {
cont = false;
}
}
}
} else if (type.equals("Text")) {
parseXmpSimpleProperty(metadata, propertyName,
XmpPropertyType.Text, schema.getContent());
} else if (type.equals("Integer")) {
parseXmpSimpleProperty(metadata, propertyName,
XmpPropertyType.Integer, schema.getContent());
} else if (type.equals("Boolean")) {
parseXmpSimpleProperty(metadata, propertyName,
XmpPropertyType.Boolean, schema.getContent());
} else if (type.equals("Real")) {
parseXmpSimpleProperty(metadata, propertyName,
XmpPropertyType.Real, schema.getContent());
} else if (type.equals("Date")) {
parseXmpSimpleProperty(metadata, propertyName,
XmpPropertyType.Date, schema.getContent());
} else if (type.equals("URI")) {
parseXmpSimpleProperty(metadata, propertyName,
XmpPropertyType.Text, schema.getContent());
} else if (type.equals("URL")) {
parseXmpSimpleProperty(metadata, propertyName,
XmpPropertyType.Text, schema.getContent());
} else if (type.equals("bag Text")) {
parseBagProperty(metadata, propertyName, XmpPropertyType.Text,
schema.getContent());
} else if (type.equals("bag ProperName")) {
parseBagProperty(metadata, propertyName, XmpPropertyType.Text,
schema.getContent());
} else if (type.equals("bag Job")) {
parseComplexBagProperty(metadata, propertyName, new JobParser(this), schema.getContent());
} else if (type.equals("bag Xpath")) {
parseBagProperty(metadata, propertyName, XmpPropertyType.Text,
schema.getContent());
} else if (type.equals("seq Text")) {
parseSeqProperty(metadata, propertyName, XmpPropertyType.Text,
schema.getContent());
} else if (type.equals("seq Date")) {
parseSeqProperty(metadata, propertyName, XmpPropertyType.Date,
schema.getContent());
} else if (type.equals("Lang Alt")) {
parseAltProperty(metadata, propertyName, XmpPropertyType.Text,
schema.getContent());
} else if (type.equals("Field")) {
parseFieldProperty(metadata, propertyName, schema);
} else if (type.equals("Thumbnail")) {
parseThumbnailProperty(metadata, propertyName, schema.getContent());
} else if (type.equals("Alt Thumbnail")) {
parseAltThumbnailProperty(metadata, propertyName, schema
.getContent());
} else {
throw new XmpUnknownPropertyTypeException("Unknown type : " + type);
}
}
/**
* Treat Alternative Thumbnails property
*
* @param metadata
* Metadata to attach new elements
* @param altName
* name of thumbnails alternative property
* @param container
* the container where record this representation
* @throws XmpUnexpectedTypeException
* When DOM Element type found unexpected
* @throws XmpParsingException
* When element expected not found
* @throws XMLStreamException
* When error during reading the rest of xmp stream
* @throws XmpUnknownPropertyTypeException
* Value Type property is incorrect or the basic value type
* can't be treat at the moment
* @throws XmpPropertyFormatException
* Unexpected type found (IllegalArgumentException)
*/
private void parseAltThumbnailProperty(XMPMetadata metadata, QName altName,
ComplexPropertyContainer container)
throws XmpUnexpectedTypeException, XmpParsingException,
XMLStreamException, XmpUnknownPropertyTypeException,
XmpPropertyFormatException {
ComplexProperty alt = new ComplexProperty(metadata,
altName.getPrefix(), altName.getLocalPart(),
ComplexProperty.ALTERNATIVE_ARRAY);
container.addProperty(alt);
// <rdf:Alt>
expectNextSpecificTag(XMLStreamReader.START_ELEMENT, ALT_NAME,
"Expected Alt Declaration");
int elmtType = reader.get().nextTag();
while (!((elmtType == XMLStreamReader.END_ELEMENT) && reader.get()
.getName().getLocalPart().equals(ALT_NAME))) {
parseThumbnailProperty(metadata, reader.get().getName(), alt
.getContainer());
elmtType = reader.get().nextTag();
}
// <dc:description><rdf:Alt><rdf:li>sujet</rdf:li></rdf:Alt></dc:description>
expectNextSpecificTag(XMLStreamReader.END_ELEMENT, altName
.getLocalPart(), "Expected end of alt property");
}
/**
* * Treat a thumbnail property
*
* @param metadata
* Metadata to attach new elements
* @param altName
* name of thumbnail property
* @param container
* The container where save property representation
* @throws XmpUnexpectedTypeException
* When DOM Element type found unexpected
* @throws XmpParsingException
* When element expected not found
* @throws XMLStreamException
* When error during reading the rest of xmp stream
* @throws XmpUnknownPropertyTypeException
* Value Type property is incorrect or the basic value type
* can't be treat at the moment
* @throws XmpPropertyFormatException
* Unexpected type found (IllegalArgumentException)
*/
private void parseThumbnailProperty(XMPMetadata metadata, QName altName,
ComplexPropertyContainer container)
throws XmpUnexpectedTypeException, XmpParsingException,
XMLStreamException, XmpUnknownPropertyTypeException,
XmpPropertyFormatException {
expectCurrentLocalName("li");
ThumbnailType thumbnail = new ThumbnailType(metadata, altName
.getPrefix(), altName.getLocalPart());
int elmtType = reader.get().nextTag();
QName eltName;
String eltContent;
while (!((elmtType == XMLStreamReader.END_ELEMENT) && reader.get()
.getName().getLocalPart().equals("li"))) {
eltName = reader.get().getName();
eltContent = reader.get().getElementText();
if (eltName.getLocalPart().equals("height")) {
thumbnail.setHeight(eltName.getPrefix(),
eltName.getLocalPart(), Integer.valueOf(eltContent));
} else if (eltName.getLocalPart().equals("width")) {
thumbnail.setWidth(eltName.getPrefix(), eltName.getLocalPart(),
Integer.valueOf(eltContent));
} else if (eltName.getLocalPart().equals("image")) {
thumbnail.setImg(eltName.getPrefix(), eltName.getLocalPart(),
eltContent);
} else if (eltName.getLocalPart().equals("format")) {
thumbnail.setFormat(eltName.getPrefix(),
eltName.getLocalPart(), eltContent);
} else {
throw new XmpParsingException(
"Unknown property name for a thumbnail element : "
+ eltName.getLocalPart());
}
elmtType = reader.get().nextTag();
}
container.addProperty(thumbnail);
}
}