mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
ALF-17897: Should be able to Override or Augment Metadata Extractor Mappings via Global Properties
- Changed AbstractMappingMetadataExtracter to implement ApplicationContextAware - Added AbstractMappingMetadataExtracter.getRelevantGlobalProperties responsible for fetching the global properties relevant to the bean and component ('extract' or 'embed') - Separated AbstractMappingMetadataExtracter readMappingProperties and readEmbedMappingProperties into separate methods with arguments for entry set or Properties - Added AbstractMappingMetadataExtracter readGlobalExtractMappingProperties and readGlobalEmbedMappingProperties which get the relevant property entries from getRelevantGlobalProperties - Changed AbstractMappingMetadataExtracter init to call readGlobalExtractMappingProperties and readGlobalEmbedMappingProperties - Added testPropertyMappingGlobalOverride to MappingMetadataExtracterTest git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@47008 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -33,6 +33,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
@@ -55,6 +56,8 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.xmlbeans.impl.xb.xsdschema.All;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.extensions.surf.util.ISO8601DateFormat;
|
||||
|
||||
/**
|
||||
@@ -97,10 +100,13 @@ import org.springframework.extensions.surf.util.ISO8601DateFormat;
|
||||
* @author Jesper Steen Møller
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
abstract public class AbstractMappingMetadataExtracter implements MetadataExtracter, MetadataEmbedder, BeanNameAware
|
||||
abstract public class AbstractMappingMetadataExtracter implements MetadataExtracter, MetadataEmbedder, BeanNameAware, ApplicationContextAware
|
||||
{
|
||||
public static final String NAMESPACE_PROPERTY_PREFIX = "namespace.prefix.";
|
||||
private static final String ERR_TYPE_CONVERSION = "metadata.extraction.err.type_conversion";
|
||||
public static final String PROPERTY_PREFIX_METADATA = "metadata.";
|
||||
public static final String PROPERTY_COMPONENT_EXTRACT = ".extract.";
|
||||
public static final String PROPERTY_COMPONENT_EMBED = ".extract.";
|
||||
|
||||
protected static Log logger = LogFactory.getLog(AbstractMappingMetadataExtracter.class);
|
||||
|
||||
@@ -120,6 +126,7 @@ abstract public class AbstractMappingMetadataExtracter implements MetadataExtrac
|
||||
private boolean inheritDefaultEmbedMapping;
|
||||
private boolean enableStringTagging;
|
||||
private String beanName;
|
||||
private ApplicationContext applicationContext;
|
||||
private Properties properties;
|
||||
|
||||
/**
|
||||
@@ -390,6 +397,11 @@ abstract public class AbstractMappingMetadataExtracter implements MetadataExtrac
|
||||
return beanName;
|
||||
}
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
{
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Alfresco global properties.
|
||||
*/
|
||||
@@ -601,16 +613,92 @@ abstract public class AbstractMappingMetadataExtracter implements MetadataExtrac
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method to convert global properties to the Map form for the given
|
||||
* propertyComponent.
|
||||
* <p>
|
||||
* Mappings can be specified using the same method defined for
|
||||
* normal mapping properties files but with a prefix of
|
||||
* <code>metadata.extracter</code>, the extracter bean name, and the propertyComponent.
|
||||
* For example:
|
||||
*
|
||||
* metadata.extracter.TikaAuto.extract.namespace.prefix.my=http://DummyMappingMetadataExtracter
|
||||
* metadata.extracter.TikaAuto.extract.namespace.prefix.cm=http://www.alfresco.org/model/content/1.0
|
||||
* metadata.extracter.TikaAuto.extract.dc\:description=cm:description, my:customDescription
|
||||
*
|
||||
*/
|
||||
private Map<Object, Object> getRelevantGlobalProperties(String propertyComponent)
|
||||
{
|
||||
if (applicationContext == null)
|
||||
{
|
||||
logger.info("ApplicationContext not set");
|
||||
return null;
|
||||
}
|
||||
Properties globalProperties = (Properties) applicationContext.getBean("global-properties");
|
||||
if (globalProperties == null)
|
||||
{
|
||||
logger.info("Could not get global-properties");
|
||||
return null;
|
||||
}
|
||||
Map<Object, Object> relevantGlobalPropertiesMap =
|
||||
new HashMap<Object, Object>();
|
||||
String propertyPrefix = PROPERTY_PREFIX_METADATA + beanName + propertyComponent;
|
||||
for (Entry<Object, Object> globalEntry : globalProperties.entrySet())
|
||||
{
|
||||
if (((String) globalEntry.getKey()).startsWith(propertyPrefix))
|
||||
{
|
||||
relevantGlobalPropertiesMap.put(
|
||||
((String) globalEntry.getKey()).replace(propertyPrefix, ""),
|
||||
globalEntry.getValue());
|
||||
}
|
||||
}
|
||||
return relevantGlobalPropertiesMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method to convert global properties to the Map form for the given
|
||||
* propertyComponent.
|
||||
* <p>
|
||||
* Mappings can be specified using the same method defined for
|
||||
* normal mapping properties files but with a prefix of
|
||||
* <code>metadata.extracter</code>, the extracter bean name, and the extract component.
|
||||
* For example:
|
||||
*
|
||||
* metadata.extracter.TikaAuto.extract.namespace.prefix.my=http://DummyMappingMetadataExtracter
|
||||
* metadata.extracter.TikaAuto.extract.namespace.prefix.cm=http://www.alfresco.org/model/content/1.0
|
||||
* metadata.extracter.TikaAuto.extract.dc\:description=cm:description, my:customDescription
|
||||
*
|
||||
*/
|
||||
protected Map<String, Set<QName>> readGlobalExtractMappingProperties()
|
||||
{
|
||||
Map<Object, Object> relevantGlobalPropertiesMap = getRelevantGlobalProperties(PROPERTY_COMPONENT_EXTRACT);
|
||||
if (relevantGlobalPropertiesMap == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return readMappingProperties(relevantGlobalPropertiesMap.entrySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method to convert mapping properties to the Map form.
|
||||
*
|
||||
* @see #setMappingProperties(Properties)
|
||||
*/
|
||||
protected Map<String, Set<QName>> readMappingProperties(Properties mappingProperties)
|
||||
{
|
||||
return readMappingProperties(mappingProperties.entrySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method to convert mapping properties entries to the Map form.
|
||||
*
|
||||
* @see #setMappingProperties(Properties)
|
||||
*/
|
||||
private Map<String, Set<QName>> readMappingProperties(Set<Entry<Object, Object>> mappingPropertiesEntries)
|
||||
{
|
||||
Map<String, String> namespacesByPrefix = new HashMap<String, String>(5);
|
||||
// Get the namespaces
|
||||
for (Map.Entry<Object, Object> entry : mappingProperties.entrySet())
|
||||
for (Map.Entry<Object, Object> entry : mappingPropertiesEntries)
|
||||
{
|
||||
String propertyName = (String) entry.getKey();
|
||||
if (propertyName.startsWith(NAMESPACE_PROPERTY_PREFIX))
|
||||
@@ -622,7 +710,7 @@ abstract public class AbstractMappingMetadataExtracter implements MetadataExtrac
|
||||
}
|
||||
// Create the mapping
|
||||
Map<String, Set<QName>> convertedMapping = new HashMap<String, Set<QName>>(17);
|
||||
for (Map.Entry<Object, Object> entry : mappingProperties.entrySet())
|
||||
for (Map.Entry<Object, Object> entry : mappingPropertiesEntries)
|
||||
{
|
||||
String documentProperty = (String) entry.getKey();
|
||||
String qnamesStr = (String) entry.getValue();
|
||||
@@ -724,6 +812,32 @@ abstract public class AbstractMappingMetadataExtracter implements MetadataExtrac
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method to convert global mapping properties to the Map form.
|
||||
* <p>
|
||||
* Different from readGlobalExtractMappingProperties in that keys are the Alfresco QNames
|
||||
* and values are file metadata properties.
|
||||
* <p>
|
||||
* Mappings can be specified using the same method defined for
|
||||
* normal embed mapping properties files but with a prefix of
|
||||
* <code>metadata.extracter</code>, the extracter bean name, and the embed component.
|
||||
* For example:
|
||||
*
|
||||
* metadata.extracter.TikaAuto.embed.namespace.prefix.cm=http://www.alfresco.org/model/content/1.0
|
||||
* metadata.extracter.TikaAuto.embed.cm\:description=description
|
||||
*
|
||||
* @see #setMappingProperties(Properties)
|
||||
*/
|
||||
protected Map<QName, Set<String>> readGlobalEmbedMappingProperties()
|
||||
{
|
||||
Map<Object, Object> relevantGlobalPropertiesMap = getRelevantGlobalProperties(PROPERTY_COMPONENT_EMBED);
|
||||
if (relevantGlobalPropertiesMap == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return readEmbedMappingProperties(relevantGlobalPropertiesMap.entrySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method to convert mapping properties to the Map form.
|
||||
* <p>
|
||||
@@ -733,10 +847,23 @@ abstract public class AbstractMappingMetadataExtracter implements MetadataExtrac
|
||||
* @see #setMappingProperties(Properties)
|
||||
*/
|
||||
protected Map<QName, Set<String>> readEmbedMappingProperties(Properties mappingProperties)
|
||||
{
|
||||
return readEmbedMappingProperties(mappingProperties.entrySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method to convert mapping properties entries to the Map form.
|
||||
* <p>
|
||||
* Different from readMappingProperties in that keys are the Alfresco QNames
|
||||
* and values are file metadata properties.
|
||||
*
|
||||
* @see #setMappingProperties(Properties)
|
||||
*/
|
||||
private Map<QName, Set<String>> readEmbedMappingProperties(Set<Entry<Object, Object>> mappingPropertiesEntries)
|
||||
{
|
||||
Map<String, String> namespacesByPrefix = new HashMap<String, String>(5);
|
||||
// Get the namespaces
|
||||
for (Map.Entry<Object, Object> entry : mappingProperties.entrySet())
|
||||
for (Map.Entry<Object, Object> entry : mappingPropertiesEntries)
|
||||
{
|
||||
String propertyName = (String) entry.getKey();
|
||||
if (propertyName.startsWith(NAMESPACE_PROPERTY_PREFIX))
|
||||
@@ -748,7 +875,7 @@ abstract public class AbstractMappingMetadataExtracter implements MetadataExtrac
|
||||
}
|
||||
// Create the mapping
|
||||
Map<QName, Set<String>> convertedMapping = new HashMap<QName, Set<String>>(17);
|
||||
for (Map.Entry<Object, Object> entry : mappingProperties.entrySet())
|
||||
for (Map.Entry<Object, Object> entry : mappingPropertiesEntries)
|
||||
{
|
||||
String modelProperty = (String) entry.getKey();
|
||||
String metadataKeysString = (String) entry.getValue();
|
||||
@@ -855,6 +982,16 @@ abstract public class AbstractMappingMetadataExtracter implements MetadataExtrac
|
||||
}
|
||||
}
|
||||
|
||||
// Override with any extract mappings specified in global properties
|
||||
Map<String, Set<QName>> globalExtractMapping = readGlobalExtractMappingProperties();
|
||||
if (globalExtractMapping != null && globalExtractMapping.size() > 0)
|
||||
{
|
||||
for (String documentKey : globalExtractMapping.keySet())
|
||||
{
|
||||
mapping.put(documentKey, globalExtractMapping.get(documentKey));
|
||||
}
|
||||
}
|
||||
|
||||
// The configured mappings are empty, but there were default mappings
|
||||
if (mapping.size() == 0 && defaultMapping.size() > 0)
|
||||
{
|
||||
@@ -887,6 +1024,16 @@ abstract public class AbstractMappingMetadataExtracter implements MetadataExtrac
|
||||
}
|
||||
}
|
||||
|
||||
// Override with any embed mappings specified in global properties
|
||||
Map<QName, Set<String>> globalEmbedMapping = readGlobalEmbedMappingProperties();
|
||||
if (globalEmbedMapping != null && globalEmbedMapping.size() > 0)
|
||||
{
|
||||
for (QName modelProperty : globalEmbedMapping.keySet())
|
||||
{
|
||||
embedMapping.put(modelProperty, globalEmbedMapping.get(modelProperty));
|
||||
}
|
||||
}
|
||||
|
||||
// Done
|
||||
initialized = true;
|
||||
}
|
||||
|
@@ -29,6 +29,7 @@ import java.util.Set;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.content.ContentMinimalContextTestSuite;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.content.filestore.FileContentReader;
|
||||
import org.alfresco.repo.content.metadata.MetadataExtracter.OverwritePolicy;
|
||||
@@ -36,6 +37,7 @@ import org.alfresco.repo.content.transform.AbstractContentTransformerTest;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.content.metadata.AbstractMappingMetadataExtracter
|
||||
@@ -131,6 +133,30 @@ public class MappingMetadataExtracterTest extends TestCase
|
||||
assertTrue(destination.containsKey(DummyMappingMetadataExtracter.QNAME_A2));
|
||||
}
|
||||
|
||||
public void testPropertyMappingGlobalOverride() throws Exception
|
||||
{
|
||||
String propertyPrefix = AbstractMappingMetadataExtracter.PROPERTY_PREFIX_METADATA +
|
||||
DummyMappingMetadataExtracter.EXTRACTER_NAME +
|
||||
AbstractMappingMetadataExtracter.PROPERTY_COMPONENT_EXTRACT;
|
||||
|
||||
ApplicationContext ctx = ContentMinimalContextTestSuite.getContext();
|
||||
Properties globalProperties = (Properties) ctx.getBean("global-properties");
|
||||
globalProperties.setProperty(
|
||||
propertyPrefix + "namespace.prefix.my",
|
||||
DummyMappingMetadataExtracter.NAMESPACE_MY);
|
||||
globalProperties.setProperty(
|
||||
propertyPrefix + DummyMappingMetadataExtracter.PROP_A,
|
||||
" my:a1, my:a2, my:c ");
|
||||
|
||||
extracter.setApplicationContext(ctx);
|
||||
|
||||
extracter.register();
|
||||
// Only mapped 'a'
|
||||
destination.clear();
|
||||
extracter.extract(reader, destination);
|
||||
assertEquals(DummyMappingMetadataExtracter.VALUE_A, destination.get(DummyMappingMetadataExtracter.QNAME_C));
|
||||
}
|
||||
|
||||
public void testPropertyMappingMerge() throws Exception
|
||||
{
|
||||
Properties props = new Properties();
|
||||
@@ -254,6 +280,7 @@ public class MappingMetadataExtracterTest extends TestCase
|
||||
public static final String VALUE_D = "DDD";
|
||||
public static final String VALUE_IMG = "IMAGE";
|
||||
|
||||
public static final String EXTRACTER_NAME = "extracter.Dummy";
|
||||
public static final String NAMESPACE_MY = "http://DummyMappingMetadataExtracter";
|
||||
public static final QName QNAME_A1 = QName.createQName(NAMESPACE_MY, "a1");
|
||||
public static final QName QNAME_A2 = QName.createQName(NAMESPACE_MY, "a2");
|
||||
@@ -278,6 +305,7 @@ public class MappingMetadataExtracterTest extends TestCase
|
||||
{
|
||||
super(MIMETYPES);
|
||||
initCheck = false;
|
||||
setBeanName(EXTRACTER_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Reference in New Issue
Block a user