You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2012/03/17 11:41:16 UTC
svn commit: r1301914 [2/3] - in /pdfbox/trunk:
preflight/src/main/java/org/apache/padaf/preflight/contentstream/
preflight/src/main/java/org/apache/padaf/preflight/font/
preflight/src/main/java/org/apache/padaf/preflight/utils/
xmpbox/src/main/java/org...
Modified: pdfbox/trunk/xmpbox/src/main/java/org/apache/padaf/xmpbox/parser/XMPDocumentBuilder.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/xmpbox/src/main/java/org/apache/padaf/xmpbox/parser/XMPDocumentBuilder.java?rev=1301914&r1=1301913&r2=1301914&view=diff
==============================================================================
--- pdfbox/trunk/xmpbox/src/main/java/org/apache/padaf/xmpbox/parser/XMPDocumentBuilder.java (original)
+++ pdfbox/trunk/xmpbox/src/main/java/org/apache/padaf/xmpbox/parser/XMPDocumentBuilder.java Sat Mar 17 10:41:15 2012
@@ -64,1511 +64,1534 @@ import org.apache.padaf.xmpbox.type.Thum
*
*/
public class XMPDocumentBuilder {
-
- protected NSMapping nsMap;
- protected ThreadLocal<XMLStreamReader> reader = new ThreadLocal<XMLStreamReader>();
+ 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.copyLarge(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);
+ }
+
+
+
- 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.copyLarge(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();
- 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");
- }
[... 850 lines stripped ...]