From b031ba0ded4db9589d9f69553113aa7f923823c6 Mon Sep 17 00:00:00 2001 From: Alan Davis Date: Fri, 22 Feb 2013 00:51:25 +0000 Subject: [PATCH] ALF-14306 Add priorities to transformers - properties with .mimtypes. in their name win over those with .extensions (for Ray) - extension and minetype expressions now only support the * wildcard git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@46950 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../transform/TransformerConfigLimits.java | 4 +- .../transform/TransformerConfigProperty.java | 12 +- .../transform/TransformerConfigSupported.java | 4 +- .../TransformerPropertyNameExtractor.java | 239 +++++++++++++----- .../TransformerPropertyNameExtractorTest.java | 82 ++++++ 5 files changed, 269 insertions(+), 72 deletions(-) create mode 100644 source/java/org/alfresco/repo/content/transform/TransformerPropertyNameExtractorTest.java diff --git a/source/java/org/alfresco/repo/content/transform/TransformerConfigLimits.java b/source/java/org/alfresco/repo/content/transform/TransformerConfigLimits.java index e32e47fd93..9f03ef00ca 100644 --- a/source/java/org/alfresco/repo/content/transform/TransformerConfigLimits.java +++ b/source/java/org/alfresco/repo/content/transform/TransformerConfigLimits.java @@ -56,14 +56,14 @@ public class TransformerConfigLimits extends TransformerPropertyNameExtractor limits = new HashMap>(); // Gets all the transformer, source and target combinations in properties that define limits. - Collection transformerNamesAndExt = + Collection properties = getTransformerSourceTargetValues(LIMIT_SUFFIXES, true, subsystem, mimetypeService); // Add the system wide default just in case it is not included, as we always need this one TransformationOptionLimits options = getOrCreateTransformerOptionLimits(DEFAULT_TRANSFORMER, ANY, ANY); // Populate the transformer limits - for (TransformerSourceTargetValue property: transformerNamesAndExt) + for (TransformerSourceTargetSuffixValue property: properties) { options = getOrCreateTransformerOptionLimits(property.transformerName, property.sourceMimetype, property.targetMimetype); diff --git a/source/java/org/alfresco/repo/content/transform/TransformerConfigProperty.java b/source/java/org/alfresco/repo/content/transform/TransformerConfigProperty.java index aac1b5dfef..d6caca388c 100644 --- a/source/java/org/alfresco/repo/content/transform/TransformerConfigProperty.java +++ b/source/java/org/alfresco/repo/content/transform/TransformerConfigProperty.java @@ -55,19 +55,19 @@ public class TransformerConfigProperty extends TransformerPropertyNameExtractor // Gets all the transformer, source and target combinations in properties that define // this value. - Collection transformerNamesAndMimetypes = + Collection properties = getTransformerSourceTargetValues(Collections.singletonList(suffix), true, subsystem, mimetypeService); // Add the system wide default if it does not exist, as we always need this one - TransformerSourceTargetValue transformerSourceTargetValue = - new TransformerSourceTargetValue(DEFAULT_TRANSFORMER, ANY, ANY, defaultValue, suffix, mimetypeService); - if (transformerNamesAndMimetypes.contains(transformerSourceTargetValue.key())) + TransformerSourceTargetSuffixValue transformerSourceTargetValue = + new TransformerSourceTargetSuffixValue(DEFAULT_TRANSFORMER, ANY, ANY, suffix, defaultValue, mimetypeService); + if (properties.contains(transformerSourceTargetValue.key())) { - transformerNamesAndMimetypes.add(transformerSourceTargetValue); + properties.add(transformerSourceTargetValue); } // Populate the transformer values - for (TransformerSourceTargetValue property: transformerNamesAndMimetypes) + for (TransformerSourceTargetSuffixValue property: properties) { DoubleMap mimetypeLimits = this.values.get(property.transformerName); if (mimetypeLimits == null) diff --git a/source/java/org/alfresco/repo/content/transform/TransformerConfigSupported.java b/source/java/org/alfresco/repo/content/transform/TransformerConfigSupported.java index a785321bff..f8b2585a3c 100644 --- a/source/java/org/alfresco/repo/content/transform/TransformerConfigSupported.java +++ b/source/java/org/alfresco/repo/content/transform/TransformerConfigSupported.java @@ -56,12 +56,12 @@ public class TransformerConfigSupported extends TransformerPropertyNameExtractor supported = new HashMap(); // Gets all the supported and unsupported transformer, source and target combinations - Collection transformerNamesAndMimetypes = + Collection properties = getTransformerSourceTargetValues(Collections.singletonList(SUPPORTED), false, subsystem, mimetypeService); // Populate the transformer values - for (TransformerSourceTargetValue property: transformerNamesAndMimetypes) + for (TransformerSourceTargetSuffixValue property: properties) { SupportedAndUnsupportedTransformations supportedBytransformer = this.supported.get(property.transformerName); if (supportedBytransformer == null) diff --git a/source/java/org/alfresco/repo/content/transform/TransformerPropertyNameExtractor.java b/source/java/org/alfresco/repo/content/transform/TransformerPropertyNameExtractor.java index 057084d618..8224c60249 100644 --- a/source/java/org/alfresco/repo/content/transform/TransformerPropertyNameExtractor.java +++ b/source/java/org/alfresco/repo/content/transform/TransformerPropertyNameExtractor.java @@ -24,6 +24,7 @@ import static org.alfresco.repo.content.transform.TransformerConfig.PREFIX; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -58,11 +59,11 @@ public abstract class TransformerPropertyNameExtractor * @param subsystem that provides the properties * @param mimetypeService */ - protected Collection getTransformerSourceTargetValues(Collection suffixes, + protected Collection getTransformerSourceTargetValues(Collection suffixes, boolean includeSummary, ChildApplicationContextFactory subsystem, MimetypeService mimetypeService) { - Map, TransformerSourceTargetValue> TransformerSourceTargetValues = - new HashMap, TransformerSourceTargetValue>(); + Map transformerSourceTargetSuffixValues = + new HashMap(); for (String propertyName: subsystem.getPropertyNames()) { @@ -87,35 +88,31 @@ public abstract class TransformerPropertyNameExtractor if (ext.length == 2) { name = name.substring(0, i); - if (separator == TransformerConfig.EXTENSIONS) + List sourceExtensions = (separator == TransformerConfig.EXTENSIONS) + ? getMatchingExtensionsFromExtensions(ext[0], mimetypeService) + : getMatchingExtensionsFromMimetypes( ext[0], mimetypeService); + List targetExtensions = (separator == TransformerConfig.EXTENSIONS) + ? getMatchingExtensionsFromExtensions(ext[1], mimetypeService) + : getMatchingExtensionsFromMimetypes( ext[1], mimetypeService); + for (String sourceExt : sourceExtensions) { - addTransformerSourceTargetValue(TransformerSourceTargetValues, - false, name, ext[0], ext[1], value, suffix, mimetypeService); - } - else if (separator == TransformerConfig.MIMETYPES) - { - List sourceExtensions = getMatchingExtensions(ext[0], mimetypeService); - List targetExtensions = getMatchingExtensions(ext[1], mimetypeService); - for (String sourceExt : sourceExtensions) + for (String targetExt : targetExtensions) { - for (String targetExt : targetExtensions) - { - addTransformerSourceTargetValue(TransformerSourceTargetValues, - true, name, sourceExt, targetExt, value, - suffix, mimetypeService); - } + addTransformerSourceTargetValue(transformerSourceTargetSuffixValues, + (separator == TransformerConfig.MIMETYPES), + name, sourceExt, targetExt, suffix, + value, mimetypeService); } } break suffixesLoop; } } - } if (!separatorMatch && includeSummary) { - addTransformerSourceTargetValue(TransformerSourceTargetValues, false, name, ANY, ANY, - value, suffix, mimetypeService); + addTransformerSourceTargetValue(transformerSourceTargetSuffixValues, false, name, ANY, ANY, + suffix, value, mimetypeService); break suffixesLoop; } } @@ -123,27 +120,27 @@ public abstract class TransformerPropertyNameExtractor } } - return TransformerSourceTargetValues.values(); + return transformerSourceTargetSuffixValues.values(); } /** - * Optionally adds a new TransformerSourceTargetValue. If the supplied value is not constructed from - * from a property that uses a regular expression against a mimetype, a new value is always added and - * will replace any existing value. If not, the value is only added if there is not a current value. - * In other words properties that include extensions win out over those that use mimetypes. + * Optionally adds a new TransformerSourceTargetValue. If the supplied value is constructed from + * from a mimetypes property a new value is always added and will replace any existing value. If + * from an extensions property the value is only added if there is not a current value. + * In other words properties that include mimetypes win out over those that use extensions. */ private void addTransformerSourceTargetValue( - Map, TransformerSourceTargetValue> transformerSourceTargetValues, - boolean mimetypeProperty, String name, String sourceExt, String targetExt, String value, - String suffix, MimetypeService mimetypeService) + Map transformerSourceTargetSuffixValues, + boolean mimetypeProperty, String name, String sourceExt, String targetExt, String suffix, + String value, MimetypeService mimetypeService) { - TransformerSourceTargetValue transformerSourceTargetValue = - new TransformerSourceTargetValue(name, sourceExt, targetExt, value, suffix, mimetypeService); - Triple key = transformerSourceTargetValue.key(); + TransformerSourceTargetSuffixValue transformerSourceTargetSuffixValue = + new TransformerSourceTargetSuffixValue(name, sourceExt, targetExt, suffix, value, mimetypeService); + TransformerSourceTargetSuffixKey key = transformerSourceTargetSuffixValue.key(); - if (!mimetypeProperty || !transformerSourceTargetValues.containsKey(key)) + if (mimetypeProperty || !transformerSourceTargetSuffixValues.containsKey(key)) { - transformerSourceTargetValues.put(key, transformerSourceTargetValue); + transformerSourceTargetSuffixValues.put(key, transformerSourceTargetSuffixValue); } } @@ -152,7 +149,7 @@ public abstract class TransformerPropertyNameExtractor * that is not escaped (preceded by a back slash '\'). * This is to allow regular expressions to be used for mimetypes. */ - private String[] splitExt(String extensions) + static String[] splitExt(String extensions) { String[] ext = NO_EXT_MATCH; Matcher matcher = EXTENSIONS_SEPARATOR.matcher(extensions); @@ -165,28 +162,39 @@ public abstract class TransformerPropertyNameExtractor } return ext; } + + /** + * Returns a regex Pattern for the supplied expression where '*' represents zero + * or more characters. + */ + static Pattern pattern(String expression) + { + // Turn the pattern into a regular expression where any special regex + // characters have no meaning and then get any * values to represent + // zero or more chars. + String regex = Pattern.quote(expression).replaceAll("\\*", "\\\\E.*\\\\Q"); + return Pattern.compile(regex); + } /** - * Gets the extensions of the mimetypes which match the given configMimetype from the given - * mimetypeService. - *

- * If the given mimetype string contains one or more wildcards (*) in the subtype, the string - * is converted to a regular expression and the extensions of the mimetypes which match are returned. - *

- * If the given mimetype string has no wildcards a list with only the given - * mimetype's extension is returned. - * - * @param mimetypeWildcardRegex + * Gets the extensions of the mimetypes that match the given expression. + * However if the expression is "*", only the ANY ("*") extension is returned. + * @param expression which may contain '*' to represent zero or more characters. * @param mimetypeService - * @return the list of extensions of mimetypes which match + * @return the list of extensions of mimetypes that match */ - private List getMatchingExtensions( - String mimetypeWildcardRegex, MimetypeService mimetypeService) + private List getMatchingExtensionsFromMimetypes( + String expression, MimetypeService mimetypeService) { + if (ANY.equals(expression)) + { + return Collections.singletonList(ANY); + } + Pattern pattern = pattern(expression); List matchingMimetypes = new ArrayList(1); for (String mimetype : mimetypeService.getMimetypes()) { - if (mimetype.matches(mimetypeWildcardRegex)) + if (pattern.matcher(mimetype).matches()) { String ext = mimetypeService.getExtension(mimetype); matchingMimetypes.add(ext); @@ -194,40 +202,139 @@ public abstract class TransformerPropertyNameExtractor } return matchingMimetypes; } + + /** + * Gets the extensions that match the given expression. Only the main extension + * of each mimetype is checked. + * However if the expression is "*", only the ANY ("*") extension is returned. + * @param expression which may contain '*' to represent zero or more characters. + * @param mimetypeService + * @return the list of extensions that match + */ + private List getMatchingExtensionsFromExtensions( + String expression, MimetypeService mimetypeService) + { + if (ANY.equals(expression)) + { + return Collections.singletonList(ANY); + } + Pattern pattern = pattern(expression); + List matchingMimetypes = new ArrayList(1); + for (String mimetype : mimetypeService.getMimetypes()) + { + String ext = mimetypeService.getExtension(mimetype); + if (pattern.matcher(ext).matches()) + { + matchingMimetypes.add(ext); + } + } + return matchingMimetypes; + } } -class TransformerSourceTargetValue +class TransformerSourceTargetSuffixKey { final String transformerName; final String sourceExt; final String targetExt; - final String value; final String suffix; - final String sourceMimetype; - final String targetMimetype; - - public TransformerSourceTargetValue(String transformerName, String sourceExt, - String targetExt, String value, String suffix, MimetypeService mimetypeService) + + public TransformerSourceTargetSuffixKey(String transformerName, String sourceExt, String targetExt, String suffix) { this.transformerName = transformerName; this.sourceExt = sourceExt; this.targetExt = targetExt; - this.value = value; this.suffix = suffix; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((sourceExt == null) ? 0 : sourceExt.hashCode()); + result = prime * result + ((suffix == null) ? 0 : suffix.hashCode()); + result = prime * result + ((targetExt == null) ? 0 : targetExt.hashCode()); + result = prime * result + ((transformerName == null) ? 0 : transformerName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + TransformerSourceTargetSuffixKey other = (TransformerSourceTargetSuffixKey) obj; + if (sourceExt == null) + { + if (other.sourceExt != null) + return false; + } + else if (!sourceExt.equals(other.sourceExt)) + return false; + if (suffix == null) + { + if (other.suffix != null) + return false; + } + else if (!suffix.equals(other.suffix)) + return false; + if (targetExt == null) + { + if (other.targetExt != null) + return false; + } + else if (!targetExt.equals(other.targetExt)) + return false; + if (transformerName == null) + { + if (other.transformerName != null) + return false; + } + else if (!transformerName.equals(other.transformerName)) + return false; + return true; + } +} + +class TransformerSourceTargetSuffixValue +{ + final String transformerName; + final String sourceExt; + final String targetExt; + final String suffix; + final String value; + + final String sourceMimetype; + final String targetMimetype; + + public TransformerSourceTargetSuffixValue(String transformerName, String sourceExt, + String targetExt, String suffix, String value, MimetypeService mimetypeService) + { + this.transformerName = transformerName; + this.sourceExt = sourceExt; + this.targetExt = targetExt; + this.suffix = suffix; + this.value = value; + this.sourceMimetype = ANY.equals(sourceExt) ? ANY : mimetypeService.getMimetype(sourceExt); this.targetMimetype = ANY.equals(targetExt) ? ANY : mimetypeService.getMimetype(targetExt); } - public Triple key() + public TransformerSourceTargetSuffixKey key() { - return new Triple(transformerName, sourceExt, targetExt); + return new TransformerSourceTargetSuffixKey(transformerName, sourceExt, targetExt, suffix); } public String toString() { - return transformerName+'.'+(sourceExt.equals(ANY) && targetExt.equals(ANY) + return transformerName+(sourceExt.equals(ANY) && targetExt.equals(ANY) ? "" - : TransformerConfig.EXTENSIONS+'.'+sourceExt+'.'+targetExt+'.')+ + : TransformerConfig.EXTENSIONS+sourceExt+'.'+targetExt)+ suffix+'='+value; } @@ -237,6 +344,7 @@ class TransformerSourceTargetValue final int prime = 31; int result = 1; result = prime * result + ((sourceExt == null) ? 0 : sourceExt.hashCode()); + result = prime * result + ((suffix == null) ? 0 : suffix.hashCode()); result = prime * result + ((targetExt == null) ? 0 : targetExt.hashCode()); result = prime * result + ((transformerName == null) ? 0 : transformerName.hashCode()); result = prime * result + ((value == null) ? 0 : value.hashCode()); @@ -252,7 +360,7 @@ class TransformerSourceTargetValue return false; if (getClass() != obj.getClass()) return false; - TransformerSourceTargetValue other = (TransformerSourceTargetValue) obj; + TransformerSourceTargetSuffixValue other = (TransformerSourceTargetSuffixValue) obj; if (sourceExt == null) { if (other.sourceExt != null) @@ -260,6 +368,13 @@ class TransformerSourceTargetValue } else if (!sourceExt.equals(other.sourceExt)) return false; + if (suffix == null) + { + if (other.suffix != null) + return false; + } + else if (!suffix.equals(other.suffix)) + return false; if (targetExt == null) { if (other.targetExt != null) diff --git a/source/java/org/alfresco/repo/content/transform/TransformerPropertyNameExtractorTest.java b/source/java/org/alfresco/repo/content/transform/TransformerPropertyNameExtractorTest.java new file mode 100644 index 0000000000..9a3da515d4 --- /dev/null +++ b/source/java/org/alfresco/repo/content/transform/TransformerPropertyNameExtractorTest.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2005-2013 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.content.transform; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +/** + * Test class for some of the regex methods. + * + * @author Alan Davis + */ +public class TransformerPropertyNameExtractorTest +{ + @Test + public void textSplitExt() + { + String[][] values = new String[][] + { + {"AAA.BBB", "AAA", "BBB"}, + {"AA\\.BB.CC\\.DD\\.EE", "AA.BB", "CC.DD.EE"}, + }; + + for (String[] args: values) + { + String input = args[0]; + String expectedSource = args[1]; + String expectedTarget = args[2]; + + String[] sourceTarget = TransformerPropertyNameExtractor.splitExt(input); + assertEquals("length", sourceTarget.length, 2); + assertEquals("source", expectedSource, sourceTarget[0]); + assertEquals("target", expectedTarget, sourceTarget[1]); + } + } + + @Test + public void testPattern() + { + assertTrue( TransformerPropertyNameExtractor.pattern("ABC").matcher("ABC").matches()); + assertFalse(TransformerPropertyNameExtractor.pattern("ABC").matcher("x").matches()); + assertFalse(TransformerPropertyNameExtractor.pattern("ABC").matcher("ABCD").matches()); + assertFalse(TransformerPropertyNameExtractor.pattern("ABC").matcher("DABC").matches()); + + assertTrue( TransformerPropertyNameExtractor.pattern("*B").matcher("B").matches()); + assertTrue( TransformerPropertyNameExtractor.pattern("*B").matcher("xxB").matches()); + assertFalse(TransformerPropertyNameExtractor.pattern("*B").matcher("xxBx").matches()); + assertFalse( TransformerPropertyNameExtractor.pattern("B*").matcher("").matches()); + + assertTrue( TransformerPropertyNameExtractor.pattern("C*").matcher("C").matches()); + assertTrue( TransformerPropertyNameExtractor.pattern("C*").matcher("CxxB").matches()); + assertFalse(TransformerPropertyNameExtractor.pattern("C*").matcher("xxBx").matches()); + + assertTrue(TransformerPropertyNameExtractor.pattern("D*E*F").matcher("DEF").matches()); + assertTrue(TransformerPropertyNameExtractor.pattern("D*E*F").matcher("DxxExxF").matches()); + assertTrue(TransformerPropertyNameExtractor.pattern("D*E*F").matcher("D*E*F").matches()); + + assertTrue( TransformerPropertyNameExtractor.pattern("A+").matcher("A+").matches()); + assertFalse(TransformerPropertyNameExtractor.pattern("A+").matcher("AA").matches()); + assertFalse(TransformerPropertyNameExtractor.pattern("A+").matcher("AAA").matches()); + assertFalse(TransformerPropertyNameExtractor.pattern("A+").matcher("A+A").matches()); + } +}