You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by gb...@apache.org on 2011/12/07 20:14:06 UTC

svn commit: r1211604 [3/4] - in /pdfbox/trunk/xmpbox/src/main/java/org/apache/padaf/xmpbox: ./ parser/ schema/ type/

Modified: pdfbox/trunk/xmpbox/src/main/java/org/apache/padaf/xmpbox/schema/XMPSchema.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/xmpbox/src/main/java/org/apache/padaf/xmpbox/schema/XMPSchema.java?rev=1211604&r1=1211603&r2=1211604&view=diff
==============================================================================
--- pdfbox/trunk/xmpbox/src/main/java/org/apache/padaf/xmpbox/schema/XMPSchema.java (original)
+++ pdfbox/trunk/xmpbox/src/main/java/org/apache/padaf/xmpbox/schema/XMPSchema.java Wed Dec  7 19:14:05 2011
@@ -52,1468 +52,1466 @@ import org.w3c.dom.Element;
  * 
  */
 public class XMPSchema implements Elementable {
-	/**
-	 * The standard xmlns namespace.
-	 */
-	public static final String NS_NAMESPACE = "http://www.w3.org/2000/xmlns/";
-
-	public static final String RDFABOUT = "rdf:about";
-
-	protected String localPrefix, localNSUri;
-	protected String localPrefixSep;
-	protected XMPMetadata metadata;
-	protected ComplexPropertyContainer content;
-
-	/**
-	 * Create a new blank schema that can be populated.
-	 * 
-	 * @param metadata
-	 *            The parent XMP metadata that this schema will be part of.
-	 * @param namespaceName
-	 *            The name of the namespace, ie pdf,dc,...
-	 * @param namespaceURI
-	 *            The URI of the namespace, ie "http://ns.adobe.com/pdf/1.3/"
-	 * 
-	 */
-	public XMPSchema(XMPMetadata metadata, String namespaceName, String namespaceURI) {
-		this.metadata = metadata;
-		content = new ComplexPropertyContainer(metadata,
-				"http://www.w3.org/1999/02/22-rdf-syntax-ns#", "rdf",
-				"Description");
-
-		localPrefix = namespaceName;
-		localPrefixSep = localPrefix + ":";
-		localNSUri = namespaceURI;
-		content.setAttribute(new Attribute(NS_NAMESPACE, "xmlns",
-				namespaceName, namespaceURI));
-
-	}
-
-	/**
-	 * Get the schema prefix
-	 * 
-	 * @return Prefix fixed for the schema
-	 */
-	public String getPrefix() {
-		return localPrefix;
-
-	}
-
-	/**
-	 * Get the namespace URI of this schema
-	 * 
-	 * @return the namespace URI of this schema
-	 */
-	public String getNamespaceValue() {
-		return localNSUri;
-	}
-
-	/**
-	 * Retrieve a generic simple type property
-	 * 
-	 * @param qualifiedName
-	 *            Full qualified name of proeprty wanted
-	 * @return The generic simple type property according to its qualified Name
-	 */
-	public AbstractField getAbstractProperty(String qualifiedName) {
-		Iterator<AbstractField> it = content.getAllProperties().iterator();
-		AbstractField tmp;
-		while (it.hasNext()) {
-			tmp = it.next();
-			if (tmp.getQualifiedName().equals(qualifiedName)) {
-				return tmp;
-			}
-		}
-		return null;
-
-	}
-
-	/**
-	 * Get the RDF about attribute
-	 * 
-	 * @return The RDF 'about' attribute.
-	 */
-	public Attribute getAboutAttribute() {
-		return content.getAttribute(RDFABOUT);
-	}
-
-	/**
-	 * Get the RDF about value.
-	 * 
-	 * @return The RDF 'about' value.
-	 */
-	public String getAboutValue() {
-		Attribute prop = content.getAttribute(RDFABOUT);
-		if (prop != null) {
-			return prop.getValue();
-		}
-		return null;
-	}
-
-	/**
-	 * Set the RDF 'about' attribute
-	 * 
-	 * @param about
-	 *            the well-formed attribute
-	 * @throws BadFieldValueException
-	 *             Bad Attribute name (not corresponding to about attribute)
-	 */
-	public void setAbout(Attribute about) throws BadFieldValueException {
-		if (about.getQualifiedName().equals(RDFABOUT)
-				|| about.getQualifiedName().equals("about")) {
-			content.setAttribute(about);
-		} else {
-			throw new BadFieldValueException(
-					"Attribute 'about' must be named 'rdf:about' or 'about'");
-		}
-	}
-
-	/**
-	 * Set the RDF 'about' attribute. Passing in null will clear this attribute.
-	 * 
-	 * @param about
-	 *            The new RFD about value.
-	 */
-	public void setAboutAsSimple(String about) {
-		if (about == null) {
-			content.removeAttribute(RDFABOUT);
-		} else {
-			content.setAttribute(new Attribute(null, "rdf", "about", about));
-
-		}
-	}
-
-	/**
-	 * Set a simple specified type property on the schema.
-	 * 
-	 * @param type
-	 *            the property type
-	 * @param qualifiedName
-	 *            the qualified name to specify for the new property
-	 * @param propertyValue
-	 *            The value (must be an object understandable by specified type)
-	 */
-	@SuppressWarnings("unchecked")
-	private void setSpecifiedSimpleTypeProperty(
-			Class<? extends AbstractSimpleProperty> type, String qualifiedName,
-			Object propertyValue) {
-		String[] splittedQualifiedName = qualifiedName.split(":");
-
-		Class[] propertyArgsClass = new Class[] { XMPMetadata.class,
-				String.class, String.class, Object.class };
-		Object[] propertyArgs = new Object[] { metadata,
-				splittedQualifiedName[0], splittedQualifiedName[1],
-				propertyValue };
-		Constructor<? extends AbstractSimpleProperty> propertyConstructor;
-
-		AbstractSimpleProperty specifiedTypeProperty;
-		if (propertyValue == null) {
-			// Search in properties to erase
-			Iterator<AbstractField> it = content.getAllProperties().iterator();
-			AbstractField tmp;
-			while (it.hasNext()) {
-				tmp = it.next();
-				if (tmp.getQualifiedName().equals(qualifiedName)) {
-					content.removeProperty(tmp);
-					return;
-				}
-			}
-		} else {
-			try {
-				propertyConstructor = type.getConstructor(propertyArgsClass);
-				specifiedTypeProperty = (AbstractSimpleProperty) propertyConstructor
-						.newInstance(propertyArgs);
-			} catch (Exception e) {
-				throw new IllegalArgumentException(
-						"Failed to create property with the specified type given in parameters");
-			}
-			// attribute placement for simple property has been removed
-			// Search in properties to erase
-			Iterator<AbstractField> it = content.getAllProperties().iterator();
-			AbstractField tmp;
-			while (it.hasNext()) {
-				tmp = it.next();
-				if (tmp.getQualifiedName().equals(qualifiedName)) {
-					content.removeProperty(tmp);
-					content.addProperty(specifiedTypeProperty);
-					return;
-				}
-			}
-			content.addProperty(specifiedTypeProperty);
-		}
-	}
-
-	/**
-	 * Add a SimpleProperty to this schema
-	 * 
-	 * @param prop
-	 *            The Property to add
-	 */
-	private void setSpecifiedSimpleTypeProperty(AbstractSimpleProperty prop) {
-		// attribute placement for simple property has been removed
-		// Search in properties to erase
-		Iterator<AbstractField> it = content.getAllProperties().iterator();
-		AbstractField tmp;
-		while (it.hasNext()) {
-			tmp = it.next();
-			if (tmp.getQualifiedName().equals(prop.getQualifiedName())) {
-				content.removeProperty(tmp);
-				content.addProperty(prop);
-				return;
-			}
-		}
-		content.addProperty(prop);
-	}
-
-	/**
-	 * Set TextType property
-	 * 
-	 * @param prop
-	 *            The text property to add
-	 */
-	public void setTextProperty(TextType prop) {
-		setSpecifiedSimpleTypeProperty(prop);
-	}
-
-	/**
-	 * Set a simple text property on the schema.
-	 * 
-	 * @param qualifiedName
-	 *            The name of the property, it must contain the namespace
-	 *            prefix, ie "pdf:Keywords"
-	 * @param propertyValue
-	 *            The value for the property, can be any string. Passing null
-	 *            will remove the property.
-	 */
-	public void setTextPropertyValue(String qualifiedName, String propertyValue) {
-		setSpecifiedSimpleTypeProperty(TextType.class, qualifiedName,
-				propertyValue);
-	}
-
-	/**
-	 * Set a simple text property on the schema, using the current prefix.
-	 * 
-	 * @param simpleName
-	 *            the name of the property without prefix
-	 * @param propertyValue
-	 *            The value for the property, can be any string. Passing null
-	 *            will remove the property.
-	 */
-	public void setTextPropertyValueAsSimple(String simpleName,
-			String propertyValue) {
-		this.setTextPropertyValue(localPrefixSep + simpleName, propertyValue);
-	}
-
-	/**
-	 * Get a TextProperty Type from its name
-	 * 
-	 * @param qualifiedName
-	 *            The full qualified name of the property wanted
-	 * @return The Text Type property wanted
-	 */
-	public TextType getTextProperty(String qualifiedName) {
-		AbstractField prop = getAbstractProperty(qualifiedName);
-		if (prop != null) {
-			if (prop instanceof TextType) {
-				return (TextType) prop;
-			} else {
-				throw new IllegalArgumentException(
-						"Property asked is not a Text Property");
-			}
-		}
-		return null;
-	}
-
-	/**
-	 * Get a simple text property value on the schema, using the current prefix.
-	 * 
-	 * @param simpleName
-	 *            The local name of the property wanted
-	 * @return The value of the text property or the null if there is no value.
-	 * 
-	 */
-	public String getTextPropertyValueAsSimple(String simpleName) {
-		return this.getTextPropertyValue(localPrefixSep + simpleName);
-	}
-
-	/**
-	 * Get the value of a simple text property.
-	 * 
-	 * @param qualifiedName
-	 *            The name of the property to get, it must include the namespace
-	 *            prefix. ie "pdf:Keywords".
-	 * 
-	 * @return The value of the text property or the null if there is no value.
-	 * 
-	 */
-	public String getTextPropertyValue(String qualifiedName) {
-		AbstractField prop = getAbstractProperty(qualifiedName);
-		if (prop != null) {
-			if (prop instanceof TextType) {
-				return ((TextType) prop).getStringValue();
-			} else {
-				throw new IllegalArgumentException(
-						"Property asked is not a Text Property");
-			}
-		}
-		return null;
-	}
-
-	/**
-	 * Get the Date property with its name
-	 * 
-	 * @param qualifiedName
-	 *            The name of the property to get, it must include the namespace
-	 *            prefix. ie "pdf:Keywords".
-	 * @return Date Type property
-	 * 
-	 */
-	public DateType getDateProperty(String qualifiedName) {
-		AbstractField prop = getAbstractProperty(qualifiedName);
-		if (prop != null) {
-			if (prop instanceof DateType) {
-				return (DateType) prop;
-			} else {
-				throw new IllegalArgumentException(
-						"Property asked is not a Date Property");
-			}
-
-		}
-		return null;
-	}
-
-	/**
-	 * Get a simple date property value on the schema, using the current prefix.
-	 * 
-	 * @param simpleName
-	 *            the local name of the property to get
-	 * @return The value of the property as a calendar.
-	 * 
-	 */
-	public Calendar getDatePropertyValueAsSimple(String simpleName) {
-		return this.getDatePropertyValue(localPrefixSep + simpleName);
-	}
-
-	/**
-	 * Get the value of the property as a date.
-	 * 
-	 * @param qualifiedName
-	 *            The fully qualified property name for the date.
-	 * 
-	 * @return The value of the property as a date.
-	 * 
-	 */
-	public Calendar getDatePropertyValue(String qualifiedName) {
-		AbstractField prop = getAbstractProperty(qualifiedName);
-		if (prop != null) {
-			if (prop instanceof DateType) {
-				return ((DateType) prop).getValue();
-			} else {
-				throw new IllegalArgumentException(
-						"Property asked is not a Date Property");
-			}
-
-		}
-		return null;
-	}
-
-	/**
-	 * Set a new DateProperty
-	 * 
-	 * @param date
-	 *            The DateType Property
-	 */
-	public void setDateProperty(DateType date) {
-		setSpecifiedSimpleTypeProperty(date);
-	}
-
-	/**
-	 * Set a simple Date property on the schema, using the current prefix.
-	 * 
-	 * @param simpleName
-	 *            the name of the property without prefix
-	 * @param date
-	 *            The calendar value for the property, can be any string.
-	 *            Passing null will remove the property.
-	 */
-	public void setDatePropertyValueAsSimple(String simpleName, Calendar date) {
-		this.setDatePropertyValue(localPrefixSep + simpleName, date);
-	}
-
-	/**
-	 * Set the value of the property as a date.
-	 * 
-	 * @param qualifiedName
-	 *            The fully qualified property name for the date.
-	 * @param date
-	 *            The date to set, or null to clear.
-	 */
-	public void setDatePropertyValue(String qualifiedName, Calendar date) {
-		setSpecifiedSimpleTypeProperty(DateType.class, qualifiedName, date);
-
-	}
-
-	/**
-	 * Get a BooleanType property with its name
-	 * 
-	 * @param qualifiedName
-	 *            the full qualified name of property wanted
-	 * @return boolean Type property
-	 */
-	public BooleanType getBooleanProperty(String qualifiedName) {
-		AbstractField prop = getAbstractProperty(qualifiedName);
-		if (prop != null) {
-			if (prop instanceof BooleanType) {
-				return (BooleanType) prop;
-			} else {
-				throw new IllegalArgumentException(
-						"Property asked is not a Boolean Property");
-			}
-		}
-		return null;
-	}
-
-	/**
-	 * Get a simple boolean property value on the schema, using the current
-	 * prefix.
-	 * 
-	 * @param simpleName
-	 *            the local name of property wanted
-	 * @return The value of the property as a boolean.
-	 */
-	public Boolean getBooleanPropertyValueAsSimple(String simpleName) {
-		return this.getBooleanPropertyValue(localPrefixSep + simpleName);
-	}
-
-	/**
-	 * Get the value of the property as a boolean.
-	 * 
-	 * @param qualifiedName
-	 *            The fully qualified property name for the boolean.
-	 * 
-	 * @return The value of the property as a boolean. Return null if property
-	 *         not exist
-	 */
-	public Boolean getBooleanPropertyValue(String qualifiedName) {
-		AbstractField prop = getAbstractProperty(qualifiedName);
-		if (prop != null) {
-			if (prop instanceof BooleanType) {
-				return ((BooleanType) prop).getValue();
-			} else {
-				throw new IllegalArgumentException(
-						"Property asked is not a Boolean Property");
-			}
-		}
-		// Return null if property not exist. This method give the property
-		// value so treat this return in this way.
-		// If you want to use this value like a condition, you must check this
-		// return before
-		return null;
-	}
-
-	/**
-	 * Set a BooleanType property
-	 * 
-	 * @param bool
-	 *            the booleanType property
-	 */
-	public void setBooleanProperty(BooleanType bool) {
-		setSpecifiedSimpleTypeProperty(bool);
-	}
-
-	/**
-	 * Set a simple Boolean property on the schema, using the current prefix.
-	 * 
-	 * @param simpleName
-	 *            the name of the property without prefix
-	 * @param bool
-	 *            The value for the property, can be any string. Passing null
-	 *            will remove the property.
-	 */
-	public void setBooleanPropertyValueAsSimple(String simpleName, Boolean bool) {
-		this.setBooleanPropertyValue(localPrefixSep + simpleName, bool);
-	}
-
-	/**
-	 * Set the value of the property as a boolean.
-	 * 
-	 * @param qualifiedName
-	 *            The fully qualified property name for the boolean.
-	 * @param bool
-	 *            The boolean to set, or null to clear.
-	 */
-	public void setBooleanPropertyValue(String qualifiedName, Boolean bool) {
-		setSpecifiedSimpleTypeProperty(BooleanType.class, qualifiedName, bool);
-	}
-
-	/**
-	 * Get the Integer property with its name
-	 * 
-	 * @param qualifiedName
-	 *            the full qualified name of property wanted
-	 * @return Integer Type property
-	 */
-	public IntegerType getIntegerProperty(String qualifiedName) {
-		AbstractField prop = getAbstractProperty(qualifiedName);
-		if (prop != null) {
-			if (prop instanceof IntegerType) {
-				return ((IntegerType) prop);
-			} else {
-				throw new IllegalArgumentException(
-						"Property asked is not an Integer Property");
-			}
-		}
-		return null;
-	}
-
-	/**
-	 * Get a simple integer property value on the schema, using the current
-	 * prefix.
-	 * 
-	 * @param simpleName
-	 *            the local name of property wanted
-	 * @return The value of the property as an integer.
-	 */
-	public Integer getIntegerPropertyValueAsSimple(String simpleName) {
-		return this.getIntegerPropertyValue(localPrefixSep + simpleName);
-	}
-
-	/**
-	 * Get the value of the property as an integer.
-	 * 
-	 * @param qualifiedName
-	 *            The fully qualified property name for the integer.
-	 * 
-	 * @return The value of the property as an integer.
-	 */
-	public Integer getIntegerPropertyValue(String qualifiedName) {
-		AbstractField prop = getAbstractProperty(qualifiedName);
-		if (prop != null) {
-			if (prop instanceof IntegerType) {
-				return ((IntegerType) prop).getValue();
-			} else {
-				throw new IllegalArgumentException(
-						"Property asked is not an Integer Property");
-			}
-		}
-		return null;
-	}
-
-	/**
-	 * Add an integerProperty
-	 * 
-	 * @param prop
-	 *            The Integer Type property
-	 */
-	public void setIntegerProperty(IntegerType prop) {
-		setSpecifiedSimpleTypeProperty(prop);
-	}
-
-	/**
-	 * Set a simple Integer property on the schema, using the current prefix.
-	 * 
-	 * @param simpleName
-	 *            the name of the property without prefix
-	 * @param intValue
-	 *            The value for the property, can be any string. Passing null
-	 *            will remove the property.
-	 */
-	public void setIntegerPropertyValueAsSimple(String simpleName,
-			Integer intValue) {
-		this.setIntegerPropertyValue(localPrefixSep + simpleName, intValue);
-	}
-
-	/**
-	 * Set the value of the property as an integer.
-	 * 
-	 * @param qualifiedName
-	 *            The fully qualified property name for the integer.
-	 * @param intValue
-	 *            The int to set, or null to clear.
-	 */
-	public void setIntegerPropertyValue(String qualifiedName, Integer intValue) {
-		setSpecifiedSimpleTypeProperty(IntegerType.class, qualifiedName,
-				intValue);
-	}
-
-	/**
-	 * Generic array property removing
-	 * 
-	 * @param qualifiedArrayName
-	 *            the full qualified name of property wanted
-	 * @param fieldValue
-	 *            the field value
-	 */
-	private void removeArrayValue(String qualifiedArrayName, String fieldValue) {
-		ComplexProperty array = (ComplexProperty) getAbstractProperty(qualifiedArrayName);
-		if (array != null) {
-			ArrayList<AbstractField> toDelete = new ArrayList<AbstractField>();
-			Iterator<AbstractField> it = array.getContainer()
-					.getAllProperties().iterator();
-			AbstractSimpleProperty tmp;
-			while (it.hasNext()) {
-				tmp = (AbstractSimpleProperty) it.next();
-				if (tmp.getStringValue().equals(fieldValue)) {
-					toDelete.add(tmp);
-				}
-			}
-			Iterator<AbstractField> eraseProperties = toDelete.iterator();
-			while (eraseProperties.hasNext()) {
-				array.getContainer().removeProperty(eraseProperties.next());
-			}
-		}
-
-	}
-
-	/**
-	 * Remove all matching entries with the given value from the bag.
-	 * 
-	 * @param qualifiedBagName
-	 *            The name of the bag, it must include the namespace prefix. ie
-	 *            "pdf:Keywords".
-	 * @param bagValue
-	 *            The value to remove from the bagList.
-	 */
-	public void removeBagValue(String qualifiedBagName, String bagValue) {
-		removeArrayValue(qualifiedBagName, bagValue);
-	}
-
-	/**
-	 * add a bag value property on the schema, using the current prefix.
-	 * 
-	 * @param simpleName
-	 *            the local name of property
-	 * @param bagValue
-	 *            the string value to add
-	 */
-	public void addBagValueAsSimple(String simpleName, String bagValue) {
-		this.addBagValue(localPrefixSep + simpleName, bagValue);
-	}
-
-	/**
-	 * Add an entry to a bag property.
-	 * 
-	 * @param qualifiedBagName
-	 *            The name of the bag, it must include the namespace prefix. ie
-	 *            "pdf:Keywords".
-	 * @param bagValue
-	 *            The value to add to the bagList.
-	 */
-	public void addBagValue(String qualifiedBagName, String bagValue) {
-		String[] splittedQualifiedName = qualifiedBagName.split(":");
-		ComplexProperty bag = (ComplexProperty) getAbstractProperty(qualifiedBagName);
-		TextType li = new TextType(metadata, "rdf", "li", bagValue);
-		if (bag != null) {
-			bag.getContainer().addProperty(li);
-		} else {
-			ComplexProperty newBag = new ComplexProperty(metadata,
-					splittedQualifiedName[0], splittedQualifiedName[1],
-					ComplexProperty.UNORDERED_ARRAY);
-			newBag.getContainer().addProperty(li);
-			content.addProperty(newBag);
-		}
-	}
-
-	/**
-	 * Generic String List Builder for arrays contents
-	 * 
-	 * @param qualifiedArrayName
-	 *            the full qualified name of property concerned
-	 * @return String list which represents content of array property
-	 */
-	private List<String> getArrayListToString(String qualifiedArrayName) {
-		List<String> retval = null;
-		ComplexProperty array = (ComplexProperty) getAbstractProperty(qualifiedArrayName);
-		if (array != null) {
-			retval = new ArrayList<String>();
-			Iterator<AbstractField> it = array.getContainer()
-					.getAllProperties().iterator();
-			AbstractSimpleProperty tmp;
-			while (it.hasNext()) {
-				tmp = (AbstractSimpleProperty) it.next();
-				retval.add(tmp.getStringValue());
-			}
-			retval = Collections.unmodifiableList(retval);
-		}
-		return retval;
-	}
-
-	/**
-	 * Get all the values of the bag property, using the current prefix. This
-	 * will return a list of java.lang.String objects, this is a read-only list.
-	 * 
-	 * @param simpleName
-	 *            the local name of property concerned
-	 * 
-	 * 
-	 * @return All values of the bag property in a list.
-	 */
-	public List<String> getBagValueListAsSimple(String simpleName) {
-		return getBagValueList(localPrefixSep + simpleName);
-	}
-
-	/**
-	 * Get all the values of the bag property. This will return a list of
-	 * java.lang.String objects, this is a read-only list.
-	 * 
-	 * @param qualifiedBagName
-	 *            The name of the bag property to get, it must include the
-	 *            namespace prefix. ie "pdf:Keywords"
-	 * 
-	 * @return All values of the bag property in a list.
-	 */
-	public List<String> getBagValueList(String qualifiedBagName) {
-		return getArrayListToString(qualifiedBagName);
-	}
-
-	/**
-	 * Remove all matching values from a sequence property.
-	 * 
-	 * @param qualifiedSeqName
-	 *            The name of the sequence property. It must include the
-	 *            namespace prefix. ie "pdf:Keywords".
-	 * @param seqValue
-	 *            The value to remove from the list.
-	 */
-	public void removeSequenceValue(String qualifiedSeqName, String seqValue) {
-		removeArrayValue(qualifiedSeqName, seqValue);
-	}
-
-	/**
-	 * Generic method to remove a field from an array with an Elementable Object
-	 * 
-	 * @param qualifiedArrayName
-	 *            the full qualified name of the property concerned
-	 * @param fieldValue
-	 *            the elementable field value
-	 */
-	public void removeArrayValue(String qualifiedArrayName,
-			Elementable fieldValue) {
-		ComplexProperty array = (ComplexProperty) getAbstractProperty(qualifiedArrayName);
-		if (array != null) {
-			ArrayList<AbstractField> toDelete = new ArrayList<AbstractField>();
-			Iterator<AbstractField> it = array.getContainer()
-					.getAllProperties().iterator();
-			AbstractSimpleProperty tmp;
-			while (it.hasNext()) {
-				tmp = (AbstractSimpleProperty) it.next();
-				if (tmp.equals(fieldValue)) {
-					toDelete.add(tmp);
-				}
-			}
-			Iterator<AbstractField> eraseProperties = toDelete.iterator();
-			while (eraseProperties.hasNext()) {
-				array.getContainer().removeProperty(eraseProperties.next());
-			}
-		}
-	}
-
-	/**
-	 * Remove a value from a sequence property. This will remove all entries
-	 * from the list.
-	 * 
-	 * @param qualifiedSeqName
-	 *            The name of the sequence property. It must include the
-	 *            namespace prefix. ie "pdf:Keywords".
-	 * @param seqValue
-	 *            The value to remove from the list.
-	 */
-	public void removeSequenceValue(String qualifiedSeqName,
-			Elementable seqValue) {
-		removeArrayValue(qualifiedSeqName, seqValue);
-	}
-
-	/**
-	 * Add a new value to a sequence property.
-	 * 
-	 * @param qualifiedSeqName
-	 *            The name of the sequence property, it must include the
-	 *            namespace prefix. ie "pdf:Keywords"
-	 * @param seqValue
-	 *            The value to add to the sequence.
-	 */
-	public void addSequenceValue(String qualifiedSeqName, String seqValue) {
-		String[] splittedQualifiedName = qualifiedSeqName.split(":");
-		ComplexProperty seq = (ComplexProperty) getAbstractProperty(qualifiedSeqName);
-		TextType li = new TextType(metadata, "rdf", "li", seqValue);
-		if (seq != null) {
-			seq.getContainer().addProperty(li);
-		} else {
-			ComplexProperty newSeq = new ComplexProperty(metadata,
-					splittedQualifiedName[0], splittedQualifiedName[1],
-					ComplexProperty.ORDERED_ARRAY);
-			newSeq.getContainer().addProperty(li);
-			content.addProperty(newSeq);
-		}
-
-	}
-
-	/**
-	 * Add a new value to a bag property.
-	 * 
-	 * @param qualifiedSeqName
-	 *            The name of the sequence property, it must include the
-	 *            namespace prefix. ie "pdf:Keywords"
-	 * @param seqValue
-	 *            The value to add to the bag.
-	 */
-	public void addBagValue(String qualifiedSeqName, AbstractField seqValue) {
-
-		String[] splittedQualifiedName = qualifiedSeqName.split(":");
-		ComplexProperty bag = (ComplexProperty) getAbstractProperty(qualifiedSeqName);
-		if (bag != null) {
-			bag.getContainer().addProperty(seqValue);
-		} else {
-			ComplexProperty newBag = new ComplexProperty(metadata,
-					splittedQualifiedName[0], splittedQualifiedName[1],
-					ComplexProperty.UNORDERED_ARRAY);
-			newBag.getContainer().addProperty(seqValue);
-			content.addProperty(newBag);
-		}
-	}
-
-	/**
-	 * add a new value to a sequence property using the current prefix.
-	 * 
-	 * @param simpleName
-	 *            the local name of the property
-	 * @param seqValue
-	 *            the string value to add
-	 */
-	public void addSequenceValueAsSimple(String simpleName, String seqValue) {
-		this.addSequenceValue(localPrefixSep + simpleName, seqValue);
-	}
-
-	/**
-	 * Add a new value to a sequence property.
-	 * 
-	 * @param qualifiedSeqName
-	 *            The name of the sequence property, it must include the
-	 *            namespace prefix. ie "pdf:Keywords"
-	 * @param seqValue
-	 *            The value to add to the sequence.
-	 */
-	public void addSequenceValue(String qualifiedSeqName, AbstractField seqValue) {
-
-		String[] splittedQualifiedName = qualifiedSeqName.split(":");
-		ComplexProperty seq = (ComplexProperty) getAbstractProperty(qualifiedSeqName);
-		if (seq != null) {
-			seq.getContainer().addProperty(seqValue);
-		} else {
-			ComplexProperty newSeq = new ComplexProperty(metadata,
-					splittedQualifiedName[0], splittedQualifiedName[1],
-					ComplexProperty.ORDERED_ARRAY);
-			newSeq.getContainer().addProperty(seqValue);
-			content.addProperty(newSeq);
-		}
-	}
-
-	/**
-	 * Get all the values in a sequence property, using the current prefix.
-	 * 
-	 * @param simpleName
-	 *            the local name of the property
-	 * @return A read-only list of java.lang.String objects or null if the
-	 *         property does not exist.
-	 */
-	public List<String> getSequenceValueListAsSimple(String simpleName) {
-		return this.getSequenceValueList(localPrefixSep + simpleName);
-	}
-
-	/**
-	 * Get all the values in a sequence property.
-	 * 
-	 * @param qualifiedSeqName
-	 *            The name of the sequence property, it must include the
-	 *            namespace prefix. ie "pdf:Keywords".
-	 * 
-	 * @return A read-only list of java.lang.String objects or null if the
-	 *         property does not exist.
-	 */
-	public List<String> getSequenceValueList(String qualifiedSeqName) {
-		return getArrayListToString(qualifiedSeqName);
-	}
-
-	/**
-	 * Remove a date sequence value from the list.
-	 * 
-	 * @param qualifiedSeqName
-	 *            The name of the sequence property, it must include the
-	 *            namespace prefix. ie "pdf:Keywords"
-	 * @param date
-	 *            The date to remove from the sequence property.
-	 */
-	public void removeSequenceDateValue(String qualifiedSeqName, Calendar date) {
-		ComplexProperty seq = (ComplexProperty) getAbstractProperty(qualifiedSeqName);
-		if (seq != null) {
-			ArrayList<AbstractField> toDelete = new ArrayList<AbstractField>();
-			Iterator<AbstractField> it = seq.getContainer().getAllProperties()
-					.iterator();
-			AbstractField tmp;
-			while (it.hasNext()) {
-				tmp = it.next();
-				if (tmp instanceof DateType) {
-					if (((DateType) tmp).getValue().equals(date)) {
-						toDelete.add(tmp);
-
-					}
-				}
-			}
-			Iterator<AbstractField> eraseProperties = toDelete.iterator();
-			while (eraseProperties.hasNext()) {
-				seq.getContainer().removeProperty(eraseProperties.next());
-			}
-		}
-	}
-
-	/**
-	 * Add a date sequence value to the list using the current prefix
-	 * 
-	 * @param simpleName
-	 *            the local name of the property
-	 * @param date
-	 *            the value to add
-	 */
-	public void addSequenceDateValueAsSimple(String simpleName, Calendar date) {
-		addSequenceDateValue(localPrefixSep + simpleName, date);
-	}
-
-	/**
-	 * Add a date sequence value to the list.
-	 * 
-	 * @param qualifiedSeqName
-	 *            The name of the sequence property, it must include the
-	 *            namespace prefix. ie "pdf:Keywords"
-	 * @param date
-	 *            The date to add to the sequence property.
-	 */
-	public void addSequenceDateValue(String qualifiedSeqName, Calendar date) {
-		addSequenceValue(qualifiedSeqName, new DateType(metadata, "rdf", "li",
-				date));
-	}
-
-	/**
-	 * Get all the date values in a sequence property, using the current prefix.
-	 * 
-	 * @param simpleName
-	 *            the local name of property concerned
-	 * @return A read-only list of java.util.Calendar objects or null if the
-	 *         property does not exist.
-	 */
-	public List<Calendar> getSequenceDateValueListAsSimple(String simpleName) {
-		return this.getSequenceDateValueList(localPrefixSep + simpleName);
-	}
-
-	/**
-	 * Get all the date values in a sequence property.
-	 * 
-	 * @param qualifiedSeqName
-	 *            The name of the sequence property, it must include the
-	 *            namespace prefix. ie "pdf:Keywords".
-	 * 
-	 * @return A read-only list of java.util.Calendar objects or null if the
-	 *         property does not exist.
-	 * 
-	 */
-	public List<Calendar> getSequenceDateValueList(String qualifiedSeqName) {
-		List<Calendar> retval = null;
-		ComplexProperty seq = (ComplexProperty) getAbstractProperty(qualifiedSeqName);
-		if (seq != null) {
-			retval = new ArrayList<Calendar>();
-			Iterator<AbstractField> it = seq.getContainer().getAllProperties()
-					.iterator();
-			AbstractField tmp;
-			while (it.hasNext()) {
-				tmp = it.next();
-				if (tmp instanceof DateType) {
-					retval.add(((DateType) tmp).getValue());
-				}
-			}
-		}
-		return retval;
-	}
-
-	/**
-	 * Method used to place the 'x-default' value in first in Language
-	 * alternatives as said in xmp spec
-	 * 
-	 * @param alt
-	 *            The property to reorganize
-	 */
-	public void reorganizeAltOrder(ComplexPropertyContainer alt) {
-		Iterator<AbstractField> it = alt.getAllProperties().iterator();
-		AbstractField xdefault = null;
-		boolean xdefaultFound = false;
-		// If alternatives contains x-default in first value
-		if (it.hasNext()) {
-			if (it.next().getAttribute("xml:lang").getValue().equals(
-					"x-default")) {
-				return;
-			}
-		}
-		// Find the xdefault definition
-		while (it.hasNext() && !xdefaultFound) {
-			xdefault = it.next();
-			if (xdefault.getAttribute("xml:lang").getValue()
-					.equals("x-default")) {
-				alt.removeProperty(xdefault);
-				xdefaultFound = true;
-			}
-		}
-		if (xdefaultFound) {
-			it = alt.getAllProperties().iterator();
-			ArrayList<AbstractField> reordered = new ArrayList<AbstractField>();
-			ArrayList<AbstractField> toDelete = new ArrayList<AbstractField>();
-			reordered.add(xdefault);
-			AbstractField tmp;
-			while (it.hasNext()) {
-				tmp = it.next();
-				reordered.add(tmp);
-				toDelete.add(tmp);
-			}
-			Iterator<AbstractField> eraseProperties = toDelete.iterator();
-			while (eraseProperties.hasNext()) {
-				alt.removeProperty(eraseProperties.next());
-			}
-			it = reordered.iterator();
-			while (it.hasNext()) {
-				alt.addProperty(it.next());
-			}
-		}
-
-	}
-
-	/**
-	 * Set a multi-lingual property on the schema, using the current prefix.
-	 * 
-	 * @param simpleName
-	 *            the local name of the property
-	 * @param language
-	 *            the language concerned
-	 * @param value
-	 *            the value to set for the language specified
-	 */
-	public void setLanguagePropertyValueAsSimple(String simpleName,
-			String language, String value) {
-		this.setLanguagePropertyValue(localPrefixSep + simpleName, language,
-				value);
-	}
-
-	/**
-	 * Set the value of a multi-lingual property.
-	 * 
-	 * @param qualifiedName
-	 *            The name of the property, it must include the namespace
-	 *            prefix. ie "pdf:Keywords"
-	 * @param language
-	 *            The language code of the value. If null then "x-default" is
-	 *            assumed.
-	 * @param value
-	 *            The value of the property in the specified language.
-	 */
-	public void setLanguagePropertyValue(String qualifiedName, String language,
-			String value) {
-		AbstractField property = getAbstractProperty(qualifiedName);
-		ComplexProperty prop;
-		if (property != null) {
-			// Analyzing content of property
-			if (property instanceof ComplexProperty) {
-				prop = (ComplexProperty) property;
-				Iterator<AbstractField> itCplx = prop.getContainer()
-						.getAllProperties().iterator();
-				// try to find the same lang definition
-				AbstractField tmp;
-				// Try to find a definition
-				while (itCplx.hasNext()) {
-					tmp = itCplx.next();
-					// System.err.println(tmp.getAttribute("xml:lang").getStringValue());
-					if (tmp.getAttribute("xml:lang").getValue()
-							.equals(language)) {
-						// the same language has been found
-						if (value == null) {
-							// if value null, erase this definition
-							prop.getContainer().removeProperty(tmp);
-						} else {
-							prop.getContainer().removeProperty(tmp);
-							TextType langValue;
-							langValue = new TextType(metadata, "rdf", "li",
-									value);
-
-							langValue.setAttribute(new Attribute(null, "xml",
-									"lang", language));
-							prop.getContainer().addProperty(langValue);
-						}
-						reorganizeAltOrder(prop.getContainer());
-						return;
-					}
-				}
-				// if no definition found, we add a new one
-				TextType langValue;
-				langValue = new TextType(metadata, "rdf", "li", value);
-				langValue.setAttribute(new Attribute(null, "xml", "lang",
-						language));
-				prop.getContainer().addProperty(langValue);
-				reorganizeAltOrder(prop.getContainer());
-			}
-		} else {
-			String[] splittedQualifiedName = qualifiedName.split(":");
-			prop = new ComplexProperty(metadata, splittedQualifiedName[0],
-					splittedQualifiedName[1], ComplexProperty.ALTERNATIVE_ARRAY);
-			TextType langValue;
-			langValue = new TextType(metadata, "rdf", "li", value);
-			langValue
-					.setAttribute(new Attribute(null, "xml", "lang", language));
-			prop.getContainer().addProperty(langValue);
-			content.addProperty(prop);
-		}
-	}
-
-	/**
-	 * Get the value of a multi-lingual property, using the current prefix.
-	 * 
-	 * @param simpleName
-	 *            the local name of the property
-	 * @param language
-	 *            The language code of the value. If null then "x-default" is
-	 *            assumed.
-	 * 
-	 * @return The value of the language property.
-	 */
-	public String getLanguagePropertyValueAsSimple(String simpleName,
-			String language) {
-		return this.getLanguagePropertyValue(localPrefixSep + simpleName,
-				language);
-	}
-
-	/**
-	 * Get the value of a multi-lingual property.
-	 * 
-	 * @param qualifiedName
-	 *            The name of the property, it must include the namespace
-	 *            prefix. ie "pdf:Keywords"
-	 * @param language
-	 *            The language code of the value. If null then "x-default" is
-	 *            assumed.
-	 * 
-	 * @return The value of the language property.
-	 */
-	public String getLanguagePropertyValue(String qualifiedName, String language) {
-		if (language == null) {
-			language = "x-default";
-		}
-
-		AbstractField property = getAbstractProperty(qualifiedName);
-		if (property != null) {
-			if (property instanceof ComplexProperty) {
-				ComplexProperty prop = (ComplexProperty) property;
-				Iterator<AbstractField> langsDef = prop.getContainer()
-						.getAllProperties().iterator();
-				AbstractField tmp;
-				Attribute text;
-				while (langsDef.hasNext()) {
-					tmp = langsDef.next();
-					text = tmp.getAttribute("xml:lang");
-					if (text != null) {
-						if (text.getValue().equals(language)) {
-							return ((TextType) tmp).getStringValue();
-						}
-					}
-				}
-				return null;
-			} else {
-				throw new IllegalArgumentException("The property '"
-						+ qualifiedName + "' is not of Lang Alt type");
-			}
-		}
-		return null;
-	}
-
-	/**
-	 * Get a list of all languages that are currently defined for a specific
-	 * property, using the current prefix.
-	 * 
-	 * @param simpleName
-	 *            the local name of the property
-	 * @return A list of all languages, this will return an non-null empty list
-	 *         if none have been defined.
-	 */
-	public List<String> getLanguagePropertyLanguagesValueAsSimple(
-			String simpleName) {
-		return this.getLanguagePropertyLanguagesValue(localPrefixSep
-				+ simpleName);
-	}
-
-	/**
-	 * Get a list of all languages that are currently defined for a specific
-	 * property.
-	 * 
-	 * @param qualifiedName
-	 *            The name of the property, it must include the namespace
-	 *            prefix. ie "pdf:Keywords"
-	 * 
-	 * @return A list of all languages, this will return an non-null empty list
-	 *         if none have been defined.
-	 */
-	public List<String> getLanguagePropertyLanguagesValue(String qualifiedName) {
-		List<String> retval = new ArrayList<String>();
-
-		AbstractField property = getAbstractProperty(qualifiedName);
-		if (property != null) {
-			if (property instanceof ComplexProperty) {
-				ComplexProperty prop = (ComplexProperty) property;
-				Iterator<AbstractField> langsDef = prop.getContainer()
-						.getAllProperties().iterator();
-				AbstractField tmp;
-				Attribute text;
-				while (langsDef.hasNext()) {
-					tmp = langsDef.next();
-					text = tmp.getAttribute("xml:lang");
-					if (text != null) {
-						retval.add(text.getValue());
-					} else {
-						retval.add("x-default");
-					}
-				}
-				return retval;
-			} else {
-				throw new IllegalArgumentException("The property '"
-						+ qualifiedName + "' is not of Lang Alt type");
-			}
-		}
-		// no property with that name
-		return null;
-	}
-
-	/**
-	 * A basic schema merge, it merges bags and sequences and replace everything
-	 * else.
-	 * 
-	 * @param xmpSchema
-	 *            The schema to merge.
-	 * @throws IOException
-	 *             If there is an error during the merge.
-	 */
-	public void merge(XMPSchema xmpSchema) throws IOException {
-		if (!xmpSchema.getClass().equals(this.getClass())) {
-			throw new IOException("Can only merge schemas of the same type.");
-		}
-
-		Iterator<Attribute> itAtt = xmpSchema.content.getAllAttributes()
-				.iterator();
-		Attribute att;
-		while (itAtt.hasNext()) {
-			att = itAtt.next();
-			if (att.getPrefix().equals(getPrefix())) {
-				content.setAttribute(att);
-			}
-		}
-
-		String analyzedPropQualifiedName;
-		Iterator<AbstractField> itProp = xmpSchema.content.getAllProperties()
-				.iterator();
-		AbstractField prop;
-		while (itProp.hasNext()) {
-			prop = itProp.next();
-			if (prop.getPrefix().equals(getPrefix())) {
-				if (prop instanceof ComplexProperty) {
-					analyzedPropQualifiedName = prop.getQualifiedName();
-					Iterator<AbstractField> itActualEmbeddedProperties = content
-							.getAllProperties().iterator();
-					AbstractField tmpEmbeddedProperty;
-
-					Iterator<AbstractField> itNewValues;
-					TextType tmpNewValue;
-
-					Iterator<AbstractField> itOldValues;
-					TextType tmpOldValue;
-
-					boolean alreadyPresent = false;
-
-					while (itActualEmbeddedProperties.hasNext()) {
-						tmpEmbeddedProperty = itActualEmbeddedProperties.next();
-						if (tmpEmbeddedProperty instanceof ComplexProperty) {
-							if (tmpEmbeddedProperty.getQualifiedName().equals(
-									analyzedPropQualifiedName)) {
-								itNewValues = ((ComplexProperty) prop)
-										.getContainer().getAllProperties()
-										.iterator();
-								// Merge a complex property
-								while (itNewValues.hasNext()) {
-									tmpNewValue = (TextType) itNewValues.next();
-									itOldValues = ((ComplexProperty) tmpEmbeddedProperty)
-											.getContainer().getAllProperties()
-											.iterator();
-									while (itOldValues.hasNext()
-											&& !alreadyPresent) {
-										tmpOldValue = (TextType) itOldValues
-												.next();
-										if (tmpOldValue
-												.getStringValue()
-												.equals(
-														tmpNewValue
-																.getStringValue())) {
-											alreadyPresent = true;
-										}
-									}
-									if (!alreadyPresent) {
-										((ComplexProperty) tmpEmbeddedProperty)
-												.getContainer().addProperty(
-														tmpNewValue);
-									}
-								}
-
-							}
-						}
-					}
-				} else {
-					content.addProperty(prop);
-				}
-			}
-		}
-	}
-
-	/**
-	 * Get an AbstractField list corresponding to the content of an array Return
-	 * null if the property is unknown
-	 * 
-	 * @param qualifiedName
-	 *            the full qualified name of the property concerned
-	 * @return List of property contained in the complex property
-	 * @throws BadFieldValueException
-	 *             Property not contains property (not complex property)
-	 */
-	public List<AbstractField> getArrayList(String qualifiedName)
-			throws BadFieldValueException {
-		ComplexProperty array = null;
-		Iterator<AbstractField> itProp = content.getAllProperties().iterator();
-		AbstractField tmp;
-		while (itProp.hasNext()) {
-			tmp = itProp.next();
-			if (tmp.getQualifiedName().equals(qualifiedName)) {
-				if (tmp instanceof ComplexProperty) {
-					array = (ComplexProperty) tmp;
-					break;
-				} else {
-					throw new BadFieldValueException(
-							"Property asked not seems to be an array");
-				}
-
-			}
-		}
-		if (array != null) {
-			Iterator<AbstractField> it = array.getContainer()
-					.getAllProperties().iterator();
-			List<AbstractField> list = new ArrayList<AbstractField>();
-			while (it.hasNext()) {
-				list.add(it.next());
-			}
-			return list;
-		}
-		return null;
-	}
-
-	/**
-	 * Get PropertyContainer of this Schema
-	 * 
-	 * @return the ComplexProperty which represents the schema content
-	 */
-	public ComplexPropertyContainer getContent() {
-		return content;
-	}
-
-	/**
-	 * Get All attributes defined for this schema
-	 * 
-	 * @return Attributes list defined for this schema
-	 */
-	public List<Attribute> getAllAttributes() {
-		return content.getAllAttributes();
-	}
-
-	/**
-	 * Get All properties defined in this schema
-	 * 
-	 * @return Properties list defined in this schema
-	 */
-	public List<AbstractField> getAllProperties() {
-		return content.getAllProperties();
-	}
-
-	/**
-	 * Set a new attribute for this schema
-	 * 
-	 * @param attr
-	 *            The new Attribute to set
-	 */
-	public void setAttribute(Attribute attr) {
-		content.setAttribute(attr);
-	}
-
-	/**
-	 * Add a new Property to this schema
-	 * 
-	 * @param obj
-	 *            The new property to add
-	 */
-	public void addProperty(AbstractField obj) {
-		content.addProperty(obj);
-	}
-
-	/**
-	 * Get DOM Element for rdf/xml serialization
-	 * 
-	 * @return the DOM Element
-	 */
-	public Element getElement() {
-		return content.getElement();
-	}
-
-	/**
-	 * get a Property with its name, using the current prefix
-	 * 
-	 * @param simpleName
-	 *            the local name of the property
-	 * @return The property wanted
-	 */
-	protected AbstractField getPropertyAsSimple(String simpleName) {
-		return getProperty(localPrefixSep + simpleName);
-	}
-
-	/**
-	 * get a Property with its qualified Name (with its prefix)
-	 * 
-	 * @param qualifiedName
-	 *            The full qualified name of the property wanted
-	 * @return the property wanted
-	 */
-	protected AbstractField getProperty(String qualifiedName) {
-		Iterator<AbstractField> it = getAllProperties().iterator();
-		AbstractField tmp;
-		while (it.hasNext()) {
-			tmp = it.next();
-			if (tmp.getQualifiedName().equals(qualifiedName)) {
-				return tmp;
-			}
-		}
-		return null;
-	}
-
-	/**
-	 * Return local prefix
-	 * 
-	 * @return current prefix fixed for this schema
-	 */
-	public String getLocalPrefix() {
-		return this.localPrefix;
-	}
-
-	/**
-	 * Return local prefix with separator
-	 * 
-	 * @return current prefix fixed for this schema with ':' separator
-	 */
-	public String getLocalPrefixWithSeparator() {
-		return this.localPrefixSep;
-	}
+    /**
+     * The standard xmlns namespace.
+     */
+    public static final String NS_NAMESPACE = "http://www.w3.org/2000/xmlns/";
+
+    public static final String RDFABOUT = "rdf:about";
+
+    protected String localPrefix, localNSUri;
+    protected String localPrefixSep;
+    protected XMPMetadata metadata;
+    protected ComplexPropertyContainer content;
+
+    /**
+     * Create a new blank schema that can be populated.
+     * 
+     * @param metadata
+     *            The parent XMP metadata that this schema will be part of.
+     * @param namespaceName
+     *            The name of the namespace, ie pdf,dc,...
+     * @param namespaceURI
+     *            The URI of the namespace, ie "http://ns.adobe.com/pdf/1.3/"
+     * 
+     */
+    public XMPSchema(XMPMetadata metadata, String namespaceName, String namespaceURI) {
+        this.metadata = metadata;
+        content = new ComplexPropertyContainer(metadata,
+                "http://www.w3.org/1999/02/22-rdf-syntax-ns#", "rdf",
+        "Description");
+
+        localPrefix = namespaceName;
+        localPrefixSep = localPrefix + ":";
+        localNSUri = namespaceURI;
+        content.setAttribute(new Attribute(NS_NAMESPACE, "xmlns",
+                namespaceName, namespaceURI));
+
+    }
+
+    /**
+     * Get the schema prefix
+     * 
+     * @return Prefix fixed for the schema
+     */
+    public String getPrefix() {
+        return localPrefix;
+
+    }
+
+    /**
+     * Get the namespace URI of this schema
+     * 
+     * @return the namespace URI of this schema
+     */
+    public String getNamespaceValue() {
+        return localNSUri;
+    }
+
+    /**
+     * Retrieve a generic simple type property
+     * 
+     * @param qualifiedName
+     *            Full qualified name of proeprty wanted
+     * @return The generic simple type property according to its qualified Name
+     */
+    public AbstractField getAbstractProperty(String qualifiedName) {
+        Iterator<AbstractField> it = content.getAllProperties().iterator();
+        AbstractField tmp;
+        while (it.hasNext()) {
+            tmp = it.next();
+            if (tmp.getQualifiedName().equals(qualifiedName)) {
+                return tmp;
+            }
+        }
+        return null;
+
+    }
+
+    /**
+     * Get the RDF about attribute
+     * 
+     * @return The RDF 'about' attribute.
+     */
+    public Attribute getAboutAttribute() {
+        return content.getAttribute(RDFABOUT);
+    }
+
+    /**
+     * Get the RDF about value.
+     * 
+     * @return The RDF 'about' value.
+     */
+    public String getAboutValue() {
+        Attribute prop = content.getAttribute(RDFABOUT);
+        if (prop != null) {
+            return prop.getValue();
+        }
+        return null;
+    }
+
+    /**
+     * Set the RDF 'about' attribute
+     * 
+     * @param about
+     *            the well-formed attribute
+     * @throws BadFieldValueException
+     *             Bad Attribute name (not corresponding to about attribute)
+     */
+    public void setAbout(Attribute about) throws BadFieldValueException {
+        if (about.getQualifiedName().equals(RDFABOUT)
+                || about.getQualifiedName().equals("about")) {
+            content.setAttribute(about);
+        } else {
+            throw new BadFieldValueException(
+            "Attribute 'about' must be named 'rdf:about' or 'about'");
+        }
+    }
+
+    /**
+     * Set the RDF 'about' attribute. Passing in null will clear this attribute.
+     * 
+     * @param about
+     *            The new RFD about value.
+     */
+    public void setAboutAsSimple(String about) {
+        if (about == null) {
+            content.removeAttribute(RDFABOUT);
+        } else {
+            content.setAttribute(new Attribute(null, "rdf", "about", about));
+
+        }
+    }
+
+    /**
+     * Set a simple specified type property on the schema.
+     * 
+     * @param type
+     *            the property type
+     * @param qualifiedName
+     *            the qualified name to specify for the new property
+     * @param propertyValue
+     *            The value (must be an object understandable by specified type)
+     */
+    @SuppressWarnings("unchecked")
+    private void setSpecifiedSimpleTypeProperty(
+            Class<? extends AbstractSimpleProperty> type, String qualifiedName,
+            Object propertyValue) {
+        String[] splittedQualifiedName = qualifiedName.split(":");
+
+        Class[] propertyArgsClass = new Class[] { XMPMetadata.class,
+                String.class, String.class, Object.class };
+        Object[] propertyArgs = new Object[] { metadata,
+                splittedQualifiedName[0], splittedQualifiedName[1],
+                propertyValue };
+        Constructor<? extends AbstractSimpleProperty> propertyConstructor;
+
+        AbstractSimpleProperty specifiedTypeProperty;
+        if (propertyValue == null) {
+            // Search in properties to erase
+            Iterator<AbstractField> it = content.getAllProperties().iterator();
+            AbstractField tmp;
+            while (it.hasNext()) {
+                tmp = it.next();
+                if (tmp.getQualifiedName().equals(qualifiedName)) {
+                    content.removeProperty(tmp);
+                    return;
+                }
+            }
+        } else {
+            try {
+                propertyConstructor = type.getConstructor(propertyArgsClass);
+                specifiedTypeProperty = (AbstractSimpleProperty) propertyConstructor
+                .newInstance(propertyArgs);
+            } catch (Exception e) {
+                throw new IllegalArgumentException(
+                        "Failed to create property with the specified type given in parameters",
+                        e);
+            }
+            // attribute placement for simple property has been removed
+            // Search in properties to erase
+            Iterator<AbstractField> it = content.getAllProperties().iterator();
+            AbstractField tmp;
+            while (it.hasNext()) {
+                tmp = it.next();
+                if (tmp.getQualifiedName().equals(qualifiedName)) {
+                    content.removeProperty(tmp);
+                    content.addProperty(specifiedTypeProperty);
+                    return;
+                }
+            }
+            content.addProperty(specifiedTypeProperty);
+        }
+    }
+
+    /**
+     * Add a SimpleProperty to this schema
+     * 
+     * @param prop
+     *            The Property to add
+     */
+    private void setSpecifiedSimpleTypeProperty(AbstractSimpleProperty prop) {
+        // attribute placement for simple property has been removed
+        // Search in properties to erase
+        Iterator<AbstractField> it = content.getAllProperties().iterator();
+        AbstractField tmp;
+        while (it.hasNext()) {
+            tmp = it.next();
+            if (tmp.getQualifiedName().equals(prop.getQualifiedName())) {
+                content.removeProperty(tmp);
+                content.addProperty(prop);
+                return;
+            }
+        }
+        content.addProperty(prop);
+    }
+
+    /**
+     * Set TextType property
+     * 
+     * @param prop
+     *            The text property to add
+     */
+    public void setTextProperty(TextType prop) {
+        setSpecifiedSimpleTypeProperty(prop);
+    }
+
+    /**
+     * Set a simple text property on the schema.
+     * 
+     * @param qualifiedName
+     *            The name of the property, it must contain the namespace
+     *            prefix, ie "pdf:Keywords"
+     * @param propertyValue
+     *            The value for the property, can be any string. Passing null
+     *            will remove the property.
+     */
+    public void setTextPropertyValue(String qualifiedName, String propertyValue) {
+        setSpecifiedSimpleTypeProperty(TextType.class, qualifiedName,
+                propertyValue);
+    }
+
+    /**
+     * Set a simple text property on the schema, using the current prefix.
+     * 
+     * @param simpleName
+     *            the name of the property without prefix
+     * @param propertyValue
+     *            The value for the property, can be any string. Passing null
+     *            will remove the property.
+     */
+    public void setTextPropertyValueAsSimple(String simpleName,
+            String propertyValue) {
+        this.setTextPropertyValue(localPrefixSep + simpleName, propertyValue);
+    }
+
+    /**
+     * Get a TextProperty Type from its name
+     * 
+     * @param qualifiedName
+     *            The full qualified name of the property wanted
+     * @return The Text Type property wanted
+     */
+    public TextType getTextProperty(String qualifiedName) {
+        AbstractField prop = getAbstractProperty(qualifiedName);
+        if (prop != null) {
+            if (prop instanceof TextType) {
+                return (TextType) prop;
+            } else {
+                throw new IllegalArgumentException(
+                "Property asked is not a Text Property");
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Get a simple text property value on the schema, using the current prefix.
+     * 
+     * @param simpleName
+     *            The local name of the property wanted
+     * @return The value of the text property or the null if there is no value.
+     * 
+     */
+    public String getTextPropertyValueAsSimple(String simpleName) {
+        return this.getTextPropertyValue(localPrefixSep + simpleName);
+    }
+
+    /**
+     * Get the value of a simple text property.
+     * 
+     * @param qualifiedName
+     *            The name of the property to get, it must include the namespace
+     *            prefix. ie "pdf:Keywords".
+     * 
+     * @return The value of the text property or the null if there is no value.
+     * 
+     */
+    public String getTextPropertyValue(String qualifiedName) {
+        AbstractField prop = getAbstractProperty(qualifiedName);
+        if (prop != null) {
+            if (prop instanceof TextType) {
+                return ((TextType) prop).getStringValue();
+            } else {
+                throw new IllegalArgumentException(
+                "Property asked is not a Text Property");
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Get the Date property with its name
+     * 
+     * @param qualifiedName
+     *            The name of the property to get, it must include the namespace
+     *            prefix. ie "pdf:Keywords".
+     * @return Date Type property
+     * 
+     */
+    public DateType getDateProperty(String qualifiedName) {
+        AbstractField prop = getAbstractProperty(qualifiedName);
+        if (prop != null) {
+            if (prop instanceof DateType) {
+                return (DateType) prop;
+            } else {
+                throw new IllegalArgumentException(
+                "Property asked is not a Date Property");
+            }
+
+        }
+        return null;
+    }
+
+    /**
+     * Get a simple date property value on the schema, using the current prefix.
+     * 
+     * @param simpleName
+     *            the local name of the property to get
+     * @return The value of the property as a calendar.
+     * 
+     */
+    public Calendar getDatePropertyValueAsSimple(String simpleName) {
+        return this.getDatePropertyValue(localPrefixSep + simpleName);
+    }
+
+    /**
+     * Get the value of the property as a date.
+     * 
+     * @param qualifiedName
+     *            The fully qualified property name for the date.
+     * 
+     * @return The value of the property as a date.
+     * 
+     */
+    public Calendar getDatePropertyValue(String qualifiedName) {
+        AbstractField prop = getAbstractProperty(qualifiedName);
+        if (prop != null) {
+            if (prop instanceof DateType) {
+                return ((DateType) prop).getValue();
+            } else {
+                throw new IllegalArgumentException(
+                "Property asked is not a Date Property");
+            }
+
+        }
+        return null;
+    }
+
+    /**
+     * Set a new DateProperty
+     * 
+     * @param date
+     *            The DateType Property
+     */
+    public void setDateProperty(DateType date) {
+        setSpecifiedSimpleTypeProperty(date);
+    }
+
+    /**
+     * Set a simple Date property on the schema, using the current prefix.
+     * 
+     * @param simpleName
+     *            the name of the property without prefix
+     * @param date
+     *            The calendar value for the property, can be any string.
+     *            Passing null will remove the property.
+     */
+    public void setDatePropertyValueAsSimple(String simpleName, Calendar date) {
+        this.setDatePropertyValue(localPrefixSep + simpleName, date);
+    }
+
+    /**
+     * Set the value of the property as a date.
+     * 
+     * @param qualifiedName
+     *            The fully qualified property name for the date.
+     * @param date
+     *            The date to set, or null to clear.
+     */
+    public void setDatePropertyValue(String qualifiedName, Calendar date) {
+        setSpecifiedSimpleTypeProperty(DateType.class, qualifiedName, date);
+
+    }
+
+    /**
+     * Get a BooleanType property with its name
+     * 
+     * @param qualifiedName
+     *            the full qualified name of property wanted
+     * @return boolean Type property
+     */
+    public BooleanType getBooleanProperty(String qualifiedName) {
+        AbstractField prop = getAbstractProperty(qualifiedName);
+        if (prop != null) {
+            if (prop instanceof BooleanType) {
+                return (BooleanType) prop;
+            } else {
+                throw new IllegalArgumentException(
+                "Property asked is not a Boolean Property");
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Get a simple boolean property value on the schema, using the current
+     * prefix.
+     * 
+     * @param simpleName
+     *            the local name of property wanted
+     * @return The value of the property as a boolean.
+     */
+    public Boolean getBooleanPropertyValueAsSimple(String simpleName) {
+        return this.getBooleanPropertyValue(localPrefixSep + simpleName);
+    }
+
+    /**
+     * Get the value of the property as a boolean.
+     * 
+     * @param qualifiedName
+     *            The fully qualified property name for the boolean.
+     * 
+     * @return The value of the property as a boolean. Return null if property
+     *         not exist
+     */
+    public Boolean getBooleanPropertyValue(String qualifiedName) {
+        AbstractField prop = getAbstractProperty(qualifiedName);
+        if (prop != null) {
+            if (prop instanceof BooleanType) {
+                return ((BooleanType) prop).getValue();
+            } else {
+                throw new IllegalArgumentException(
+                "Property asked is not a Boolean Property");
+            }
+        }
+        // Return null if property not exist. This method give the property
+        // value so treat this return in this way.
+        // If you want to use this value like a condition, you must check this
+        // return before
+        return null;
+    }
+
+    /**
+     * Set a BooleanType property
+     * 
+     * @param bool
+     *            the booleanType property
+     */
+    public void setBooleanProperty(BooleanType bool) {
+        setSpecifiedSimpleTypeProperty(bool);
+    }
+
+    /**
+     * Set a simple Boolean property on the schema, using the current prefix.
+     * 
+     * @param simpleName
+     *            the name of the property without prefix
+     * @param bool
+     *            The value for the property, can be any string. Passing null
+     *            will remove the property.
+     */
+    public void setBooleanPropertyValueAsSimple(String simpleName, Boolean bool) {
+        this.setBooleanPropertyValue(localPrefixSep + simpleName, bool);
+    }
+
+    /**
+     * Set the value of the property as a boolean.
+     * 
+     * @param qualifiedName
+     *            The fully qualified property name for the boolean.
+     * @param bool
+     *            The boolean to set, or null to clear.
+     */
+    public void setBooleanPropertyValue(String qualifiedName, Boolean bool) {
+        setSpecifiedSimpleTypeProperty(BooleanType.class, qualifiedName, bool);
+    }
+
+    /**
+     * Get the Integer property with its name
+     * 
+     * @param qualifiedName
+     *            the full qualified name of property wanted
+     * @return Integer Type property
+     */
+    public IntegerType getIntegerProperty(String qualifiedName) {
+        AbstractField prop = getAbstractProperty(qualifiedName);
+        if (prop != null) {
+            if (prop instanceof IntegerType) {
+                return ((IntegerType) prop);
+            } else {
+                throw new IllegalArgumentException(
+                "Property asked is not an Integer Property");
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Get a simple integer property value on the schema, using the current
+     * prefix.
+     * 
+     * @param simpleName
+     *            the local name of property wanted
+     * @return The value of the property as an integer.
+     */
+    public Integer getIntegerPropertyValueAsSimple(String simpleName) {
+        return this.getIntegerPropertyValue(localPrefixSep + simpleName);
+    }
+
+    /**
+     * Get the value of the property as an integer.
+     * 
+     * @param qualifiedName
+     *            The fully qualified property name for the integer.
+     * 
+     * @return The value of the property as an integer.
+     */
+    public Integer getIntegerPropertyValue(String qualifiedName) {
+        AbstractField prop = getAbstractProperty(qualifiedName);
+        if (prop != null) {
+            if (prop instanceof IntegerType) {
+                return ((IntegerType) prop).getValue();
+            } else {
+                throw new IllegalArgumentException(
+                "Property asked is not an Integer Property");
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Add an integerProperty
+     * 
+     * @param prop
+     *            The Integer Type property
+     */
+    public void setIntegerProperty(IntegerType prop) {
+        setSpecifiedSimpleTypeProperty(prop);
+    }
+
+    /**
+     * Set a simple Integer property on the schema, using the current prefix.
+     * 
+     * @param simpleName
+     *            the name of the property without prefix
+     * @param intValue
+     *            The value for the property, can be any string. Passing null
+     *            will remove the property.
+     */
+    public void setIntegerPropertyValueAsSimple(String simpleName,
+            Integer intValue) {
+        this.setIntegerPropertyValue(localPrefixSep + simpleName, intValue);
+    }
+
+    /**
+     * Set the value of the property as an integer.
+     * 
+     * @param qualifiedName
+     *            The fully qualified property name for the integer.
+     * @param intValue
+     *            The int to set, or null to clear.
+     */
+    public void setIntegerPropertyValue(String qualifiedName, Integer intValue) {
+        setSpecifiedSimpleTypeProperty(IntegerType.class, qualifiedName,
+                intValue);
+    }
+
+    /**
+     * Generic array property removing
+     * 
+     * @param qualifiedArrayName
+     *            the full qualified name of property wanted
+     * @param fieldValue
+     *            the field value
+     */
+    private void removeArrayValue(String qualifiedArrayName, String fieldValue) {
+        ComplexProperty array = (ComplexProperty) getAbstractProperty(qualifiedArrayName);
+        if (array != null) {
+            ArrayList<AbstractField> toDelete = new ArrayList<AbstractField>();
+            Iterator<AbstractField> it = array.getContainer()
+            .getAllProperties().iterator();
+            AbstractSimpleProperty tmp;
+            while (it.hasNext()) {
+                tmp = (AbstractSimpleProperty) it.next();
+                if (tmp.getStringValue().equals(fieldValue)) {
+                    toDelete.add(tmp);
+                }
+            }
+            Iterator<AbstractField> eraseProperties = toDelete.iterator();
+            while (eraseProperties.hasNext()) {
+                array.getContainer().removeProperty(eraseProperties.next());
+            }
+        }
+
+    }
+
+    /**
+     * Remove all matching entries with the given value from the bag.
+     * 
+     * @param qualifiedBagName
+     *            The name of the bag, it must include the namespace prefix. ie
+     *            "pdf:Keywords".
+     * @param bagValue
+     *            The value to remove from the bagList.
+     */
+    public void removeBagValue(String qualifiedBagName, String bagValue) {
+        removeArrayValue(qualifiedBagName, bagValue);
+    }
+
+    /**
+     * add a bag value property on the schema, using the current prefix.
+     * 
+     * @param simpleName
+     *            the local name of property
+     * @param bagValue
+     *            the string value to add
+     */
+    public void addBagValueAsSimple(String simpleName, String bagValue) {
+        this.addBagValue(localPrefixSep + simpleName, bagValue);
+    }
+
+    /**
+     * Add an entry to a bag property.
+     * 
+     * @param qualifiedBagName
+     *            The name of the bag, it must include the namespace prefix. ie
+     *            "pdf:Keywords".
+     * @param bagValue
+     *            The value to add to the bagList.
+     */
+    public void addBagValue(String qualifiedBagName, String bagValue) {
+        String[] splittedQualifiedName = qualifiedBagName.split(":");
+        ComplexProperty bag = (ComplexProperty) getAbstractProperty(qualifiedBagName);
+        TextType li = new TextType(metadata, "rdf", "li", bagValue);
+        if (bag != null) {
+            bag.getContainer().addProperty(li);
+        } else {
+            ComplexProperty newBag = new ComplexProperty(metadata,
+                    splittedQualifiedName[0], splittedQualifiedName[1],
+                    ComplexProperty.UNORDERED_ARRAY);
+            newBag.getContainer().addProperty(li);
+            content.addProperty(newBag);
+        }
+    }
+
+    /**
+     * Generic String List Builder for arrays contents
+     * 
+     * @param qualifiedArrayName
+     *            the full qualified name of property concerned
+     * @return String list which represents content of array property
+     */
+    private List<String> getArrayListToString(String qualifiedArrayName) {
+        List<String> retval = null;
+        ComplexProperty array = (ComplexProperty) getAbstractProperty(qualifiedArrayName);
+        if (array != null) {
+            retval = new ArrayList<String>();
+            Iterator<AbstractField> it = array.getContainer()
+            .getAllProperties().iterator();
+            AbstractSimpleProperty tmp;
+            while (it.hasNext()) {
+                tmp = (AbstractSimpleProperty) it.next();
+                retval.add(tmp.getStringValue());
+            }
+            retval = Collections.unmodifiableList(retval);
+        }
+        return retval;
+    }
+
+    /**
+     * Get all the values of the bag property, using the current prefix. This
+     * will return a list of java.lang.String objects, this is a read-only list.
+     * 
+     * @param simpleName
+     *            the local name of property concerned
+     * 
+     * 
+     * @return All values of the bag property in a list.
+     */
+    public List<String> getBagValueListAsSimple(String simpleName) {
+        return getBagValueList(localPrefixSep + simpleName);
+    }
+
+    /**
+     * Get all the values of the bag property. This will return a list of
+     * java.lang.String objects, this is a read-only list.
+     * 
+     * @param qualifiedBagName
+     *            The name of the bag property to get, it must include the
+     *            namespace prefix. ie "pdf:Keywords"
+     * 
+     * @return All values of the bag property in a list.
+     */
+    public List<String> getBagValueList(String qualifiedBagName) {
+        return getArrayListToString(qualifiedBagName);
+    }
+
+    /**
+     * Remove all matching values from a sequence property.
+     * 
+     * @param qualifiedSeqName
+     *            The name of the sequence property. It must include the
+     *            namespace prefix. ie "pdf:Keywords".
+     * @param seqValue
+     *            The value to remove from the list.
+     */
+    public void removeSequenceValue(String qualifiedSeqName, String seqValue) {
+        removeArrayValue(qualifiedSeqName, seqValue);
+    }
+
+    /**
+     * Generic method to remove a field from an array with an Elementable Object
+     * 
+     * @param qualifiedArrayName
+     *            the full qualified name of the property concerned
+     * @param fieldValue
+     *            the elementable field value
+     */
+    public void removeArrayValue(String qualifiedArrayName,
+            Elementable fieldValue) {
+        ComplexProperty array = (ComplexProperty) getAbstractProperty(qualifiedArrayName);
+        if (array != null) {
+            ArrayList<AbstractField> toDelete = new ArrayList<AbstractField>();
+            Iterator<AbstractField> it = array.getContainer()
+            .getAllProperties().iterator();
+            AbstractSimpleProperty tmp;
+            while (it.hasNext()) {
+                tmp = (AbstractSimpleProperty) it.next();
+                if (tmp.equals(fieldValue)) {
+                    toDelete.add(tmp);
+                }
+            }
+            Iterator<AbstractField> eraseProperties = toDelete.iterator();
+            while (eraseProperties.hasNext()) {
+                array.getContainer().removeProperty(eraseProperties.next());
+            }
+        }
+    }
+
+    /**
+     * Remove a value from a sequence property. This will remove all entries
+     * from the list.
+     * 
+     * @param qualifiedSeqName
+     *            The name of the sequence property. It must include the
+     *            namespace prefix. ie "pdf:Keywords".
+     * @param seqValue
+     *            The value to remove from the list.
+     */
+    public void removeSequenceValue(String qualifiedSeqName,
+            Elementable seqValue) {
+        removeArrayValue(qualifiedSeqName, seqValue);
+    }
+
+    /**
+     * Add a new value to a sequence property.
+     * 
+     * @param qualifiedSeqName
+     *            The name of the sequence property, it must include the
+     *            namespace prefix. ie "pdf:Keywords"
+     * @param seqValue
+     *            The value to add to the sequence.
+     */
+    public void addSequenceValue(String qualifiedSeqName, String seqValue) {
+        String[] splittedQualifiedName = qualifiedSeqName.split(":");
+        ComplexProperty seq = (ComplexProperty) getAbstractProperty(qualifiedSeqName);
+        TextType li = new TextType(metadata, "rdf", "li", seqValue);
+        if (seq != null) {
+            seq.getContainer().addProperty(li);
+        } else {
+            ComplexProperty newSeq = new ComplexProperty(metadata,
+                    splittedQualifiedName[0], splittedQualifiedName[1],
+                    ComplexProperty.ORDERED_ARRAY);
+            newSeq.getContainer().addProperty(li);
+            content.addProperty(newSeq);
+        }
+
+    }
+
+    /**
+     * Add a new value to a bag property.
+     * 
+     * @param qualifiedSeqName
+     *            The name of the sequence property, it must include the
+     *            namespace prefix. ie "pdf:Keywords"
+     * @param seqValue
+     *            The value to add to the bag.
+     */
+    public void addBagValue(String qualifiedSeqName, AbstractField seqValue) {
+
+        String[] splittedQualifiedName = qualifiedSeqName.split(":");
+        ComplexProperty bag = (ComplexProperty) getAbstractProperty(qualifiedSeqName);
+        if (bag != null) {
+            bag.getContainer().addProperty(seqValue);
+        } else {
+            ComplexProperty newBag = new ComplexProperty(metadata,
+                    splittedQualifiedName[0], splittedQualifiedName[1],
+                    ComplexProperty.UNORDERED_ARRAY);
+            newBag.getContainer().addProperty(seqValue);
+            content.addProperty(newBag);
+        }
+    }
+
+    /**
+     * add a new value to a sequence property using the current prefix.
+     * 
+     * @param simpleName
+     *            the local name of the property
+     * @param seqValue
+     *            the string value to add
+     */
+    public void addSequenceValueAsSimple(String simpleName, String seqValue) {
+        this.addSequenceValue(localPrefixSep + simpleName, seqValue);
+    }
+
+    /**
+     * Add a new value to a sequence property.
+     * 
+     * @param qualifiedSeqName
+     *            The name of the sequence property, it must include the
+     *            namespace prefix. ie "pdf:Keywords"
+     * @param seqValue
+     *            The value to add to the sequence.
+     */
+    public void addSequenceValue(String qualifiedSeqName, AbstractField seqValue) {
+
+        String[] splittedQualifiedName = qualifiedSeqName.split(":");
+        ComplexProperty seq = (ComplexProperty) getAbstractProperty(qualifiedSeqName);
+        if (seq != null) {
+            seq.getContainer().addProperty(seqValue);
+        } else {
+            ComplexProperty newSeq = new ComplexProperty(metadata,
+                    splittedQualifiedName[0], splittedQualifiedName[1],
+                    ComplexProperty.ORDERED_ARRAY);
+            newSeq.getContainer().addProperty(seqValue);
+            content.addProperty(newSeq);
+        }
+    }
+
+    /**
+     * Get all the values in a sequence property, using the current prefix.
+     * 
+     * @param simpleName
+     *            the local name of the property
+     * @return A read-only list of java.lang.String objects or null if the
+     *         property does not exist.
+     */
+    public List<String> getSequenceValueListAsSimple(String simpleName) {
+        return this.getSequenceValueList(localPrefixSep + simpleName);
+    }
+
+    /**
+     * Get all the values in a sequence property.
+     * 
+     * @param qualifiedSeqName
+     *            The name of the sequence property, it must include the
+     *            namespace prefix. ie "pdf:Keywords".
+     * 
+     * @return A read-only list of java.lang.String objects or null if the
+     *         property does not exist.
+     */
+    public List<String> getSequenceValueList(String qualifiedSeqName) {
+        return getArrayListToString(qualifiedSeqName);
+    }
+
+    /**
+     * Remove a date sequence value from the list.
+     * 
+     * @param qualifiedSeqName
+     *            The name of the sequence property, it must include the
+     *            namespace prefix. ie "pdf:Keywords"
+     * @param date
+     *            The date to remove from the sequence property.
+     */
+    public void removeSequenceDateValue(String qualifiedSeqName, Calendar date) {
+        ComplexProperty seq = (ComplexProperty) getAbstractProperty(qualifiedSeqName);
+        if (seq != null) {
+            ArrayList<AbstractField> toDelete = new ArrayList<AbstractField>();
+            Iterator<AbstractField> it = seq.getContainer().getAllProperties()
+            .iterator();
+            AbstractField tmp;
+            while (it.hasNext()) {
+                tmp = it.next();
+                if (tmp instanceof DateType) {
+                    if (((DateType) tmp).getValue().equals(date)) {
+                        toDelete.add(tmp);
+
+                    }
+                }
+            }
+            Iterator<AbstractField> eraseProperties = toDelete.iterator();
+            while (eraseProperties.hasNext()) {
+                seq.getContainer().removeProperty(eraseProperties.next());
+            }
+        }
+    }
+
+    /**
+     * Add a date sequence value to the list using the current prefix
+     * 
+     * @param simpleName
+     *            the local name of the property
+     * @param date
+     *            the value to add
+     */
+    public void addSequenceDateValueAsSimple(String simpleName, Calendar date) {
+        addSequenceDateValue(localPrefixSep + simpleName, date);
+    }
+
+    /**
+     * Add a date sequence value to the list.
+     * 
+     * @param qualifiedSeqName
+     *            The name of the sequence property, it must include the
+     *            namespace prefix. ie "pdf:Keywords"
+     * @param date
+     *            The date to add to the sequence property.
+     */
+    public void addSequenceDateValue(String qualifiedSeqName, Calendar date) {
+        addSequenceValue(qualifiedSeqName, new DateType(metadata, "rdf", "li",
+                date));
+    }
+
+    /**
+     * Get all the date values in a sequence property, using the current prefix.
+     * 
+     * @param simpleName
+     *            the local name of property concerned
+     * @return A read-only list of java.util.Calendar objects or null if the
+     *         property does not exist.
+     */
+    public List<Calendar> getSequenceDateValueListAsSimple(String simpleName) {
+        return this.getSequenceDateValueList(localPrefixSep + simpleName);
+    }
+
+    /**
+     * Get all the date values in a sequence property.
+     * 
+     * @param qualifiedSeqName
+     *            The name of the sequence property, it must include the
+     *            namespace prefix. ie "pdf:Keywords".
+     * 
+     * @return A read-only list of java.util.Calendar objects or null if the
+     *         property does not exist.
+     * 
+     */
+    public List<Calendar> getSequenceDateValueList(String qualifiedSeqName) {
+        List<Calendar> retval = null;
+        ComplexProperty seq = (ComplexProperty) getAbstractProperty(qualifiedSeqName);
+        if (seq != null) {
+            retval = new ArrayList<Calendar>();
+            Iterator<AbstractField> it = seq.getContainer().getAllProperties()
+            .iterator();
+            AbstractField tmp;
+            while (it.hasNext()) {
+                tmp = it.next();
+                if (tmp instanceof DateType) {
+                    retval.add(((DateType) tmp).getValue());
+                }
+            }
+        }
+        return retval;
+    }
+
+    /**
+     * Method used to place the 'x-default' value in first in Language
+     * alternatives as said in xmp spec
+     * 
+     * @param alt
+     *            The property to reorganize
+     */
+    public void reorganizeAltOrder(ComplexPropertyContainer alt) {
+        Iterator<AbstractField> it = alt.getAllProperties().iterator();
+        AbstractField xdefault = null;
+        boolean xdefaultFound = false;
+        // If alternatives contains x-default in first value
+        if (it.hasNext()) {
+            if (it.next().getAttribute("xml:lang").getValue().equals(
+            "x-default")) {
+                return;
+            }
+        }
+        // Find the xdefault definition
+        while (it.hasNext() && !xdefaultFound) {
+            xdefault = it.next();
+            if (xdefault.getAttribute("xml:lang").getValue()
+                    .equals("x-default")) {
+                alt.removeProperty(xdefault);
+                xdefaultFound = true;
+            }
+        }
+        if (xdefaultFound) {
+            it = alt.getAllProperties().iterator();
+            ArrayList<AbstractField> reordered = new ArrayList<AbstractField>();
+            ArrayList<AbstractField> toDelete = new ArrayList<AbstractField>();
+            reordered.add(xdefault);
+            AbstractField tmp;
+            while (it.hasNext()) {
+                tmp = it.next();
+                reordered.add(tmp);
+                toDelete.add(tmp);
+            }
+            Iterator<AbstractField> eraseProperties = toDelete.iterator();
+            while (eraseProperties.hasNext()) {
+                alt.removeProperty(eraseProperties.next());
+            }
+            it = reordered.iterator();
+            while (it.hasNext()) {
+                alt.addProperty(it.next());
+            }
+        }
+
+    }
+
+    /**
+     * Set a multi-lingual property on the schema, using the current prefix.
+     * 
+     * @param simpleName
+     *            the local name of the property
+     * @param language
+     *            the language concerned
+     * @param value
+     *            the value to set for the language specified
+     */
+    public void setLanguagePropertyValueAsSimple(String simpleName,
+            String language, String value) {
+        this.setLanguagePropertyValue(localPrefixSep + simpleName, language,
+                value);
+    }
+
+    /**
+     * Set the value of a multi-lingual property.
+     * 
+     * @param qualifiedName
+     *            The name of the property, it must include the namespace
+     *            prefix. ie "pdf:Keywords"
+     * @param language
+     *            The language code of the value. If null then "x-default" is
+     *            assumed.
+     * @param value
+     *            The value of the property in the specified language.
+     */
+    public void setLanguagePropertyValue(String qualifiedName, String language,
+            String value) {
+        AbstractField property = getAbstractProperty(qualifiedName);
+        ComplexProperty prop;
+        if (property != null) {
+            // Analyzing content of property
+            if (property instanceof ComplexProperty) {
+                prop = (ComplexProperty) property;
+                Iterator<AbstractField> itCplx = prop.getContainer()
+                .getAllProperties().iterator();
+                // try to find the same lang definition
+                AbstractField tmp;
+                // Try to find a definition
+                while (itCplx.hasNext()) {
+                    tmp = itCplx.next();
+                    // System.err.println(tmp.getAttribute("xml:lang").getStringValue());
+                    if (tmp.getAttribute("xml:lang").getValue()
+                            .equals(language)) {
+                        // the same language has been found
+                        if (value == null) {
+                            // if value null, erase this definition
+                            prop.getContainer().removeProperty(tmp);
+                        } else {
+                            prop.getContainer().removeProperty(tmp);
+                            TextType langValue;
+                            langValue = new TextType(metadata, "rdf", "li",
+                                    value);
+
+                            langValue.setAttribute(new Attribute(null, "xml",
+                                    "lang", language));
+                            prop.getContainer().addProperty(langValue);
+                        }
+                        reorganizeAltOrder(prop.getContainer());
+                        return;
+                    }
+                }
+                // if no definition found, we add a new one
+                TextType langValue;
+                langValue = new TextType(metadata, "rdf", "li", value);
+                langValue.setAttribute(new Attribute(null, "xml", "lang",
+                        language));
+                prop.getContainer().addProperty(langValue);
+                reorganizeAltOrder(prop.getContainer());
+            }
+        } else {
+            String[] splittedQualifiedName = qualifiedName.split(":");
+            prop = new ComplexProperty(metadata, splittedQualifiedName[0],
+                    splittedQualifiedName[1], ComplexProperty.ALTERNATIVE_ARRAY);
+            TextType langValue;
+            langValue = new TextType(metadata, "rdf", "li", value);
+            langValue
+            .setAttribute(new Attribute(null, "xml", "lang", language));
+            prop.getContainer().addProperty(langValue);
+            content.addProperty(prop);
+        }
+    }
+
+    /**
+     * Get the value of a multi-lingual property, using the current prefix.
+     * 
+     * @param simpleName
+     *            the local name of the property
+     * @param language
+     *            The language code of the value. If null then "x-default" is
+     *            assumed.
+     * 
+     * @return The value of the language property.
+     */
+    public String getLanguagePropertyValueAsSimple(String simpleName,
+            String language) {
+        return this.getLanguagePropertyValue(localPrefixSep + simpleName,
+                language);
+    }
+
+    /**
+     * Get the value of a multi-lingual property.
+     * 
+     * @param qualifiedName
+     *            The name of the property, it must include the namespace
+     *            prefix. ie "pdf:Keywords"
+     * @param language
+     *            The language code of the value. If null then "x-default" is
+     *            assumed.
+     * 
+     * @return The value of the language property.
+     */
+    public String getLanguagePropertyValue(String qualifiedName, String expectedLanguage) {
+        String language = (expectedLanguage!=null)?expectedLanguage:"x-default";
+        AbstractField property = getAbstractProperty(qualifiedName);
+        if (property != null) {
+            if (property instanceof ComplexProperty) {
+                ComplexProperty prop = (ComplexProperty) property;
+                Iterator<AbstractField> langsDef = prop.getContainer()
+                .getAllProperties().iterator();
+                AbstractField tmp;
+                Attribute text;
+                while (langsDef.hasNext()) {
+                    tmp = langsDef.next();
+                    text = tmp.getAttribute("xml:lang");
+                    if (text != null) {
+                        if (text.getValue().equals(language)) {
+                            return ((TextType) tmp).getStringValue();
+                        }
+                    }
+                }
+                return null;
+            } else {
+                throw new IllegalArgumentException("The property '"
+                        + qualifiedName + "' is not of Lang Alt type");
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Get a list of all languages that are currently defined for a specific
+     * property, using the current prefix.
+     * 
+     * @param simpleName
+     *            the local name of the property
+     * @return A list of all languages, this will return an non-null empty list
+     *         if none have been defined.
+     */
+    public List<String> getLanguagePropertyLanguagesValueAsSimple(
+            String simpleName) {
+        return this.getLanguagePropertyLanguagesValue(localPrefixSep
+                + simpleName);
+    }
+
+    /**
+     * Get a list of all languages that are currently defined for a specific
+     * property.
+     * 
+     * @param qualifiedName
+     *            The name of the property, it must include the namespace
+     *            prefix. ie "pdf:Keywords"
+     * 
+     * @return A list of all languages, this will return an non-null empty list
+     *         if none have been defined.
+     */
+    public List<String> getLanguagePropertyLanguagesValue(String qualifiedName) {
+        List<String> retval = new ArrayList<String>();
+
+        AbstractField property = getAbstractProperty(qualifiedName);
+        if (property != null) {
+            if (property instanceof ComplexProperty) {
+                ComplexProperty prop = (ComplexProperty) property;
+                Iterator<AbstractField> langsDef = prop.getContainer()
+                .getAllProperties().iterator();
+                AbstractField tmp;
+                Attribute text;
+                while (langsDef.hasNext()) {
+                    tmp = langsDef.next();
+                    text = tmp.getAttribute("xml:lang");
+                    if (text != null) {
+                        retval.add(text.getValue());
+                    } else {
+                        retval.add("x-default");
+                    }
+                }
+                return retval;
+            } else {
+                throw new IllegalArgumentException("The property '"
+                        + qualifiedName + "' is not of Lang Alt type");
+            }
+        }
+        // no property with that name
+        return null;
+    }
+
+    /**

[... 233 lines stripped ...]