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 ...]