Bug 501827 - Parameter replacement in the document metadata attributes.

Change-Id: I0ba5be05d7ba53fadea2fa144d988af2b2d0f22e
Signed-off-by: Antonio Campesino <antonio.campesino.robles@ericsson.com>
diff --git a/features/org.eclipse.gendoc.feature/feature.xml b/features/org.eclipse.gendoc.feature/feature.xml
index f637f86..a4844b2 100644
--- a/features/org.eclipse.gendoc.feature/feature.xml
+++ b/features/org.eclipse.gendoc.feature/feature.xml
@@ -301,4 +301,11 @@
          version="0.0.0"
          unpack="false"/>
 
+   <plugin
+         id="org.eclipse.gendoc.documents.metadata"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
 </feature>
diff --git a/plugins/org.eclipse.gendoc.document.parser/src/org/eclipse/gendoc/document/parser/documents/Document.java b/plugins/org.eclipse.gendoc.document.parser/src/org/eclipse/gendoc/document/parser/documents/Document.java
index 4c5ea08..a61dd80 100644
--- a/plugins/org.eclipse.gendoc.document.parser/src/org/eclipse/gendoc/document/parser/documents/Document.java
+++ b/plugins/org.eclipse.gendoc.document.parser/src/org/eclipse/gendoc/document/parser/documents/Document.java
@@ -28,7 +28,7 @@
      * Developer has to precise if he wants to manage header or footer
      * Classes derived from document have to guarante access to xml parsers corresponding
      */
-    enum CONFIGURATION {undefined, content, header, footer, comment} ;
+    enum CONFIGURATION {undefined, content, header, footer, comment, metadata} ;
     
     /**
      * Enumeration to get property from document
diff --git a/plugins/org.eclipse.gendoc.document.parser/src/org/eclipse/gendoc/document/parser/documents/docx/DocxDocument.java b/plugins/org.eclipse.gendoc.document.parser/src/org/eclipse/gendoc/document/parser/documents/docx/DocxDocument.java
index c2e6eb3..9f7bd4b 100644
--- a/plugins/org.eclipse.gendoc.document.parser/src/org/eclipse/gendoc/document/parser/documents/docx/DocxDocument.java
+++ b/plugins/org.eclipse.gendoc.document.parser/src/org/eclipse/gendoc/document/parser/documents/docx/DocxDocument.java
@@ -210,6 +210,13 @@
             case comment:
                 OfficeHelper.fillCollection(getUnzipper(), parsers, DOCXHelper.RELATIONSHIPS_COMMENTS, idForDocument, DOCXHelper.DOCUMENT_RELS_FILE_NAME);
                 break;
+            case metadata:
+            	parsers.add(new XMLParser(getUnzipper().getFile(DOCXHelper.PROPERTIES_CORE_FILE_NAME), idForDocument));
+            	File customProp = getUnzipper().getFile(DOCXHelper.PROPERTIES_CUSTOM_FILE_NAME);
+            	if (customProp != null && customProp.exists()) {
+            		parsers.add(new XMLParser(customProp, idForDocument));
+            	}
+            	break;
             default:
         }
         return parsers;
diff --git a/plugins/org.eclipse.gendoc.document.parser/src/org/eclipse/gendoc/document/parser/documents/helper/DOCXHelper.java b/plugins/org.eclipse.gendoc.document.parser/src/org/eclipse/gendoc/document/parser/documents/helper/DOCXHelper.java
index c1f5b3b..eb53d3c 100644
--- a/plugins/org.eclipse.gendoc.document.parser/src/org/eclipse/gendoc/document/parser/documents/helper/DOCXHelper.java
+++ b/plugins/org.eclipse.gendoc.document.parser/src/org/eclipse/gendoc/document/parser/documents/helper/DOCXHelper.java
@@ -33,6 +33,9 @@
     public static final String STYLE_FILE_NAME = "styles.xml";
 
     public static final String DOCUMENT_RELS_FILE_NAME = "document.xml.rels";
+    
+    public static final String PROPERTIES_CUSTOM_FILE_NAME = "docProps/custom.xml";
+    public static final String PROPERTIES_CORE_FILE_NAME = "docProps/core.xml";
 
     /** The Constant XPATH_ALL_STYLES. */
     public static final String XPATH_ALL_STYLES = "//w:style";
diff --git a/plugins/org.eclipse.gendoc.documents.metadata/.classpath b/plugins/org.eclipse.gendoc.documents.metadata/.classpath
new file mode 100644
index 0000000..eca7bdb
--- /dev/null
+++ b/plugins/org.eclipse.gendoc.documents.metadata/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.gendoc.documents.metadata/.project b/plugins/org.eclipse.gendoc.documents.metadata/.project
new file mode 100644
index 0000000..b63a18d
--- /dev/null
+++ b/plugins/org.eclipse.gendoc.documents.metadata/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.gendoc.documents.metadata</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.gendoc.documents.metadata/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.gendoc.documents.metadata/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0c68a61
--- /dev/null
+++ b/plugins/org.eclipse.gendoc.documents.metadata/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/plugins/org.eclipse.gendoc.documents.metadata/META-INF/MANIFEST.MF b/plugins/org.eclipse.gendoc.documents.metadata/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..7245fd2
--- /dev/null
+++ b/plugins/org.eclipse.gendoc.documents.metadata/META-INF/MANIFEST.MF
@@ -0,0 +1,15 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Gendoc document metadata
+Bundle-SymbolicName: org.eclipse.gendoc.documents.metadata;singleton:=true
+Bundle-Version: 0.6.0.qualifier
+Bundle-Activator: org.eclipse.gendoc.documents.metadata.Activator
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.gendoc.process,
+ org.eclipse.gendoc.document.parser,
+ org.eclipse.gendoc.services,
+ org.eclipse.gendoc.documents
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ActivationPolicy: lazy
+Export-Package: org.eclipse.gendoc.documents.metadata
diff --git a/plugins/org.eclipse.gendoc.documents.metadata/build.properties b/plugins/org.eclipse.gendoc.documents.metadata/build.properties
new file mode 100644
index 0000000..e9863e2
--- /dev/null
+++ b/plugins/org.eclipse.gendoc.documents.metadata/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               plugin.xml
diff --git a/plugins/org.eclipse.gendoc.documents.metadata/plugin.xml b/plugins/org.eclipse.gendoc.documents.metadata/plugin.xml
new file mode 100644
index 0000000..e0671cc
--- /dev/null
+++ b/plugins/org.eclipse.gendoc.documents.metadata/plugin.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+   <extension
+         point="org.eclipse.gendoc.serviceTypes">
+      <serviceType
+            id="IPropertyDocumentService"
+            interface="org.eclipse.gendoc.documents.metadata.IDocumentMetadataService">
+      </serviceType>
+   </extension>
+   <extension
+         point="org.eclipse.gendoc.services">
+      <service
+            class="org.eclipse.gendoc.documents.metadata.impl.DocumentMetadataServiceFactory"
+            default="true"
+            id="PropertyDocumentServiceFactory"
+            priority="10"
+            serviceType="IPropertyDocumentService">
+      </service>
+   </extension>
+   <extension
+         point="org.eclipse.gendoc.processes">
+      <process
+            id="DocumentProperties"
+            label="DocumentProperties"
+            parallel="false"
+            priority="NORMAL"
+            processor="org.eclipse.gendoc.documents.metadata.impl.DocumentMetadataProcess">
+         <successor
+               ref="save">
+         </successor>
+         <predecessor
+               ref="generate">
+         </predecessor>
+      </process>
+   </extension>  
+</plugin>
diff --git a/plugins/org.eclipse.gendoc.documents.metadata/pom.xml b/plugins/org.eclipse.gendoc.documents.metadata/pom.xml
new file mode 100644
index 0000000..66e4e66
--- /dev/null
+++ b/plugins/org.eclipse.gendoc.documents.metadata/pom.xml
@@ -0,0 +1,12 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.eclipse.gendoc</groupId>
+    <artifactId>parent</artifactId>
+    <relativePath>../../pom.xml</relativePath>
+    <version>0.6.0-SNAPSHOT</version>
+  </parent>
+  
+  <artifactId>org.eclipse.gendoc.documents.metadata</artifactId>
+  <packaging>eclipse-plugin</packaging>
+</project>
\ No newline at end of file
diff --git a/plugins/org.eclipse.gendoc.documents.metadata/src/org/eclipse/gendoc/documents/metadata/Activator.java b/plugins/org.eclipse.gendoc.documents.metadata/src/org/eclipse/gendoc/documents/metadata/Activator.java
new file mode 100644
index 0000000..3b786dc
--- /dev/null
+++ b/plugins/org.eclipse.gendoc.documents.metadata/src/org/eclipse/gendoc/documents/metadata/Activator.java
@@ -0,0 +1,50 @@
+package org.eclipse.gendoc.documents.metadata;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+	// The plug-in ID
+	public static final String PLUGIN_ID = "org.eclipse.gendoc.documents.metadata"; //$NON-NLS-1$
+
+	// The shared instance
+	private static Activator plugin;
+	
+	/**
+	 * The constructor
+	 */
+	public Activator() {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+		plugin = this;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+	 */
+	public void stop(BundleContext context) throws Exception {
+		plugin = null;
+		super.stop(context);
+	}
+
+	/**
+	 * Returns the shared instance
+	 *
+	 * @return the shared instance
+	 */
+	public static Activator getDefault() {
+		return plugin;
+	}
+
+}
diff --git a/plugins/org.eclipse.gendoc.documents.metadata/src/org/eclipse/gendoc/documents/metadata/IDocumentMetadataService.java b/plugins/org.eclipse.gendoc.documents.metadata/src/org/eclipse/gendoc/documents/metadata/IDocumentMetadataService.java
new file mode 100644
index 0000000..cd8206f
--- /dev/null
+++ b/plugins/org.eclipse.gendoc.documents.metadata/src/org/eclipse/gendoc/documents/metadata/IDocumentMetadataService.java
@@ -0,0 +1,61 @@
+/*****************************************************************************
+ * (c) Copyright 2016 Telefonaktiebolaget LM Ericsson
+ *
+ *    
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *  Antonio Campesino (Ericsson) antonio.campesino.robles@ericsson.com - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.gendoc.documents.metadata;
+
+import java.util.List;
+
+import org.eclipse.gendoc.document.parser.documents.Document;
+import org.eclipse.gendoc.services.IService;
+/**
+ * The Interface IDocumentMetadataService provides methods to 
+ * access the metadata information in a {@link Document}. 
+ */
+public interface IDocumentMetadataService extends IService {
+	
+	/**
+	 * Gets the metadata properties.
+	 *
+	 * @param doc a {@link Document} with the the metadata properties.
+	 * @return a {@link List} containing the name of the metadata 
+	 *         properties. 
+	 */
+	public List<String> getMetadataProperties(Document doc);
+	
+	/**
+	 * Gets the string representation of the value of a metadata property 
+	 * in the document
+	 *
+	 * @param doc a {@link Document} with the the metadata properties.
+	 * @param propertyId a {@link String} identifying metadata property to access
+	 * @return the metadata value
+	 */
+	public String getMetadataValue(Document doc, String propertyId);
+	
+	/**
+	 * Sets the metadata value.
+	 *
+	 * @param doc a {@link Document} with the the metadata properties.
+	 * @param propertyId a {@link String} identifying metadata property to 
+	 *                   set the value.
+	 * @param value the string representation of the value of the metadata property.
+	 */
+	public void setMetadataValue(Document doc, String propertyId, String value);
+	
+	/**
+	 * Save the metadata in the document
+	 * 
+	 * @param doc a {@link Document} with the the metadata properties.
+	 */
+	public void saveMetadata(Document doc);
+}
diff --git a/plugins/org.eclipse.gendoc.documents.metadata/src/org/eclipse/gendoc/documents/metadata/impl/DocumentMetadataProcess.java b/plugins/org.eclipse.gendoc.documents.metadata/src/org/eclipse/gendoc/documents/metadata/impl/DocumentMetadataProcess.java
new file mode 100644
index 0000000..eedd370
--- /dev/null
+++ b/plugins/org.eclipse.gendoc.documents.metadata/src/org/eclipse/gendoc/documents/metadata/impl/DocumentMetadataProcess.java
@@ -0,0 +1,121 @@
+/*****************************************************************************
+ * (c) Copyright 2016 Telefonaktiebolaget LM Ericsson
+ *
+ *    
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *  Antonio Campesino (Ericsson) antonio.campesino.robles@ericsson.com - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.gendoc.documents.metadata.impl;
+
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.gendoc.document.parser.documents.Document;
+import org.eclipse.gendoc.document.parser.documents.Document.CONFIGURATION;
+import org.eclipse.gendoc.documents.metadata.IDocumentMetadataService;
+import org.eclipse.gendoc.process.AbstractStepProcess;
+import org.eclipse.gendoc.services.GendocServices;
+import org.eclipse.gendoc.services.IRegistryService;
+import org.eclipse.gendoc.services.exception.GenDocException;
+import org.eclipse.gendoc.services.exception.InvalidTemplateParameterException;
+
+/**
+ * The Class DocumentMetadataProcess implements the process that inject configuration parameters or 
+ * values defined in the {@link IRegistryService} in the metadata properties values.<br/>
+ * Any string of the type ${&lt;key&gt;} in the value of a metadata property, will be replaced with the
+ * value of the attribute with name equal to &lt;key&gt; in the {@link IRegistryService}. In order to be able to
+ * extract information from the model and make it available in the {@link IRegistryService} using the
+ * <code>gPut(...)</code> query, the process runs after the 'generate' process before save the 
+ * output document.     
+ */
+public class DocumentMetadataProcess extends AbstractStepProcess {
+	 
+	/** The pattern param. */
+	private static Pattern PATTERN_PARAM = Pattern.compile("\\$\\{[a-zA-Z0-9_]+\\}");
+	 
+	 /**
+	 * Instantiates a new document metadata process.
+	 */
+	public DocumentMetadataProcess() {
+		// TODO Auto-generated constructor stub
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gendoc.process.AbstractStepProcess#step(org.eclipse.gendoc.document.parser.documents.Document)
+	 */
+	@Override
+	protected void step(Document document) throws GenDocException {
+		if (document == null) {
+			this.worked(1);
+			return;
+		}
+
+		do {
+			if (document.getXMLParser() == null || document.getXMLParser().getKind() != CONFIGURATION.metadata)
+				continue;
+
+			IDocumentMetadataService propertyService = ((IDocumentMetadataService)GendocServices.getDefault().getService(IDocumentMetadataService.class));
+			if (propertyService != null) {
+				boolean modify = false;
+				List<String> propertyNames = propertyService.getMetadataProperties(document);
+				for (String prop : propertyNames) {
+					String value = propertyService.getMetadataValue(document, prop);
+					String newValue = replaceValue(value);
+					if (newValue != null && newValue.equals(value)) {
+						continue;
+					}
+					propertyService.setMetadataValue(document, prop, newValue);
+					modify = true;
+				}
+				if (modify) {
+					propertyService.saveMetadata(document);
+				}
+				
+			}		
+		} while (document.jumpToNextFile());
+		
+		document.getXMLParser().setCurrentNode(null);
+		this.worked(1);
+	}
+	
+    /**
+	 * Replace the string in the form ${&lt;key&gt;} with the  corresponding value of the <key> 
+	 * entry in the {@link IRegistryService} if the entry contains a {@link String} value.
+	 *
+	 * @param value the input string with the ${&lt;key&gt;} strings to be replaced
+	 * @return the output string with the replaced content.
+	 */
+    public String replaceValue(String value) 
+    {
+        if (value == null) {
+            return null;
+        }
+		
+        IRegistryService regService = ((IRegistryService)GendocServices.getDefault().getService(IRegistryService.class));
+        Matcher m = PATTERN_PARAM.matcher(value);
+        StringBuffer buffer = new StringBuffer();
+        int index = 0; // Current index
+        while (m.find())
+        {
+            buffer.append(value.substring(index, m.start()));
+            String paramName = value.substring(m.start() + 2, m.end() - 1);
+            Object objRegValue = regService.get(paramName);
+            if (objRegValue instanceof String)
+            {
+            	buffer.append(objRegValue);
+            } else {
+            	buffer.append("<<Cannot resolve parameter '"+paramName+"' in the registry>>");
+            }
+            index = m.end();
+        }
+        buffer.append(value.substring(index, value.length()));
+        return buffer.toString();
+    }
+}
diff --git a/plugins/org.eclipse.gendoc.documents.metadata/src/org/eclipse/gendoc/documents/metadata/impl/DocumentMetadataServiceFactory.java b/plugins/org.eclipse.gendoc.documents.metadata/src/org/eclipse/gendoc/documents/metadata/impl/DocumentMetadataServiceFactory.java
new file mode 100644
index 0000000..19d462b
--- /dev/null
+++ b/plugins/org.eclipse.gendoc.documents.metadata/src/org/eclipse/gendoc/documents/metadata/impl/DocumentMetadataServiceFactory.java
@@ -0,0 +1,63 @@
+/*****************************************************************************
+ * (c) Copyright 2016 Telefonaktiebolaget LM Ericsson
+ *
+ *    
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *  Antonio Campesino (Ericsson) antonio.campesino.robles@ericsson.com - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.gendoc.documents.metadata.impl;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.core.runtime.IExecutableExtensionFactory;
+import org.eclipse.gendoc.documents.IDocumentService;
+import org.eclipse.gendoc.documents.metadata.IDocumentMetadataService;
+import org.eclipse.gendoc.services.GendocServices;
+
+/**
+ * A factory for creating DocumentMetadataService objects.
+ */
+public class DocumentMetadataServiceFactory implements IExecutableExtensionFactory, IExecutableExtension {
+
+	/**
+	 * Instantiates a new document metadata service factory.
+	 */
+	public DocumentMetadataServiceFactory() {
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
+	 */
+	@Override
+	public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
+	}
+
+	/**
+	 * It returns a {@link IDocumentMetadataService} for the current IDocumentService.<br/>
+	 * 
+	 * @return a @{IDocumentMetadataService} if the current {@link IDocumentService} is not 
+	 *         implementing @{IDocumentMetadataService}, null otherwise.
+	 *         
+	 */
+	@Override
+	public Object create() throws CoreException {
+		IDocumentService service = null;
+		try {
+			service = ((IDocumentService)GendocServices.getDefault().getService(IDocumentService.class));
+			if (service instanceof IDocumentMetadataService)
+				return service;
+						
+			return null;
+		} catch (Exception e) {
+			throw new IllegalStateException("Document service cannot be initialized.", e);
+		}
+	}
+
+}
diff --git a/plugins/org.eclipse.gendoc.documents/src/org/eclipse/gendoc/documents/impl/DocumentManager.java b/plugins/org.eclipse.gendoc.documents/src/org/eclipse/gendoc/documents/impl/DocumentManager.java
index c9734c5..4c80063 100644
--- a/plugins/org.eclipse.gendoc.documents/src/org/eclipse/gendoc/documents/impl/DocumentManager.java
+++ b/plugins/org.eclipse.gendoc.documents/src/org/eclipse/gendoc/documents/impl/DocumentManager.java
@@ -105,6 +105,7 @@
 		result.put(CONFIGURATION.content, true);
 		result.put(CONFIGURATION.header, true);
 		result.put(CONFIGURATION.footer, true);
+		result.put(CONFIGURATION.metadata, true);
 		return result;
 	}
 
diff --git a/plugins/org.eclipse.gendoc.services.docx/META-INF/MANIFEST.MF b/plugins/org.eclipse.gendoc.services.docx/META-INF/MANIFEST.MF
index 79ca2e3..7df1ece 100644
--- a/plugins/org.eclipse.gendoc.services.docx/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.gendoc.services.docx/META-INF/MANIFEST.MF
@@ -10,7 +10,8 @@
  org.eclipse.gendoc.documents,
  org.eclipse.gendoc.services,
  org.eclipse.gendoc.tags,
- org.eclipse.gendoc.tags.handlers
+ org.eclipse.gendoc.tags.handlers,
+ org.eclipse.gendoc.documents.metadata
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
 Bundle-ActivationPolicy: lazy
 Export-Package: org.eclipse.gendoc.services.docx
diff --git a/plugins/org.eclipse.gendoc.services.docx/src/org/eclipse/gendoc/services/docx/DOCXDocumentService.java b/plugins/org.eclipse.gendoc.services.docx/src/org/eclipse/gendoc/services/docx/DOCXDocumentService.java
index 7a712fb..1d52450 100644
--- a/plugins/org.eclipse.gendoc.services.docx/src/org/eclipse/gendoc/services/docx/DOCXDocumentService.java
+++ b/plugins/org.eclipse.gendoc.services.docx/src/org/eclipse/gendoc/services/docx/DOCXDocumentService.java
@@ -15,7 +15,10 @@
 
 import java.io.File;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Stack;
 import java.util.regex.Pattern;
 
@@ -30,21 +33,25 @@
 import javax.xml.transform.stream.StreamResult;
 
 import org.eclipse.gendoc.document.parser.documents.Document;
+import org.eclipse.gendoc.document.parser.documents.Document.CONFIGURATION;
 import org.eclipse.gendoc.document.parser.documents.docx.DocxDocument;
 import org.eclipse.gendoc.document.parser.documents.docx.DocxNamespaceContext;
 import org.eclipse.gendoc.documents.IAdditionalResourceService;
 import org.eclipse.gendoc.documents.IMimeHtmlService;
 import org.eclipse.gendoc.documents.XMLDocumentService;
+import org.eclipse.gendoc.documents.metadata.IDocumentMetadataService;
 import org.eclipse.gendoc.services.exception.DocumentServiceException;
 import org.eclipse.gendoc.services.exception.InvalidContentException;
 import org.eclipse.gendoc.tags.handlers.impl.RegisteredTags;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
 /**
  * Specific service for DOCX document management
  */
-public class DOCXDocumentService extends XMLDocumentService
+public class DOCXDocumentService extends XMLDocumentService implements IDocumentMetadataService
 {
     /** Service for additional resources */
     IAdditionalResourceService additionalResourceService;
@@ -54,6 +61,9 @@
 
 	private String serviceId;
 	
+	/** The Constant TRANSFORMER_FACTORY create a XML transformation . */
+	private static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance();
+	
 	public DOCXDocumentService()
     {
         super();
@@ -344,4 +354,135 @@
 		return formatted;
 	}
 
+	@Override
+	public List<String> getMetadataProperties(Document doc) {
+		if (getDocument() == null) {
+			setDocument(doc);
+		}
+
+		String docName = doc.getXMLParser().getXmlFile().getName(); 
+		ArrayList<String> res = new ArrayList<String>(); 
+		if (docName.equals("custom.xml")) {
+			NodeList nl = doc.getXMLParser().getNodesFromXPathExpression(
+				"//vt:lpwstr", 
+				new DocxNamespaceContextEx(new String[] {
+					"def",  "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties",
+					"vt","http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"}));
+			for (int i=0; i<nl.getLength(); i++) {
+				Element e = (Element)nl.item(i);
+				res.add(((Element)e.getParentNode()).getAttribute("name"));				
+			}
+		} else if (docName.equals("core.xml")) {
+			NodeList nl = doc.getXMLParser().getNodesFromXPathExpression(
+					"/cp:coreProperties/*", 
+					new DocxNamespaceContextEx(new String[] {
+							"cp", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties",
+							"dc", "http://purl.org/dc/elements/1.1/", 
+							"dcterms", "http://purl.org/dc/terms/",
+							"dcmitype","http://purl.org/dc/dcmitype/"}));
+			for (int i=0; i<nl.getLength(); i++) {
+				Element e = (Element)nl.item(i);
+				res.add(e.getPrefix()+":"+e.getLocalName());				
+			}
+		}
+		return res;
+	}
+
+	@Override
+	public String getMetadataValue(Document doc, String propertyId) {
+		Node n = getPropertyNode(doc, propertyId);
+		if (n instanceof Element)
+			return n.getTextContent();
+		else if (n instanceof Attr) {
+			return ((Attr) n).getValue();
+		} else {
+			return null;
+		}
+	}
+
+	@Override
+	public void setMetadataValue(Document doc, String propertyId, String value) {
+		Node n = getPropertyNode(doc, propertyId);
+		if (n instanceof Element)
+			n.setTextContent(value);
+		else if (n instanceof Attr) {
+			((Attr) n).setValue(value);
+		} 
+	}		
+
+	@Override
+	public void saveMetadata(Document doc) {
+		try {
+			if (doc.getXMLParser().getKind() != CONFIGURATION.metadata)
+				return;
+			File f = doc.getXMLParser().getXmlFile();
+			Transformer t = TRANSFORMER_FACTORY.newTransformer();
+			t.setOutputProperty(OutputKeys.STANDALONE, "no");
+			t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+			t.transform(new DOMSource(doc.getXMLParser().getDocument()), new StreamResult(f));
+		} catch (TransformerException e) {
+			throw new RuntimeException(e);
+		} 
+	}
+
+	private Node getPropertyNode(Document doc, String propertyId) {
+		String docName = doc.getXMLParser().getXmlFile().getName(); 
+		if (docName.equals("custom.xml")) {
+			NodeList nl = doc.getXMLParser().getNodesFromXPathExpression(
+				"//def:property[@name='"+propertyId+"']/vt:lpwstr", 
+				new DocxNamespaceContextEx(new String[] {
+					"def",  "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties",
+					"vt","http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"}));
+			if (nl.getLength() > 0) {
+				return nl.item(0);
+			}
+		} else if (docName.equals("core.xml")) {
+			NodeList nl = doc.getXMLParser().getNodesFromXPathExpression(
+					"/cp:coreProperties/"+propertyId, 
+					new DocxNamespaceContextEx(new String[] {
+							"cp", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties",
+							"dc", "http://purl.org/dc/elements/1.1/", 
+							"dcterms", "http://purl.org/dc/terms/",
+							"dcmitype","http://purl.org/dc/dcmitype/"}));
+			if (nl.getLength() > 0)
+				return nl.item(0);
+		}
+		return null;
+	}
+	
+	
+	
+	private static class DocxNamespaceContextEx implements NamespaceContext {
+		public DocxNamespaceContextEx(String[] mapping) {
+			this.mapping = new HashMap<String,String>(2);
+			for (int i=0; i<mapping.length; i+=2) {
+				this.mapping.put(mapping[i], mapping[i+1]);
+			}
+		}
+
+		@Override
+		public String getNamespaceURI(String prefix) {
+			String uri = mapping.get(prefix);
+			if (uri == null)
+				uri = "";
+			return uri;
+		}
+		
+		@Override
+ 	    public String getPrefix(String uri)
+ 	    {
+ 	        throw new UnsupportedOperationException();
+
+ 	    }
+
+		@SuppressWarnings("rawtypes")
+		@Override
+ 	    public Iterator getPrefixes(String uri)
+ 	    {
+ 	        throw new UnsupportedOperationException();
+
+ 	    }
+		
+		private Map<String, String> mapping; 
+	}	
 }
diff --git a/plugins/org.eclipse.gendoc.tags.html/META-INF/MANIFEST.MF b/plugins/org.eclipse.gendoc.tags.html/META-INF/MANIFEST.MF
index fa9248b..739f0bb 100644
--- a/plugins/org.eclipse.gendoc.tags.html/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.gendoc.tags.html/META-INF/MANIFEST.MF
@@ -13,7 +13,8 @@
  org.eclipse.gendoc.services.docx,
  org.eclipse.gendoc.tags,
  org.eclipse.gendoc.tags.handlers,
- org.eclipse.gendoc.process
+ org.eclipse.gendoc.process,
+ org.eclipse.gendoc.documents.metadata
 Bundle-ActivationPolicy: lazy
 Bundle-Activator: org.eclipse.gendoc.tags.html.Activator
 Bundle-ClassPath: lib/jtidy-04aug2000r7.jar,
diff --git a/pom.xml b/pom.xml
index 8868d5b..c3d11d1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,6 +15,7 @@
   	<module>plugins/org.eclipse.gendoc.bundle.acceleo.sirius</module>
   	<module>plugins/org.eclipse.gendoc.document.parser</module>
   	<module>plugins/org.eclipse.gendoc.documents</module>
+  	<module>plugins/org.eclipse.gendoc.documents.metadata</module>
   	<module>plugins/org.eclipse.gendoc.m2t</module>
   	<module>plugins/org.eclipse.gendoc.process</module>
   	<module>plugins/org.eclipse.gendoc.script.acceleo</module>