[java-identity-provider] branch feature/IDP-1434 updated: Eliminate use of Properties from interfaces.

Scott Cantor cantor.2 at osu.edu
Tue May 7 13:51:56 EDT 2019


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch feature/IDP-1434
in repository java-identity-provider.

View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=fbf1bdd0ed9c2b5b69ccbe46a24dd32db48e9ac5

The following commit(s) were added to refs/heads/feature/IDP-1434 by this push:
       new  fbf1bdd   Eliminate use of Properties from interfaces.
fbf1bdd is described below

commit fbf1bdd0ed9c2b5b69ccbe46a24dd32db48e9ac5
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue May 7 13:51:50 2019 -0400

    Eliminate use of Properties from interfaces.
---
 .../transcoding/AbstractAttributeTranscoder.java   | 43 ++++++++------------
 .../attribute/transcoding/AttributeTranscoder.java | 13 +++---
 .../transcoding/AttributeTranscoderRegistry.java   | 10 ++---
 .../attribute/transcoding/TranscoderSupport.java   | 17 ++++----
 .../attribute/transcoding}/TranscodingRule.java    | 47 ++++++++++++++++++++--
 .../impl/AttributeTranscoderRegistryImpl.java      | 23 +++++------
 .../impl/AttributeTranscoderRegistryImplTest.java  | 38 ++++++++---------
 .../attribute/transcoding/impl/PairTranscoder.java | 17 ++++----
 .../spring/enc/BaseAttributeEncoderParser.java     |  2 +-
 .../impl/AttributeRegistryServiceStrategy.java     |  2 +-
 .../resolver/spring/AttributeMapperTest.java       | 19 ++++-----
 .../spring/BaseEncoderDefinitionParserTest.java    |  2 +-
 .../attribute/resolver/spring/enc/Regressions.java |  2 +-
 .../system/conf/attribute-registry-system.xml      |  2 +-
 .../AbstractSAML1AttributeTranscoder.java          | 16 ++++----
 .../AbstractSAML2AttributeTranscoder.java          | 18 ++++-----
 .../AbstractSAMLAttributeTranscoder.java           | 32 +++++++--------
 .../impl/SAML1ByteAttributeTranscoder.java         | 14 +++----
 .../impl/SAML1ScopedStringAttributeTranscoder.java | 28 ++++++-------
 .../impl/SAML1StringAttributeTranscoder.java       | 14 +++----
 .../impl/SAML1XMLObjectAttributeTranscoder.java    | 10 ++---
 .../impl/SAML2ByteAttributeTranscoder.java         | 14 +++----
 .../impl/SAML2ScopedStringAttributeTranscoder.java | 27 ++++++-------
 .../impl/SAML2StringAttributeTranscoder.java       | 14 +++----
 .../impl/SAML2XMLObjectAttributeTranscoder.java    | 10 ++---
 .../impl/AttributeMappingNodeProcessor.java        |  6 +--
 .../impl/BaseAddAttributeStatementToAssertion.java |  6 +--
 .../impl/FilterByQueriedAttributeDesignators.java  |  6 +--
 .../profile/impl/FilterByQueriedAttributes.java    |  6 +--
 .../impl/SAML1ByteAttributeTranscoderTest.java     | 47 +++++++++++-----------
 .../SAML1ScopedStringAttributeTranscoderTest.java  | 39 +++++++++---------
 .../impl/SAML1StringAttributeTranscoderTest.java   | 43 ++++++++++----------
 .../impl/SAML2ByteAttributeTranscoderTest.java     | 47 +++++++++++-----------
 .../SAML2ScopedStringAttributeTranscoderTest.java  | 43 ++++++++++----------
 .../impl/SAML2StringAttributeTranscoderTest.java   | 43 ++++++++++----------
 .../SAML2XMLObjectAttributeTranscoderTest.java     | 43 ++++++++++----------
 .../impl/AddAttributeStatementToAssertionTest.java |  5 +--
 .../impl/AddAttributeStatementToAssertionTest.java |  5 +--
 .../idp/saml/impl/profile/saml1Mapper.xml          |  2 +-
 .../idp/saml/impl/profile/saml2Mapper.xml          |  2 +-
 40 files changed, 390 insertions(+), 387 deletions(-)

diff --git a/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AbstractAttributeTranscoder.java b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AbstractAttributeTranscoder.java
index 92ce1ac..14a2500 100644
--- a/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AbstractAttributeTranscoder.java
+++ b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AbstractAttributeTranscoder.java
@@ -17,7 +17,6 @@
 
 package net.shibboleth.idp.attribute.transcoding;
 
-import java.util.Properties;
 import java.util.function.Predicate;
 
 import javax.annotation.Nonnull;
@@ -69,38 +68,28 @@ public abstract class AbstractAttributeTranscoder<T> extends AbstractInitializab
     /** {@inheritDoc} */
     @Nullable public T encode(@Nullable final ProfileRequestContext profileRequestContext,
             @Nonnull final IdPAttribute attribute, @Nonnull final Class<? extends T> to,
-            @Nonnull final Properties properties) throws AttributeEncodingException {
+            @Nonnull final TranscodingRule rule) throws AttributeEncodingException {
         ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
         Constraint.isNotNull(attribute, "Attribute to encode cannot be null");
 
-        if (!checkActivation(profileRequestContext, properties)) {
+        if (!checkActivation(profileRequestContext, rule)) {
             return null;
         }
 
-        return doEncode(profileRequestContext, attribute, to, properties);
+        return doEncode(profileRequestContext, attribute, to, rule);
     }
     
-    /**
-     * Decode the supplied object into a protocol-neutral representation.
-     * 
-     * @param profileRequestContext current profile request context
-     * @param input the object to decode
-     * @param properties properties governing the decoding process, principally the resulting attribute's naming
-     * 
-     * @return the attribute the object was decoded into
-     * 
-     * @throws AttributeDecodingException if unable to successfully decode object
-     */
+    /** {@inheritDoc} */
     @Nullable public IdPAttribute decode(@Nullable final ProfileRequestContext profileRequestContext,
-            @Nonnull final T input, @Nonnull final Properties properties) throws AttributeDecodingException {
+            @Nonnull final T input, @Nonnull final TranscodingRule rule) throws AttributeDecodingException {
         ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
         Constraint.isNotNull(input, "Attribute to decode cannot be null");
 
-        if (!checkActivation(profileRequestContext, properties)) {
+        if (!checkActivation(profileRequestContext, rule)) {
             return null;
         }
         
-        return doDecode(profileRequestContext, input, properties);
+        return doDecode(profileRequestContext, input, rule);
     }
     
     
@@ -110,7 +99,7 @@ public abstract class AbstractAttributeTranscoder<T> extends AbstractInitializab
      * @param profileRequestContext current profile request context
      * @param attribute the attribute to encode
      * @param to specific type of object to encode
-     * @param properties properties governing the encoding process, principally the resulting object's naming
+     * @param rule properties governing the encoding process, principally the resulting object's naming
      * 
      * @return the Object the attribute was encoded into
      * 
@@ -118,7 +107,7 @@ public abstract class AbstractAttributeTranscoder<T> extends AbstractInitializab
      */
     @Nullable protected abstract T doEncode(@Nullable final ProfileRequestContext profileRequestContext,
             @Nonnull final IdPAttribute attribute, @Nonnull final Class<? extends T> to,
-            @Nonnull final Properties properties) throws AttributeEncodingException;
+            @Nonnull final TranscodingRule rule) throws AttributeEncodingException;
     
 
     /**
@@ -126,14 +115,14 @@ public abstract class AbstractAttributeTranscoder<T> extends AbstractInitializab
      * 
      * @param profileRequestContext current profile request context
      * @param input the object to decode
-     * @param properties properties governing the decoding process, principally the resulting attribute's naming
+     * @param rule properties governing the decoding process, principally the resulting attribute's naming
      * 
      * @return the attribute the object was decoded into
      * 
      * @throws AttributeDecodingException if unable to successfully decode object
      */
     @Nullable protected abstract IdPAttribute doDecode(@Nullable final ProfileRequestContext profileRequestContext,
-            @Nonnull final T input, @Nonnull final Properties properties) throws AttributeDecodingException;
+            @Nonnull final T input, @Nonnull final TranscodingRule rule) throws AttributeDecodingException;
 
 
     /**
@@ -141,21 +130,21 @@ public abstract class AbstractAttributeTranscoder<T> extends AbstractInitializab
      * Apply any activation rules to the request.
      * 
      * @param profileRequestContext current profile request context
-     * @param properties properties governing the transoding process
+     * @param rule properties governing the transoding process
      * 
      * @return true iff the process should continue
      */
     private boolean checkActivation(@Nullable final ProfileRequestContext profileRequestContext,
-            @Nonnull final Properties properties) {
+            @Nonnull final TranscodingRule rule) {
         
         if (!activationCondition.test(profileRequestContext)) {
             log.debug("Transcoder inactive");
             return false;
         }
 
-        final Object condition = properties.get(AttributeTranscoderRegistry.PROP_CONDITION);
-        if (condition instanceof Predicate) {
-            if (!((Predicate) condition).test(profileRequestContext)) {
+        final Predicate condition = rule.get(AttributeTranscoderRegistry.PROP_CONDITION, Predicate.class);
+        if (condition != null) {
+            if (!condition.test(profileRequestContext)) {
                 log.debug("Transcoder inactive");
                 return false;
             }
diff --git a/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AttributeTranscoder.java b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AttributeTranscoder.java
index 5b83414..a8a0a2f 100644
--- a/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AttributeTranscoder.java
+++ b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AttributeTranscoder.java
@@ -17,7 +17,6 @@
 
 package net.shibboleth.idp.attribute.transcoding;
 
-import java.util.Properties;
 import java.util.function.Predicate;
 
 import javax.annotation.Nonnull;
@@ -59,12 +58,12 @@ public interface AttributeTranscoder<T> extends InitializableComponent {
      * Get the name of the encoded object that would be created by a given set of
      * instructions.
      * 
-     * @param properties properties governing the encoding process
+     * @param rule properties governing the encoding process
      * 
      * @return a canonical name for objects produced by this transcoder for the
      *  given instructions
      */
-    @Nullable @NotEmpty String getEncodedName(@Nonnull final Properties properties);
+    @Nullable @NotEmpty String getEncodedName(@Nonnull final TranscodingRule rule);
     
     /**
      * Encode the supplied attribute into a protocol specific representation.
@@ -72,7 +71,7 @@ public interface AttributeTranscoder<T> extends InitializableComponent {
      * @param profileRequestContext current profile request context
      * @param attribute the attribute to encode
      * @param to specific type of object to encode
-     * @param properties properties governing the encoding process, principally the resulting object's naming
+     * @param rule properties governing the encoding process, principally the resulting object's naming
      * 
      * @return the Object the attribute was encoded into
      * 
@@ -80,20 +79,20 @@ public interface AttributeTranscoder<T> extends InitializableComponent {
      */
     @Nullable T encode(@Nullable final ProfileRequestContext profileRequestContext,
             @Nonnull final IdPAttribute attribute, @Nonnull final Class<? extends T> to,
-            @Nonnull final Properties properties) throws AttributeEncodingException;
+            @Nonnull final TranscodingRule rule) throws AttributeEncodingException;
     
     /**
      * Decode the supplied object into a protocol-neutral representation.
      * 
      * @param profileRequestContext current profile request context
      * @param input the object to decode
-     * @param properties properties governing the decoding process, principally the resulting attribute's naming
+     * @param rule properties governing the decoding process, principally the resulting attribute's naming
      * 
      * @return the attribute the object was decoded into
      * 
      * @throws AttributeDecodingException if unable to successfully decode object
      */
     @Nullable IdPAttribute decode(@Nullable final ProfileRequestContext profileRequestContext,
-            @Nonnull final T input, @Nonnull final Properties properties) throws AttributeDecodingException;
+            @Nonnull final T input, @Nonnull final TranscodingRule rule) throws AttributeDecodingException;
     
 }
\ No newline at end of file
diff --git a/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AttributeTranscoderRegistry.java b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AttributeTranscoderRegistry.java
index 861797a..f061901 100644
--- a/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AttributeTranscoderRegistry.java
+++ b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/AttributeTranscoderRegistry.java
@@ -18,7 +18,6 @@
 package net.shibboleth.idp.attribute.transcoding;
 
 import java.util.Collection;
-import java.util.Properties;
 
 import javax.annotation.Nonnull;
 import javax.annotation.concurrent.ThreadSafe;
@@ -60,10 +59,10 @@ public interface AttributeTranscoderRegistry extends IdentifiedComponent {
      * @param from the input object to encode
      * @param to class of object being encoded
      * 
-     * @return a collection of {@link Properties} objects, possibly empty
+     * @return a collection of {@link TranscodingRule} objects, possibly empty
      */
     @Nonnull @NonnullElements @Unmodifiable
-    Collection<Properties> getTranscodingProperties(@Nonnull final IdPAttribute from, @Nonnull final Class<?> to);
+    Collection<TranscodingRule> getTranscodingRules(@Nonnull final IdPAttribute from, @Nonnull final Class<?> to);
 
     /**
      * Obtains a set of instructions for decoding an input object into an {@link IdPAttribute}.
@@ -75,8 +74,9 @@ public interface AttributeTranscoderRegistry extends IdentifiedComponent {
      * @param <T> the type of object to decode
      * @param from object to decode
      * 
-     * @return a collection of {@link Properties} objects, possibly empty
+     * @return a collection of {@link TranscodingRule} objects, possibly empty
      */
-    @Nonnull @NonnullElements @Unmodifiable <T> Collection<Properties> getTranscodingProperties(@Nonnull final T from);
+    @Nonnull @NonnullElements @Unmodifiable <T> Collection<TranscodingRule> getTranscodingRules(
+            @Nonnull final T from);
         
 }
\ No newline at end of file
diff --git a/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/TranscoderSupport.java b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/TranscoderSupport.java
index 10df4a2..e9f8ac6 100644
--- a/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/TranscoderSupport.java
+++ b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/TranscoderSupport.java
@@ -17,8 +17,6 @@
 
 package net.shibboleth.idp.attribute.transcoding;
 
-import java.util.Properties;
-
 import javax.annotation.Nonnull;
 
 import net.shibboleth.utilities.java.support.logic.Constraint;
@@ -35,22 +33,23 @@ public final class TranscoderSupport {
     }
 
     /**
-     * Pull an {@link AttributeTranscoder} object out of the properties provided.
+     * Pull an {@link AttributeTranscoder} object out of the rule provided.
      * 
      * @param <T> type of supported target object
-     * @param ruleset transcoding rules in the form of a {@link Properties} collection
+     * @param rule transcoding rule
      * 
      * @return an {@link AttributeTranscoder}
      * 
      * @throws ConstraintViolationException if a transcoder cannot be obtained
      */
-    @Nonnull public static <T> AttributeTranscoder<T> getTranscoder(@Nonnull final Properties ruleset)
+    @Nonnull public static <T> AttributeTranscoder<T> getTranscoder(@Nonnull final TranscodingRule rule)
             throws ConstraintViolationException {
-        Constraint.isNotNull(ruleset, "Transcoding properties cannot be null");
+        Constraint.isNotNull(rule, "Transcoding rule cannot be null");
         
-        final Object transcoder = ruleset.get(AttributeTranscoderRegistry.PROP_TRANSCODER);
-        Constraint.isTrue(transcoder instanceof AttributeTranscoder<?>, "AttributeTranscoder not found in properties");
-        return (AttributeTranscoder<T>) transcoder;
+        final AttributeTranscoder<T> transcoder =
+                rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER, AttributeTranscoder.class);
+        Constraint.isNotNull(transcoder, "AttributeTranscoder not found in properties");
+        return transcoder;
     }
 
 }
\ No newline at end of file
diff --git a/idp-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/TranscodingRule.java b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/TranscodingRule.java
similarity index 63%
rename from idp-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/TranscodingRule.java
rename to idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/TranscodingRule.java
index 52c163f..5e3e036 100644
--- a/idp-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/TranscodingRule.java
+++ b/idp-attribute-api/src/main/java/net/shibboleth/idp/attribute/transcoding/TranscodingRule.java
@@ -15,18 +15,18 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.attribute.transcoding.impl;
+package net.shibboleth.idp.attribute.transcoding;
 
 import java.util.HashMap;
 import java.util.Map;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
-import net.shibboleth.idp.attribute.transcoding.AttributeTranscoder;
-import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
 import net.shibboleth.utilities.java.support.annotation.ParameterName;
 import net.shibboleth.utilities.java.support.annotation.constraint.Live;
 import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
 
 /**
  * Wrapper around a {@link Map} representing a rule for transcoding, used to
@@ -55,7 +55,7 @@ public class TranscodingRule {
     public TranscodingRule(@Nonnull @NonnullElements @ParameterName(name="map") final Map<String,Object> map) {
         rule = new HashMap<>(map);
     }
- 
+
     /**
      * Access the underlying mapping rule.
      * 
@@ -65,4 +65,43 @@ public class TranscodingRule {
         return rule;
     }
     
+    /**
+     * Get the value of a property key in the rule.
+     * 
+     * @param <T> type of property value
+     * @param key key of property
+     * @param type class type of property
+     * 
+     * @return the mapped value, or null
+     */
+    @Nullable public <T> T get(@Nonnull @NotEmpty final String key, @Nonnull final Class<T> type) {
+        final Object value = rule.get(key);
+        if (type.isInstance(value)) {
+            return (T) value;
+        } else {
+            return null;
+        }
+    }
+    
+    /**
+     * Get the value of a property key in the rule or a default value if no property exists.
+     * 
+     * @param <T> type of property value
+     * @param key key of property
+     * @param type class type of property
+     * @param defValue default value
+     * 
+     * @return the mapped value, or the default
+     */
+    @Nullable public <T> T getOrDefault(@Nonnull @NotEmpty final String key, @Nonnull final Class<T> type,
+            @Nullable final T defValue) {
+        
+        final T value = get(key, type);
+        if (value != null) {
+            return value;
+        } else {
+            return defValue;
+        }
+    }
+
 }
\ No newline at end of file
diff --git a/idp-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/AttributeTranscoderRegistryImpl.java b/idp-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/AttributeTranscoderRegistryImpl.java
index c72eac8..fffe8c6 100644
--- a/idp-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/AttributeTranscoderRegistryImpl.java
+++ b/idp-attribute-impl/src/main/java/net/shibboleth/idp/attribute/transcoding/impl/AttributeTranscoderRegistryImpl.java
@@ -22,7 +22,6 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Properties;
 import java.util.function.Function;
 import java.util.function.Predicate;
 
@@ -34,6 +33,7 @@ import net.shibboleth.ext.spring.service.AbstractServiceableComponent;
 import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoder;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.profile.logic.RelyingPartyIdPredicate;
 import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
 import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
@@ -62,7 +62,7 @@ public class AttributeTranscoderRegistryImpl extends AbstractServiceableComponen
     @Nonnull private final Logger log = LoggerFactory.getLogger(AttributeTranscoderRegistryImpl.class);
     
     /** Registry of transcoding instructions for a given "name" and type of object. */
-    @Nonnull private final Map<String,Multimap<Class<?>,Properties>> transcodingRegistry;
+    @Nonnull private final Map<String,Multimap<Class<?>,TranscodingRule>> transcodingRegistry;
     
     /** Registry of naming functions for supported object types. */
     @Nonnull private final Map<Class<?>,Function<?,String>> namingFunctionRegistry;
@@ -142,13 +142,13 @@ public class AttributeTranscoderRegistryImpl extends AbstractServiceableComponen
     }
     
     /** {@inheritDoc} */
-    @Nonnull @NonnullElements @Unmodifiable public Collection<Properties> getTranscodingProperties(
+    @Nonnull @NonnullElements @Unmodifiable public Collection<TranscodingRule> getTranscodingRules(
             @Nonnull final IdPAttribute from, @Nonnull final Class<?> to) {
         ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
         Constraint.isNotNull(from, "IdPAttribute cannot be null");
         Constraint.isNotNull(to, "Target type cannot be null");
         
-        final Multimap<Class<?>,Properties> propertyCollections = transcodingRegistry.get(from.getId());
+        final Multimap<Class<?>,TranscodingRule> propertyCollections = transcodingRegistry.get(from.getId());
         if (propertyCollections == null) {
             return Collections.emptyList();
         }
@@ -165,7 +165,7 @@ public class AttributeTranscoderRegistryImpl extends AbstractServiceableComponen
     }
 
     /** {@inheritDoc} */
-    @Nonnull @NonnullElements @Unmodifiable public <T> Collection<Properties> getTranscodingProperties(
+    @Nonnull @NonnullElements @Unmodifiable public <T> Collection<TranscodingRule> getTranscodingRules(
             @Nonnull final T from) {
         ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
         Constraint.isNotNull(from, "Input object cannot be null");
@@ -183,7 +183,7 @@ public class AttributeTranscoderRegistryImpl extends AbstractServiceableComponen
         // Don't know if we can work around this cast or not.
         final String id = ((Function<? super T,String>) namingFunction).apply(from);
         if (id != null) {
-            final Multimap<Class<?>,Properties> propertyCollections = transcodingRegistry.get(id);
+            final Multimap<Class<?>,TranscodingRule> propertyCollections = transcodingRegistry.get(id);
             
             return propertyCollections != null ? ImmutableList.copyOf(propertyCollections.get(effectiveType))
                     : Collections.emptyList();
@@ -224,9 +224,8 @@ public class AttributeTranscoderRegistryImpl extends AbstractServiceableComponen
             return;
         }
 
-        final Properties copy = new Properties();
-        copy.putAll(ruleset);
-        copy.put(PROP_TRANSCODER, transcoder);
+        final TranscodingRule copy = new TranscodingRule(ruleset);
+        copy.getMap().put(PROP_TRANSCODER, transcoder);
 
         final Class<?> type = ((AttributeTranscoder) transcoder).getEncodedType();
         final String targetName = ((AttributeTranscoder) transcoder).getEncodedName(copy);
@@ -235,9 +234,9 @@ public class AttributeTranscoderRegistryImpl extends AbstractServiceableComponen
             log.debug("Attribute mapping: {} <-> {} via {}", id, targetName, transcoder.getClass().getSimpleName());
             
             // Install mapping back to IdPAttribute's trimmed name.
-            copy.setProperty(PROP_ID, id);
+            copy.getMap().put(PROP_ID, id);
             
-            Multimap<Class<?>,Properties> rulesetsForIdPName = transcodingRegistry.get(id);
+            Multimap<Class<?>,TranscodingRule> rulesetsForIdPName = transcodingRegistry.get(id);
             if (rulesetsForIdPName == null) {
                 rulesetsForIdPName = ArrayListMultimap.create();
                 transcodingRegistry.put(id, rulesetsForIdPName);
@@ -245,7 +244,7 @@ public class AttributeTranscoderRegistryImpl extends AbstractServiceableComponen
             
             rulesetsForIdPName.put(type, copy);
 
-            Multimap<Class<?>,Properties> rulesetsForEncodedName = transcodingRegistry.get(targetName);
+            Multimap<Class<?>,TranscodingRule> rulesetsForEncodedName = transcodingRegistry.get(targetName);
             if (rulesetsForEncodedName == null) {
                 rulesetsForEncodedName = ArrayListMultimap.create();
                 transcodingRegistry.put(targetName, rulesetsForEncodedName);
diff --git a/idp-attribute-impl/src/test/java/net/shibboleth/idp/attribute/transcoding/impl/AttributeTranscoderRegistryImplTest.java b/idp-attribute-impl/src/test/java/net/shibboleth/idp/attribute/transcoding/impl/AttributeTranscoderRegistryImplTest.java
index 6b0a089..d0741db 100644
--- a/idp-attribute-impl/src/test/java/net/shibboleth/idp/attribute/transcoding/impl/AttributeTranscoderRegistryImplTest.java
+++ b/idp-attribute-impl/src/test/java/net/shibboleth/idp/attribute/transcoding/impl/AttributeTranscoderRegistryImplTest.java
@@ -24,7 +24,6 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Properties;
 
 import static org.testng.Assert.*;
 import org.testng.annotations.AfterClass;
@@ -41,6 +40,7 @@ import net.shibboleth.idp.attribute.StringAttributeValue;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoder;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
 import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
 import net.shibboleth.utilities.java.support.collection.Pair;
 import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
@@ -99,25 +99,25 @@ public class AttributeTranscoderRegistryImplTest {
 
     @Test public void testEncodeNoMappings() throws AttributeEncodingException {
         
-        assertTrue(registry.getTranscodingProperties(new IdPAttribute("frobnitz"), Pair.class).isEmpty());
-        assertTrue(registry.getTranscodingProperties(new IdPAttribute("frobnitz"), MyPair.class).isEmpty());
-        assertTrue(registry.getTranscodingProperties(new IdPAttribute("foo"), String.class).isEmpty());
+        assertTrue(registry.getTranscodingRules(new IdPAttribute("frobnitz"), Pair.class).isEmpty());
+        assertTrue(registry.getTranscodingRules(new IdPAttribute("frobnitz"), MyPair.class).isEmpty());
+        assertTrue(registry.getTranscodingRules(new IdPAttribute("foo"), String.class).isEmpty());
 }
 
     @Test public void testDecodeNoMappings() throws AttributeDecodingException {
         
-        assertTrue(registry.getTranscodingProperties(new Pair("foo", "value")).isEmpty());
-        assertTrue(registry.getTranscodingProperties(new MyPair("foo", "value")).isEmpty());
-        assertTrue(registry.getTranscodingProperties(new String("bar")).isEmpty());
+        assertTrue(registry.getTranscodingRules(new Pair("foo", "value")).isEmpty());
+        assertTrue(registry.getTranscodingRules(new MyPair("foo", "value")).isEmpty());
+        assertTrue(registry.getTranscodingRules(new String("bar")).isEmpty());
     }
 
     @Test public void testDecodeInactive() throws AttributeDecodingException {
 
         final Pair p = new Pair("ban", "value");
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(p);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(p);
         assertEquals(rulesets.size(), 1);
         
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
         assertNull(t.decode(null, p, ruleset));
@@ -128,7 +128,7 @@ public class AttributeTranscoderRegistryImplTest {
         
         final List<Pair> pairs = new ArrayList<>();
         
-        for (final Properties ruleset : registry.getTranscodingProperties(foo, Pair.class)) {
+        for (final TranscodingRule ruleset : registry.getTranscodingRules(foo, Pair.class)) {
             final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
             final Pair p = t.encode(null, foo, Pair.class, ruleset);
             if (p != null) {
@@ -151,7 +151,7 @@ public class AttributeTranscoderRegistryImplTest {
         
         final List<IdPAttribute> attributes = new ArrayList<>();
         
-        for (final Properties ruleset : registry.getTranscodingProperties(bar)) {
+        for (final TranscodingRule ruleset : registry.getTranscodingRules(bar)) {
             final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
             attributes.add(t.decode(null, bar, ruleset));
         }
@@ -168,7 +168,7 @@ public class AttributeTranscoderRegistryImplTest {
         
         final List<IdPAttribute> attributes = new ArrayList<>();
         
-        for (final Properties ruleset : registry.getTranscodingProperties(baz)) {
+        for (final TranscodingRule ruleset : registry.getTranscodingRules(baz)) {
             final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
             attributes.add(t.decode(null, baz, ruleset));
         }
@@ -188,7 +188,7 @@ public class AttributeTranscoderRegistryImplTest {
         
         final List<Pair> pairs = new ArrayList<>();
         
-        for (final Properties ruleset : registry.getTranscodingProperties(foo, Pair.class)) {
+        for (final TranscodingRule ruleset : registry.getTranscodingRules(foo, Pair.class)) {
             final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
             final Pair p = t.encode(null, foo, Pair.class, ruleset);
             if (p != null) {
@@ -211,7 +211,7 @@ public class AttributeTranscoderRegistryImplTest {
         
         final List<MyPair> pairs = new ArrayList<>();
         
-        for (final Properties ruleset : registry.getTranscodingProperties(foo, MyPair.class)) {
+        for (final TranscodingRule ruleset : registry.getTranscodingRules(foo, MyPair.class)) {
             final AttributeTranscoder<MyPair> t = TranscoderSupport.getTranscoder(ruleset);
             final MyPair p = t.encode(null, foo, MyPair.class, ruleset);
             if (p != null) {
@@ -234,7 +234,7 @@ public class AttributeTranscoderRegistryImplTest {
         
         final List<IdPAttribute> attributes = new ArrayList<>();
         
-        for (final Properties ruleset : registry.getTranscodingProperties(bar)) {
+        for (final TranscodingRule ruleset : registry.getTranscodingRules(bar)) {
             final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
             attributes.add(t.decode(null, bar, ruleset));
         }
@@ -251,7 +251,7 @@ public class AttributeTranscoderRegistryImplTest {
         
         final List<IdPAttribute> attributes = new ArrayList<>();
         
-        for (final Properties ruleset : registry.getTranscodingProperties(baz)) {
+        for (final TranscodingRule ruleset : registry.getTranscodingRules(baz)) {
             final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
             attributes.add(t.decode(null, baz, ruleset));
         }
@@ -271,7 +271,7 @@ public class AttributeTranscoderRegistryImplTest {
         
         final List<Pair> pairs = new ArrayList<>();
         
-        for (final Properties ruleset : registry.getTranscodingProperties(foo, Pair.class)) {
+        for (final TranscodingRule ruleset : registry.getTranscodingRules(foo, Pair.class)) {
             final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
             final Pair p = t.encode(null, foo, Pair.class, ruleset);
             if (p != null) {
@@ -294,7 +294,7 @@ public class AttributeTranscoderRegistryImplTest {
         
         final List<IdPAttribute> attributes = new ArrayList<>();
         
-        for (final Properties ruleset : registry.getTranscodingProperties(bar)) {
+        for (final TranscodingRule ruleset : registry.getTranscodingRules(bar)) {
             final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
             attributes.add(t.decode(null, bar, ruleset));
         }
@@ -311,7 +311,7 @@ public class AttributeTranscoderRegistryImplTest {
         
         final List<IdPAttribute> attributes = new ArrayList<>();
         
-        for (final Properties ruleset : registry.getTranscodingProperties(baz)) {
+        for (final TranscodingRule ruleset : registry.getTranscodingRules(baz)) {
             final AttributeTranscoder<Pair> t = TranscoderSupport.getTranscoder(ruleset);
             attributes.add(t.decode(null, baz, ruleset));
         }
diff --git a/idp-attribute-impl/src/test/java/net/shibboleth/idp/attribute/transcoding/impl/PairTranscoder.java b/idp-attribute-impl/src/test/java/net/shibboleth/idp/attribute/transcoding/impl/PairTranscoder.java
index 0617bcd..abe4e10 100644
--- a/idp-attribute-impl/src/test/java/net/shibboleth/idp/attribute/transcoding/impl/PairTranscoder.java
+++ b/idp-attribute-impl/src/test/java/net/shibboleth/idp/attribute/transcoding/impl/PairTranscoder.java
@@ -19,7 +19,6 @@ package net.shibboleth.idp.attribute.transcoding.impl;
 
 import java.lang.reflect.InvocationTargetException;
 import java.util.Collections;
-import java.util.Properties;
 
 import org.opensaml.profile.context.ProfileRequestContext;
 
@@ -30,6 +29,7 @@ import net.shibboleth.idp.attribute.IdPAttributeValue;
 import net.shibboleth.idp.attribute.StringAttributeValue;
 import net.shibboleth.idp.attribute.transcoding.AbstractAttributeTranscoder;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.utilities.java.support.collection.Pair;
 import net.shibboleth.utilities.java.support.primitive.StringSupport;
 
@@ -44,9 +44,10 @@ public class PairTranscoder extends AbstractAttributeTranscoder<Pair> {
     }
 
     /** {@inheritDoc} */
-    public String getEncodedName(Properties properties) {
-        if (properties.containsKey("name")) {
-            return "{Pair}" + properties.getProperty("name");
+    public String getEncodedName(TranscodingRule rule) {
+        final String name = rule.get("name", String.class);
+        if (name != null) {
+            return "{Pair}" + name;
         } else {
             return null;
         }
@@ -54,10 +55,10 @@ public class PairTranscoder extends AbstractAttributeTranscoder<Pair> {
 
     /** {@inheritDoc} */
     @Override
-    public Pair doEncode(ProfileRequestContext profileRequestContext, IdPAttribute attribute, Class<? extends Pair> to, Properties properties)
+    public Pair doEncode(ProfileRequestContext profileRequestContext, IdPAttribute attribute, Class<? extends Pair> to, TranscodingRule rule)
             throws AttributeEncodingException {
         
-        final String name = StringSupport.trimOrNull(properties.getProperty("name"));
+        final String name = StringSupport.trimOrNull(rule.get("name", String.class));
         if (name == null) {
             throw new AttributeEncodingException("No name property");
         }
@@ -76,10 +77,10 @@ public class PairTranscoder extends AbstractAttributeTranscoder<Pair> {
 
     /** {@inheritDoc} */
     @Override
-    public IdPAttribute doDecode(ProfileRequestContext profileRequestContext, Pair input, Properties properties)
+    public IdPAttribute doDecode(ProfileRequestContext profileRequestContext, Pair input, TranscodingRule rule)
             throws AttributeDecodingException {
        
-        final String id = StringSupport.trimOrNull(properties.getProperty(AttributeTranscoderRegistry.PROP_ID));
+        final String id = StringSupport.trimOrNull(rule.get(AttributeTranscoderRegistry.PROP_ID, String.class));
         if (id == null) {
             throw new AttributeDecodingException("No id property");
         }
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/BaseAttributeEncoderParser.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/BaseAttributeEncoderParser.java
index 1bdda33..880adfe 100644
--- a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/BaseAttributeEncoderParser.java
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/enc/BaseAttributeEncoderParser.java
@@ -23,7 +23,7 @@ import javax.annotation.Nonnull;
 
 import net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverNamespaceHandler;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
-import net.shibboleth.idp.attribute.transcoding.impl.TranscodingRule;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.profile.logic.ScriptedPredicate;
 import net.shibboleth.idp.profile.spring.relyingparty.metadata.ScriptTypeBeanParser;
 import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/transcoding/spring/impl/AttributeRegistryServiceStrategy.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/transcoding/spring/impl/AttributeRegistryServiceStrategy.java
index 8601fe9..8bfdc25 100644
--- a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/transcoding/spring/impl/AttributeRegistryServiceStrategy.java
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/transcoding/spring/impl/AttributeRegistryServiceStrategy.java
@@ -29,8 +29,8 @@ import org.slf4j.LoggerFactory;
 import org.springframework.context.ApplicationContext;
 
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
-import net.shibboleth.idp.attribute.transcoding.impl.TranscodingRule;
 import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
 import net.shibboleth.utilities.java.support.component.AbstractIdentifiableInitializableComponent;
 import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeMapperTest.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeMapperTest.java
index e80df89..ab688f0 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeMapperTest.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeMapperTest.java
@@ -22,7 +22,6 @@ import static org.testng.Assert.*;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
-import java.util.Properties;
 
 import org.opensaml.core.OpenSAMLInitBaseTestCase;
 import org.opensaml.saml.saml2.core.Attribute;
@@ -35,8 +34,10 @@ import net.shibboleth.ext.spring.config.StringToDurationConverter;
 import net.shibboleth.ext.spring.util.SchemaTypeAwareXMLBeanDefinitionReader;
 import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.attribute.resolver.ResolutionException;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoder;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
-import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.saml.attribute.transcoding.SAML2AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2ScopedStringAttributeTranscoder;
 import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
 import net.shibboleth.utilities.java.support.service.ReloadableService;
@@ -88,15 +89,15 @@ public class AttributeMapperTest extends OpenSAMLInitBaseTestCase {
         try {
             serviceableComponent = transcoderRegistry.getServiceableComponent();
             
-            Collection<Properties> rulesets = serviceableComponent.getComponent().getTranscodingProperties(
+            Collection<TranscodingRule> rulesets = serviceableComponent.getComponent().getTranscodingRules(
                     new IdPAttribute("eduPersonScopedAffiliation"), Attribute.class);
             assertEquals(rulesets.size(), 1);
-            final Properties rule = rulesets.iterator().next();
-            assertEquals(rule.get(AbstractSAML2AttributeTranscoder.PROP_NAME), "urn:oid:1.3.6.1.4.1.5923.1.1.1.9");
-            assertNull(rule.get(AbstractSAML2AttributeTranscoder.PROP_NAME_FORMAT));
-            assertEquals(rule.get(AbstractSAML2AttributeTranscoder.PROP_FRIENDLY_NAME), "feduPersonScopedAffiliation");
-            assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER) instanceof SAML2ScopedStringAttributeTranscoder);
-            assertEquals(rule.get(SAML2ScopedStringAttributeTranscoder.PROP_SCOPE_DELIMITER), "#");
+            final TranscodingRule rule = rulesets.iterator().next();
+            assertEquals(rule.get(SAML2AttributeTranscoder.PROP_NAME, String.class), "urn:oid:1.3.6.1.4.1.5923.1.1.1.9");
+            assertNull(rule.get(SAML2AttributeTranscoder.PROP_NAME_FORMAT, String.class));
+            assertEquals(rule.get(SAML2AttributeTranscoder.PROP_FRIENDLY_NAME, String.class), "feduPersonScopedAffiliation");
+            assertTrue(rule.get(AttributeTranscoderRegistry.PROP_TRANSCODER, AttributeTranscoder.class) instanceof SAML2ScopedStringAttributeTranscoder);
+            assertEquals(rule.get(SAML2ScopedStringAttributeTranscoder.PROP_SCOPE_DELIMITER, String.class), "#");
         } finally {
             serviceableComponent.unpinComponent();
         }
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/BaseEncoderDefinitionParserTest.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/BaseEncoderDefinitionParserTest.java
index 807ea81..f6a0437 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/BaseEncoderDefinitionParserTest.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/BaseEncoderDefinitionParserTest.java
@@ -28,7 +28,7 @@ import org.springframework.core.env.StandardEnvironment;
 import org.springframework.mock.env.MockPropertySource;
 import org.testng.annotations.Test;
 
-import net.shibboleth.idp.attribute.transcoding.impl.TranscodingRule;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 
 /**
  * Base class for testing Attribute Encoding Parsers
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/Regressions.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/Regressions.java
index 7530f29..136a68b 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/Regressions.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/enc/Regressions.java
@@ -28,7 +28,7 @@ import org.testng.annotations.Test;
 import net.shibboleth.idp.attribute.resolver.AttributeDefinition;
 import net.shibboleth.idp.attribute.resolver.spring.BaseAttributeDefinitionParserTest;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
-import net.shibboleth.idp.attribute.transcoding.impl.TranscodingRule;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2StringAttributeTranscoder;
 
 /**
diff --git a/idp-conf/src/main/resources/system/conf/attribute-registry-system.xml b/idp-conf/src/main/resources/system/conf/attribute-registry-system.xml
index f63ec12..003c49a 100644
--- a/idp-conf/src/main/resources/system/conf/attribute-registry-system.xml
+++ b/idp-conf/src/main/resources/system/conf/attribute-registry-system.xml
@@ -40,6 +40,6 @@
     </util:map>
     
     <bean id="shibboleth.TranscodingRule"
-        class="net.shibboleth.idp.attribute.transcoding.impl.TranscodingRule" abstract="true" />
+        class="net.shibboleth.idp.attribute.transcoding.TranscodingRule" abstract="true" />
     
 </beans>
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML1AttributeTranscoder.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML1AttributeTranscoder.java
index 8c3ab08..0171c0f 100644
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML1AttributeTranscoder.java
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML1AttributeTranscoder.java
@@ -19,7 +19,6 @@ package net.shibboleth.idp.saml.attribute.transcoding;
 
 import java.util.Collections;
 import java.util.List;
-import java.util.Properties;
 import java.util.function.Function;
 
 import javax.annotation.Nonnull;
@@ -31,6 +30,7 @@ import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.attribute.IdPAttributeValue;
 import net.shibboleth.idp.attribute.IdPRequestedAttribute;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.saml.xml.SAMLConstants;
 import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
 
@@ -79,11 +79,11 @@ public abstract class AbstractSAML1AttributeTranscoder<EncodedType extends IdPAt
     }
     
     /** {@inheritDoc} */
-    @Nullable public String getEncodedName(@Nonnull final Properties properties) {
+    @Nullable public String getEncodedName(@Nonnull final TranscodingRule rule) {
         
         try {
             // SAML 1 naming should be based on only what needs to be available from the properties alone.
-            return new NamingFunction().apply(buildAttribute(null, null, AttributeDesignator.class, properties,
+            return new NamingFunction().apply(buildAttribute(null, null, AttributeDesignator.class, rule,
                     Collections.emptyList()));
         } catch (final AttributeEncodingException e) {
             return null;
@@ -94,14 +94,14 @@ public abstract class AbstractSAML1AttributeTranscoder<EncodedType extends IdPAt
     @Override
     @Nonnull protected AttributeDesignator buildAttribute(@Nullable final ProfileRequestContext profileRequestContext,
             @Nullable final IdPAttribute attribute, @Nonnull final Class<? extends AttributeDesignator> to,
-            @Nonnull final Properties properties, @Nonnull @NonnullElements final List<XMLObject> attributeValues)
+            @Nonnull final TranscodingRule rule, @Nonnull @NonnullElements final List<XMLObject> attributeValues)
                     throws AttributeEncodingException {
 
         if (attribute != null && !attribute.getValues().isEmpty() && attributeValues.isEmpty()) {
             throw new AttributeEncodingException("Failed to encode any values for attribute " + attribute.getId());
         }
 
-        final String name = properties.getProperty(PROP_NAME);
+        final String name = rule.get(PROP_NAME, String.class);
         if (Strings.isNullOrEmpty(name)) {
             throw new AttributeEncodingException("Required transcoder property 'name' not found");
         }
@@ -126,7 +126,7 @@ public abstract class AbstractSAML1AttributeTranscoder<EncodedType extends IdPAt
 
         samlAttribute.setAttributeName(name);
         samlAttribute.setAttributeNamespace(
-                properties.getProperty(PROP_NAMESPACE, SAMLConstants.SAML1_ATTR_NAMESPACE_URI));
+                rule.getOrDefault(PROP_NAMESPACE, String.class, SAMLConstants.SAML1_ATTR_NAMESPACE_URI));
         
         return samlAttribute;
     }
@@ -135,11 +135,11 @@ public abstract class AbstractSAML1AttributeTranscoder<EncodedType extends IdPAt
     @Override
     @Nonnull protected IdPAttribute buildIdPAttribute(
             @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final AttributeDesignator attribute,
-            @Nonnull final Properties properties,
+            @Nonnull final TranscodingRule rule,
             @Nonnull @NonnullElements final List<IdPAttributeValue<?>> attributeValues)
                     throws AttributeDecodingException {
         
-        final String id = properties.getProperty(AttributeTranscoderRegistry.PROP_ID);
+        final String id = rule.get(AttributeTranscoderRegistry.PROP_ID, String.class);
         if (Strings.isNullOrEmpty(id)) {
             throw new AttributeDecodingException("Required transcoder property 'id' not found");
         }
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML2AttributeTranscoder.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML2AttributeTranscoder.java
index e999039..52e2b8d 100644
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML2AttributeTranscoder.java
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAML2AttributeTranscoder.java
@@ -19,7 +19,6 @@ package net.shibboleth.idp.saml.attribute.transcoding;
 
 import java.util.Collections;
 import java.util.List;
-import java.util.Properties;
 import java.util.function.Function;
 
 import javax.annotation.Nonnull;
@@ -31,6 +30,7 @@ import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.attribute.IdPAttributeValue;
 import net.shibboleth.idp.attribute.IdPRequestedAttribute;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
 
 import org.opensaml.core.xml.XMLObject;
@@ -72,11 +72,11 @@ public abstract class AbstractSAML2AttributeTranscoder<EncodedType extends IdPAt
     }
     
     /** {@inheritDoc} */
-    @Nullable public String getEncodedName(@Nonnull final Properties properties) {
+    @Nullable public String getEncodedName(@Nonnull final TranscodingRule rule) {
         
         try {
             // SAML 2 naming should be based on only what needs to be available from the properties alone.
-            return new NamingFunction().apply(buildAttribute(null, null, Attribute.class, properties,
+            return new NamingFunction().apply(buildAttribute(null, null, Attribute.class, rule,
                     Collections.emptyList()));
         } catch (final AttributeEncodingException e) {
             return null;
@@ -87,14 +87,14 @@ public abstract class AbstractSAML2AttributeTranscoder<EncodedType extends IdPAt
     @Override
     @Nonnull protected Attribute buildAttribute(@Nullable final ProfileRequestContext profileRequestContext,
             @Nullable final IdPAttribute attribute, @Nonnull final Class<? extends Attribute> to,
-            @Nonnull final Properties properties, @Nonnull @NonnullElements final List<XMLObject> attributeValues)
+            @Nonnull final TranscodingRule rule, @Nonnull @NonnullElements final List<XMLObject> attributeValues)
                     throws AttributeEncodingException {
 
         if (attribute != null && !attribute.getValues().isEmpty() && attributeValues.isEmpty()) {
             throw new AttributeEncodingException("Failed to encode any values for attribute " + attribute.getId());
         }
         
-        final String name = properties.getProperty(PROP_NAME);
+        final String name = rule.get(PROP_NAME, String.class);
         if (Strings.isNullOrEmpty(name)) {
             throw new AttributeEncodingException("Required transcoder property 'name' not found");
         }
@@ -113,10 +113,10 @@ public abstract class AbstractSAML2AttributeTranscoder<EncodedType extends IdPAt
         }
 
         samlAttribute.setName(name);
-        samlAttribute.setNameFormat(properties.getProperty(PROP_NAME_FORMAT, Attribute.URI_REFERENCE));
+        samlAttribute.setNameFormat(rule.getOrDefault(PROP_NAME_FORMAT, String.class, Attribute.URI_REFERENCE));
         samlAttribute.getAttributeValues().addAll(attributeValues);
         
-        final String friendlyName = properties.getProperty(PROP_FRIENDLY_NAME,
+        final String friendlyName = rule.getOrDefault(PROP_FRIENDLY_NAME, String.class,
                 attribute != null ? attribute.getId() : "");
         if (!friendlyName.isBlank()) {
             samlAttribute.setFriendlyName(friendlyName);
@@ -129,7 +129,7 @@ public abstract class AbstractSAML2AttributeTranscoder<EncodedType extends IdPAt
     @Override
     @Nonnull protected IdPAttribute buildIdPAttribute(
             @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final Attribute attribute,
-            @Nonnull final Properties properties,
+            @Nonnull final TranscodingRule rule,
             @Nonnull @NonnullElements final List<IdPAttributeValue<?>> attributeValues)
                     throws AttributeDecodingException {
         
@@ -137,7 +137,7 @@ public abstract class AbstractSAML2AttributeTranscoder<EncodedType extends IdPAt
             throw new AttributeDecodingException("Failed to decode any values for attribute " + attribute.getName());
         }
         
-        final String id = properties.getProperty(AttributeTranscoderRegistry.PROP_ID);
+        final String id = rule.get(AttributeTranscoderRegistry.PROP_ID, String.class);
         if (Strings.isNullOrEmpty(id)) {
             throw new AttributeDecodingException("Required transcoder property 'id' not found");
         }
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAMLAttributeTranscoder.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAMLAttributeTranscoder.java
index 19fec60..df99f1b 100644
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAMLAttributeTranscoder.java
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/AbstractSAMLAttributeTranscoder.java
@@ -20,7 +20,6 @@ package net.shibboleth.idp.saml.attribute.transcoding;
 import java.time.Instant;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Properties;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -30,6 +29,7 @@ import net.shibboleth.idp.attribute.AttributeEncodingException;
 import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.attribute.IdPAttributeValue;
 import net.shibboleth.idp.attribute.transcoding.AbstractAttributeTranscoder;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.saml.xmlobject.ScopedValue;
 import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
 import net.shibboleth.utilities.java.support.xml.DOMTypeSupport;
@@ -64,7 +64,7 @@ public abstract class AbstractSAMLAttributeTranscoder<AttributeType extends SAML
     @Override
     @Nullable public AttributeType doEncode(@Nullable final ProfileRequestContext profileRequestContext,
             @Nonnull final IdPAttribute attribute, @Nonnull final Class<? extends AttributeType> to,
-            @Nonnull final Properties properties) throws AttributeEncodingException {
+            @Nonnull final TranscodingRule rule) throws AttributeEncodingException {
 
         final String attributeId = attribute.getId();
 
@@ -87,7 +87,7 @@ public abstract class AbstractSAMLAttributeTranscoder<AttributeType extends SAML
 
             final EncodedType attributeValue = (EncodedType) o;
             final XMLObject samlAttributeValue =
-                    encodeValue(profileRequestContext, attribute, properties, attributeValue);
+                    encodeValue(profileRequestContext, attribute, rule, attributeValue);
             if (samlAttributeValue == null) {
                 log.debug("Skipping null value for attribute {}", attributeId);
             } else {
@@ -96,16 +96,16 @@ public abstract class AbstractSAMLAttributeTranscoder<AttributeType extends SAML
         }
         
         log.debug("Encoded {} values for attribute {}", samlAttributeValues.size(), attributeId);
-        return buildAttribute(profileRequestContext, attribute, to, properties, samlAttributeValues);
+        return buildAttribute(profileRequestContext, attribute, to, rule, samlAttributeValues);
     }
 
     /** {@inheritDoc} */
     @Override
     @Nullable public IdPAttribute doDecode(@Nullable final ProfileRequestContext profileRequestContext,
-            @Nonnull final AttributeType input, @Nonnull final Properties properties)
+            @Nonnull final AttributeType input, @Nonnull final TranscodingRule rule)
                     throws AttributeDecodingException {
 
-        final String attributeName = getEncodedName(properties);
+        final String attributeName = getEncodedName(rule);
         
         log.debug("Beginning to decode attribute {}", attributeName);
 
@@ -119,7 +119,7 @@ public abstract class AbstractSAMLAttributeTranscoder<AttributeType extends SAML
                 continue;
             }
 
-            final IdPAttributeValue<?> idpAttributeValue = decodeValue(profileRequestContext, input, properties, o);
+            final IdPAttributeValue<?> idpAttributeValue = decodeValue(profileRequestContext, input, rule, o);
             if (idpAttributeValue == null) {
                 log.debug("Unable to decode value of attribute {}", attributeName);
             } else {
@@ -130,7 +130,7 @@ public abstract class AbstractSAMLAttributeTranscoder<AttributeType extends SAML
         if (!idpAttributeValues.isEmpty()) {
             log.debug("Decoded {} values for attribute {}", idpAttributeValues.size(), attributeName);
         }
-        return buildIdPAttribute(profileRequestContext, input, properties, idpAttributeValues);
+        return buildIdPAttribute(profileRequestContext, input, rule, idpAttributeValues);
     }
 
     /**
@@ -213,7 +213,7 @@ public abstract class AbstractSAMLAttributeTranscoder<AttributeType extends SAML
      * @param profileRequestContext current profile request
      * @param attribute the attribute being encoded
      * @param to target type to create
-     * @param properties properties to control encoding
+     * @param rule properties to control encoding
      * @param attributeValues the encoded values for the attribute
      * 
      * @return the SAML attribute object
@@ -222,7 +222,7 @@ public abstract class AbstractSAMLAttributeTranscoder<AttributeType extends SAML
      */
     @Nonnull protected abstract AttributeType buildAttribute(
             @Nullable final ProfileRequestContext profileRequestContext, @Nullable final IdPAttribute attribute,
-            @Nonnull final Class<? extends AttributeType> to, @Nonnull final Properties properties,
+            @Nonnull final Class<? extends AttributeType> to, @Nonnull final TranscodingRule rule,
             @Nonnull @NonnullElements final List<XMLObject> attributeValues) throws AttributeEncodingException;
 
     /**
@@ -230,7 +230,7 @@ public abstract class AbstractSAMLAttributeTranscoder<AttributeType extends SAML
      * 
      * @param profileRequestContext current profile request
      * @param attribute the attribute being encoded
-     * @param properties properties to control encoding
+     * @param rule properties to control encoding
      * @param value the value to encode
      * 
      * @return the attribute value or null if the resulting attribute value would be empty
@@ -238,7 +238,7 @@ public abstract class AbstractSAMLAttributeTranscoder<AttributeType extends SAML
      * @throws AttributeEncodingException thrown if there is a problem encoding the attribute value
      */
     @Nullable protected abstract XMLObject encodeValue(@Nullable final ProfileRequestContext profileRequestContext,
-            @Nonnull final IdPAttribute attribute, @Nonnull final Properties properties,
+            @Nonnull final IdPAttribute attribute, @Nonnull final TranscodingRule rule,
             @Nonnull final EncodedType value) throws AttributeEncodingException;
 
     /**
@@ -246,7 +246,7 @@ public abstract class AbstractSAMLAttributeTranscoder<AttributeType extends SAML
      * 
      * @param profileRequestContext current profile request
      * @param attribute the attribute being decoded
-     * @param properties properties to control decoding
+     * @param rule properties to control decoding
      * @param attributeValues the decoded values for the attribute
      * 
      * @return the IdPAttribute object
@@ -255,7 +255,7 @@ public abstract class AbstractSAMLAttributeTranscoder<AttributeType extends SAML
      */
     @Nonnull protected abstract IdPAttribute buildIdPAttribute(
             @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final AttributeType attribute,
-            @Nonnull final Properties properties,
+            @Nonnull final TranscodingRule rule,
             @Nonnull @NonnullElements final List<IdPAttributeValue<?>> attributeValues)
                     throws AttributeDecodingException;
     
@@ -273,13 +273,13 @@ public abstract class AbstractSAMLAttributeTranscoder<AttributeType extends SAML
      * 
      * @param profileRequestContext current profile request
      * @param attribute the attribute being decoded
-     * @param properties properties to control decoding
+     * @param rule properties to control decoding
      * @param value the value to decode
      * 
      * @return the returned final {@link IdPAttributeValue} or null if decoding failed
      */
     @Nullable protected abstract IdPAttributeValue<?> decodeValue(
             @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final AttributeType attribute,
-            @Nonnull final Properties properties, @Nullable final XMLObject value);
+            @Nonnull final TranscodingRule rule, @Nullable final XMLObject value);
 
 }
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ByteAttributeTranscoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ByteAttributeTranscoder.java
index 433a511..02f500c 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ByteAttributeTranscoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ByteAttributeTranscoder.java
@@ -17,8 +17,6 @@
 
 package net.shibboleth.idp.saml.attribute.transcoding.impl;
 
-import java.util.Properties;
-
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
@@ -26,6 +24,7 @@ import net.shibboleth.idp.attribute.AttributeEncodingException;
 import net.shibboleth.idp.attribute.ByteAttributeValue;
 import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.saml.attribute.transcoding.SAMLEncoderSupport;
 import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML1AttributeTranscoder;
 import net.shibboleth.utilities.java.support.codec.Base64Support;
@@ -54,20 +53,19 @@ public class SAML1ByteAttributeTranscoder extends AbstractSAML1AttributeTranscod
 
     /** {@inheritDoc} */
     @Override @Nullable protected XMLObject encodeValue(@Nullable final ProfileRequestContext profileRequestContext,
-            @Nonnull final IdPAttribute attribute, @Nonnull final Properties properties,
+            @Nonnull final IdPAttribute attribute, @Nonnull final TranscodingRule rule,
             @Nonnull final ByteAttributeValue value) throws AttributeEncodingException {
                 
-        final Object encodeType = properties.getOrDefault(PROP_ENCODE_TYPE, Boolean.TRUE);
+        final Boolean encodeType = rule.getOrDefault(PROP_ENCODE_TYPE, Boolean.class, Boolean.TRUE);
 
-        return SAMLEncoderSupport.encodeByteArrayValue(attribute,
-                AttributeValue.DEFAULT_ELEMENT_NAME, value.getValue(),
-                encodeType instanceof Boolean ? (Boolean) encodeType : true);
+        return SAMLEncoderSupport.encodeByteArrayValue(attribute, AttributeValue.DEFAULT_ELEMENT_NAME, value.getValue(),
+                encodeType);
     }
 
     /** {@inheritDoc} */
     @Override @Nullable protected IdPAttributeValue<?> decodeValue(
             @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final AttributeDesignator attribute,
-            @Nonnull final Properties properties, @Nullable final XMLObject value) {
+            @Nonnull final TranscodingRule rule, @Nullable final XMLObject value) {
         
         final String s = getStringValue(value);
         if (null == s) {
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ScopedStringAttributeTranscoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ScopedStringAttributeTranscoder.java
index 26cd26a..4ddefdc 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ScopedStringAttributeTranscoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ScopedStringAttributeTranscoder.java
@@ -17,8 +17,6 @@
 
 package net.shibboleth.idp.saml.attribute.transcoding.impl;
 
-import java.util.Properties;
-
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.xml.namespace.QName;
@@ -27,6 +25,7 @@ import net.shibboleth.idp.attribute.AttributeEncodingException;
 import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.attribute.IdPAttributeValue;
 import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML1AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAMLEncoderSupport;
 import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
@@ -65,23 +64,21 @@ public class SAML1ScopedStringAttributeTranscoder extends AbstractSAML1Attribute
 
     /** {@inheritDoc} */
     @Override @Nullable protected XMLObject encodeValue(@Nullable final ProfileRequestContext profileRequestContext,
-            @Nonnull final IdPAttribute attribute, @Nonnull final Properties properties,
+            @Nonnull final IdPAttribute attribute, @Nonnull final TranscodingRule rule,
             @Nonnull final ScopedStringAttributeValue value) throws AttributeEncodingException {
                 
-        final Object encodeType = properties.getOrDefault(PROP_ENCODE_TYPE, Boolean.TRUE);
+        final Boolean encodeType = rule.getOrDefault(PROP_ENCODE_TYPE, Boolean.class, Boolean.TRUE);
 
-        final String scopeType = properties.getProperty(PROP_SCOPE_TYPE, "attribute");
+        final String scopeType = rule.getOrDefault(PROP_SCOPE_TYPE, String.class, "attribute");
         
         if ("attribute".equals(scopeType)) {
-            final String scopeAttributeName = properties.getProperty(PROP_SCOPE_ATTR_NAME, "Scope");
+            final String scopeAttributeName = rule.getOrDefault(PROP_SCOPE_ATTR_NAME, String.class, "Scope");
             return SAMLEncoderSupport.encodeScopedStringValueAttribute(attribute,
-                    AttributeValue.DEFAULT_ELEMENT_NAME, value, scopeAttributeName,
-                    encodeType instanceof Boolean ? (Boolean) encodeType : true);
+                    AttributeValue.DEFAULT_ELEMENT_NAME, value, scopeAttributeName, encodeType);
         } else if ("inline".equals(scopeType)) {
-            final String scopeDelimiter = properties.getProperty(PROP_SCOPE_DELIMITER, "@");
+            final String scopeDelimiter = rule.getOrDefault(PROP_SCOPE_DELIMITER, String.class, "@");
             return SAMLEncoderSupport.encodeScopedStringValueInline(
-                    attribute, AttributeValue.DEFAULT_ELEMENT_NAME, value, scopeDelimiter,
-                    encodeType instanceof Boolean ? (Boolean) encodeType : true);
+                    attribute, AttributeValue.DEFAULT_ELEMENT_NAME, value, scopeDelimiter, encodeType);
         } else {
             throw new AttributeEncodingException("Invalid scopeType property (must be inline or attribute)");
         }
@@ -90,7 +87,7 @@ public class SAML1ScopedStringAttributeTranscoder extends AbstractSAML1Attribute
     /** {@inheritDoc} */
     @Override @Nullable protected IdPAttributeValue<?> decodeValue(
             @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final AttributeDesignator attribute,
-            @Nonnull final Properties properties, @Nullable final XMLObject value) {
+            @Nonnull final TranscodingRule rule, @Nullable final XMLObject value) {
         
         if (value == null) {
             return null;
@@ -101,12 +98,11 @@ public class SAML1ScopedStringAttributeTranscoder extends AbstractSAML1Attribute
             return null;
         }
 
-        final String scopeType = properties.getProperty(PROP_SCOPE_TYPE, "attribute");
+        final String scopeType = rule.getOrDefault(PROP_SCOPE_TYPE, String.class, "attribute");
         if ("attribute".equals(scopeType)) {
-            
             if (value instanceof AttributeExtensibleXMLObject) {
                 final String scopeValue = ((AttributeExtensibleXMLObject) value).getUnknownAttributes().get(
-                        new QName(properties.getProperty(PROP_SCOPE_ATTR_NAME, "Scope")));
+                        new QName(rule.getOrDefault(PROP_SCOPE_ATTR_NAME, String.class, "Scope")));
 
                 if (scopeValue == null) {
                     log.warn("Scope not found in designated XML attribute");
@@ -119,7 +115,7 @@ public class SAML1ScopedStringAttributeTranscoder extends AbstractSAML1Attribute
                 return null;
             }
         } else if ("inline".equals(scopeType)) {
-            final String scopeDelimiter = properties.getProperty(PROP_SCOPE_DELIMITER, "@");
+            final String scopeDelimiter = rule.getOrDefault(PROP_SCOPE_DELIMITER, String.class, "@");
             final int offset = stringValue.indexOf(scopeDelimiter);
             if (offset < 0) {
                 log.warn("Ignoring value with no scope delimiter ({})", scopeDelimiter);
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1StringAttributeTranscoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1StringAttributeTranscoder.java
index 02bea67..3e595ad 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1StringAttributeTranscoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1StringAttributeTranscoder.java
@@ -17,8 +17,6 @@
 
 package net.shibboleth.idp.saml.attribute.transcoding.impl;
 
-import java.util.Properties;
-
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
@@ -28,6 +26,7 @@ import net.shibboleth.idp.attribute.IdPAttributeValue;
 import net.shibboleth.idp.attribute.LocalizedStringAttributeValue;
 import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
 import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML1AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAMLEncoderSupport;
 
@@ -55,7 +54,7 @@ public class SAML1StringAttributeTranscoder extends AbstractSAML1AttributeTransc
 
     /** {@inheritDoc} */
     @Override @Nullable protected XMLObject encodeValue(@Nullable final ProfileRequestContext profileRequestContext,
-            @Nonnull final IdPAttribute attribute, @Nonnull final Properties properties,
+            @Nonnull final IdPAttribute attribute, @Nonnull final TranscodingRule rule,
             @Nonnull final StringAttributeValue value) throws AttributeEncodingException {
         
         if (value instanceof LocalizedStringAttributeValue || value instanceof ScopedStringAttributeValue) {
@@ -63,17 +62,16 @@ public class SAML1StringAttributeTranscoder extends AbstractSAML1AttributeTransc
                     attribute.getId(), value.getClass().getSimpleName());
         }
         
-        final Object encodeType = properties.getOrDefault(PROP_ENCODE_TYPE, Boolean.TRUE);
+        final Boolean encodeType = rule.getOrDefault(PROP_ENCODE_TYPE, Boolean.class, Boolean.TRUE);
         
-        return SAMLEncoderSupport.encodeStringValue(attribute,
-                AttributeValue.DEFAULT_ELEMENT_NAME, value.getValue(),
-                encodeType instanceof Boolean ? (Boolean) encodeType : true);
+        return SAMLEncoderSupport.encodeStringValue(attribute, AttributeValue.DEFAULT_ELEMENT_NAME, value.getValue(),
+                encodeType);
     }
 
     /** {@inheritDoc} */
     @Override @Nullable protected IdPAttributeValue<?> decodeValue(
             @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final AttributeDesignator attribute,
-            @Nonnull final Properties properties, @Nullable final XMLObject value) {
+            @Nonnull final TranscodingRule rule, @Nullable final XMLObject value) {
         
         return value != null ? StringAttributeValue.valueOf(getStringValue(value)) : null;
     }
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1XMLObjectAttributeTranscoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1XMLObjectAttributeTranscoder.java
index c46c277..761ce51 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1XMLObjectAttributeTranscoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1XMLObjectAttributeTranscoder.java
@@ -18,7 +18,6 @@
 package net.shibboleth.idp.saml.attribute.transcoding.impl;
 
 import java.util.List;
-import java.util.Properties;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -27,6 +26,7 @@ import net.shibboleth.idp.attribute.AttributeEncodingException;
 import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.attribute.IdPAttributeValue;
 import net.shibboleth.idp.attribute.XMLObjectAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML1AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAMLEncoderSupport;
 import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
@@ -58,7 +58,7 @@ public class SAML1XMLObjectAttributeTranscoder extends AbstractSAML1AttributeTra
 
     /** {@inheritDoc} */
     @Override @Nullable protected XMLObject encodeValue(@Nullable final ProfileRequestContext profileRequestContext,
-            @Nonnull final IdPAttribute attribute, @Nonnull final Properties properties,
+            @Nonnull final IdPAttribute attribute, @Nonnull final TranscodingRule rule,
             @Nonnull final XMLObjectAttributeValue value) throws AttributeEncodingException {
 
         return SAMLEncoderSupport.encodeXMLObjectValue(attribute, AttributeValue.DEFAULT_ELEMENT_NAME,
@@ -68,14 +68,14 @@ public class SAML1XMLObjectAttributeTranscoder extends AbstractSAML1AttributeTra
     /** {@inheritDoc} */
     @Override @Nullable protected IdPAttributeValue<?> decodeValue(
             @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final AttributeDesignator attribute,
-            @Nonnull final Properties properties, @Nullable final XMLObject value) {
+            @Nonnull final TranscodingRule rule, @Nullable final XMLObject value) {
 
         if (value == null) {
             return null;
         }
         
-        final Object includeAttributeValue = properties.getOrDefault(PROP_INCLUDE_ATTR_VALUE, Boolean.FALSE);
-        if (includeAttributeValue instanceof Boolean && (Boolean) includeAttributeValue) {
+        final Boolean includeAttributeValue = rule.getOrDefault(PROP_INCLUDE_ATTR_VALUE, Boolean.class, Boolean.FALSE);
+        if (includeAttributeValue) {
             return new XMLObjectAttributeValue(value);
         }
         
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ByteAttributeTranscoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ByteAttributeTranscoder.java
index 550711a..b58a3d4 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ByteAttributeTranscoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ByteAttributeTranscoder.java
@@ -17,8 +17,6 @@
 
 package net.shibboleth.idp.saml.attribute.transcoding.impl;
 
-import java.util.Properties;
-
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
@@ -26,6 +24,7 @@ import net.shibboleth.idp.attribute.AttributeEncodingException;
 import net.shibboleth.idp.attribute.ByteAttributeValue;
 import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAMLEncoderSupport;
 import net.shibboleth.utilities.java.support.codec.Base64Support;
@@ -54,20 +53,19 @@ public class SAML2ByteAttributeTranscoder extends AbstractSAML2AttributeTranscod
 
     /** {@inheritDoc} */
     @Override @Nullable protected XMLObject encodeValue(@Nullable final ProfileRequestContext profileRequestContext,
-            @Nonnull final IdPAttribute attribute, @Nonnull final Properties properties,
+            @Nonnull final IdPAttribute attribute, @Nonnull final TranscodingRule rule,
             @Nonnull final ByteAttributeValue value) throws AttributeEncodingException {
                 
-        final Object encodeType = properties.getOrDefault(PROP_ENCODE_TYPE, Boolean.TRUE);
+        final Boolean encodeType = rule.getOrDefault(PROP_ENCODE_TYPE, Boolean.class, Boolean.TRUE);
 
-        return SAMLEncoderSupport.encodeByteArrayValue(attribute,
-                AttributeValue.DEFAULT_ELEMENT_NAME, value.getValue(),
-                encodeType instanceof Boolean ? (Boolean) encodeType : true);
+        return SAMLEncoderSupport.encodeByteArrayValue(attribute, AttributeValue.DEFAULT_ELEMENT_NAME, value.getValue(),
+                encodeType);
     }
 
     /** {@inheritDoc} */
     @Override @Nullable protected IdPAttributeValue<?> decodeValue(
             @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final Attribute attribute,
-            @Nonnull final Properties properties, @Nullable final XMLObject value) {
+            @Nonnull final TranscodingRule rule, @Nullable final XMLObject value) {
         
         final String s = getStringValue(value);
         if (null == s) {
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ScopedStringAttributeTranscoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ScopedStringAttributeTranscoder.java
index be0c6b8..5dbdf9b 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ScopedStringAttributeTranscoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ScopedStringAttributeTranscoder.java
@@ -17,8 +17,6 @@
 
 package net.shibboleth.idp.saml.attribute.transcoding.impl;
 
-import java.util.Properties;
-
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.xml.namespace.QName;
@@ -27,6 +25,7 @@ import net.shibboleth.idp.attribute.AttributeEncodingException;
 import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.attribute.IdPAttributeValue;
 import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAMLEncoderSupport;
 import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
@@ -65,23 +64,21 @@ public class SAML2ScopedStringAttributeTranscoder extends AbstractSAML2Attribute
 
     /** {@inheritDoc} */
     @Override @Nullable protected XMLObject encodeValue(@Nullable final ProfileRequestContext profileRequestContext,
-            @Nonnull final IdPAttribute attribute, @Nonnull final Properties properties,
+            @Nonnull final IdPAttribute attribute, @Nonnull final TranscodingRule rule,
             @Nonnull final ScopedStringAttributeValue value) throws AttributeEncodingException {
                 
-        final Object encodeType = properties.getOrDefault(PROP_ENCODE_TYPE, Boolean.TRUE);
+        final Boolean encodeType = rule.getOrDefault(PROP_ENCODE_TYPE, Boolean.class, Boolean.TRUE);
 
-        final String scopeType = properties.getProperty(PROP_SCOPE_TYPE, "inline");
+        final String scopeType = rule.getOrDefault(PROP_SCOPE_TYPE, String.class, "inline");
         
         if ("attribute".equals(scopeType)) {
-            final String scopeAttributeName = properties.getProperty(PROP_SCOPE_ATTR_NAME, "Scope");
+            final String scopeAttributeName = rule.getOrDefault(PROP_SCOPE_ATTR_NAME, String.class, "Scope");
             return SAMLEncoderSupport.encodeScopedStringValueAttribute(attribute,
-                    AttributeValue.DEFAULT_ELEMENT_NAME, value, scopeAttributeName,
-                    encodeType instanceof Boolean ? (Boolean) encodeType : true);
+                    AttributeValue.DEFAULT_ELEMENT_NAME, value, scopeAttributeName, encodeType);
         } else if ("inline".equals(scopeType)) {
-            final String scopeDelimiter = properties.getProperty(PROP_SCOPE_DELIMITER, "@");
+            final String scopeDelimiter = rule.getOrDefault(PROP_SCOPE_DELIMITER, String.class, "@");
             return SAMLEncoderSupport.encodeScopedStringValueInline(
-                    attribute, AttributeValue.DEFAULT_ELEMENT_NAME, value, scopeDelimiter,
-                    encodeType instanceof Boolean ? (Boolean) encodeType : true);
+                    attribute, AttributeValue.DEFAULT_ELEMENT_NAME, value, scopeDelimiter, encodeType);
         } else {
             throw new AttributeEncodingException("Invalid scopeType property (must be inline or attribute)");
         }
@@ -90,7 +87,7 @@ public class SAML2ScopedStringAttributeTranscoder extends AbstractSAML2Attribute
     /** {@inheritDoc} */
     @Override @Nullable protected IdPAttributeValue<?> decodeValue(
             @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final Attribute attribute,
-            @Nonnull final Properties properties, @Nullable final XMLObject value) {
+            @Nonnull final TranscodingRule rule, @Nullable final XMLObject value) {
         
         if (value == null) {
             return null;
@@ -101,12 +98,12 @@ public class SAML2ScopedStringAttributeTranscoder extends AbstractSAML2Attribute
             return null;
         }
 
-        final String scopeType = properties.getProperty(PROP_SCOPE_TYPE, "inline");
+        final String scopeType = rule.getOrDefault(PROP_SCOPE_TYPE, String.class, "inline");
         if ("attribute".equals(scopeType)) {
             
             if (value instanceof AttributeExtensibleXMLObject) {
                 final String scopeValue = ((AttributeExtensibleXMLObject) value).getUnknownAttributes().get(
-                        new QName(null, properties.getProperty(PROP_SCOPE_ATTR_NAME, "Scope")));
+                        new QName(null, rule.getOrDefault(PROP_SCOPE_ATTR_NAME, String.class, "Scope")));
                 if (scopeValue == null) {
                     log.warn("Scope not found in designated XML attribute");
                     return null;
@@ -119,7 +116,7 @@ public class SAML2ScopedStringAttributeTranscoder extends AbstractSAML2Attribute
                 return null;
             }
         } else if ("inline".equals(scopeType)) {
-            final String scopeDelimiter = properties.getProperty(PROP_SCOPE_DELIMITER, "@");
+            final String scopeDelimiter = rule.getOrDefault(PROP_SCOPE_DELIMITER, String.class, "@");
             final int offset = stringValue.indexOf(scopeDelimiter);
             if (offset < 0) {
                 log.warn("Ignoring value with no scope delimiter ({})", scopeDelimiter);
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2StringAttributeTranscoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2StringAttributeTranscoder.java
index 682cb6e..64d95b8 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2StringAttributeTranscoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2StringAttributeTranscoder.java
@@ -17,8 +17,6 @@
 
 package net.shibboleth.idp.saml.attribute.transcoding.impl;
 
-import java.util.Properties;
-
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
@@ -28,6 +26,7 @@ import net.shibboleth.idp.attribute.IdPAttributeValue;
 import net.shibboleth.idp.attribute.LocalizedStringAttributeValue;
 import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
 import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAMLEncoderSupport;
 
@@ -55,7 +54,7 @@ public class SAML2StringAttributeTranscoder extends AbstractSAML2AttributeTransc
 
     /** {@inheritDoc} */
     @Override @Nullable protected XMLObject encodeValue(@Nullable final ProfileRequestContext profileRequestContext,
-            @Nonnull final IdPAttribute attribute, @Nonnull final Properties properties,
+            @Nonnull final IdPAttribute attribute, @Nonnull final TranscodingRule rule,
             @Nonnull final StringAttributeValue value) throws AttributeEncodingException {
         
         if (value instanceof LocalizedStringAttributeValue || value instanceof ScopedStringAttributeValue) {
@@ -63,17 +62,16 @@ public class SAML2StringAttributeTranscoder extends AbstractSAML2AttributeTransc
                     attribute.getId(), value.getClass().getSimpleName());
         }
         
-        final Object encodeType = properties.getOrDefault(PROP_ENCODE_TYPE, Boolean.TRUE);
+        final Boolean encodeType = rule.getOrDefault(PROP_ENCODE_TYPE, Boolean.class, Boolean.TRUE);
         
-        return SAMLEncoderSupport.encodeStringValue(attribute,
-                AttributeValue.DEFAULT_ELEMENT_NAME, value.getValue(),
-                encodeType instanceof Boolean ? (Boolean) encodeType : true);
+        return SAMLEncoderSupport.encodeStringValue(attribute, AttributeValue.DEFAULT_ELEMENT_NAME, value.getValue(),
+                encodeType);
     }
 
     /** {@inheritDoc} */
     @Override @Nullable protected IdPAttributeValue<?> decodeValue(
             @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final Attribute attribute,
-            @Nonnull final Properties properties, @Nullable final XMLObject value) {
+            @Nonnull final TranscodingRule rule, @Nullable final XMLObject value) {
         
         return value != null ? StringAttributeValue.valueOf(getStringValue(value)) : null;
     }
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2XMLObjectAttributeTranscoder.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2XMLObjectAttributeTranscoder.java
index 4352cb9..6d9ee65 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2XMLObjectAttributeTranscoder.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2XMLObjectAttributeTranscoder.java
@@ -18,7 +18,6 @@
 package net.shibboleth.idp.saml.attribute.transcoding.impl;
 
 import java.util.List;
-import java.util.Properties;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -27,6 +26,7 @@ import net.shibboleth.idp.attribute.AttributeEncodingException;
 import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.attribute.IdPAttributeValue;
 import net.shibboleth.idp.attribute.XMLObjectAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAMLEncoderSupport;
 import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
@@ -58,7 +58,7 @@ public class SAML2XMLObjectAttributeTranscoder extends AbstractSAML2AttributeTra
 
     /** {@inheritDoc} */
     @Override @Nullable protected XMLObject encodeValue(@Nullable final ProfileRequestContext profileRequestContext,
-            @Nonnull final IdPAttribute attribute, @Nonnull final Properties properties,
+            @Nonnull final IdPAttribute attribute, @Nonnull final TranscodingRule rule,
             @Nonnull final XMLObjectAttributeValue value) throws AttributeEncodingException {
 
         return SAMLEncoderSupport.encodeXMLObjectValue(attribute, AttributeValue.DEFAULT_ELEMENT_NAME,
@@ -68,14 +68,14 @@ public class SAML2XMLObjectAttributeTranscoder extends AbstractSAML2AttributeTra
     /** {@inheritDoc} */
     @Override @Nullable protected IdPAttributeValue<?> decodeValue(
             @Nullable final ProfileRequestContext profileRequestContext, @Nonnull final Attribute attribute,
-            @Nonnull final Properties properties, @Nullable final XMLObject value) {
+            @Nonnull final TranscodingRule rule, @Nullable final XMLObject value) {
 
         if (value == null) {
             return null;
         }
         
-        final Object includeAttributeValue = properties.getOrDefault(PROP_INCLUDE_ATTR_VALUE, Boolean.FALSE);
-        if (includeAttributeValue instanceof Boolean && (Boolean) includeAttributeValue) {
+        final Boolean includeAttributeValue = rule.getOrDefault(PROP_INCLUDE_ATTR_VALUE, Boolean.class, Boolean.FALSE);
+        if (includeAttributeValue) {
             return new XMLObjectAttributeValue(value);
         }
         
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/metadata/impl/AttributeMappingNodeProcessor.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/metadata/impl/AttributeMappingNodeProcessor.java
index 919434f..e2e8c72 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/metadata/impl/AttributeMappingNodeProcessor.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/metadata/impl/AttributeMappingNodeProcessor.java
@@ -19,7 +19,6 @@ package net.shibboleth.idp.saml.metadata.impl;
 
 import java.util.Collection;
 import java.util.List;
-import java.util.Properties;
 
 import javax.annotation.Nonnull;
 import javax.annotation.concurrent.NotThreadSafe;
@@ -30,6 +29,7 @@ import net.shibboleth.idp.attribute.IdPRequestedAttribute;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoder;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
 import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.saml.attribute.transcoding.AttributesMapContainer;
 import net.shibboleth.utilities.java.support.annotation.constraint.Live;
 import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
@@ -185,9 +185,9 @@ public class AttributeMappingNodeProcessor implements MetadataNodeProcessor {
             @Nonnull final T input, @Nonnull @NonnullElements @Live final Multimap<String,IdPAttribute> results)
                     throws AttributeDecodingException {
         
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(input);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(input);
         
-        for (final Properties rules : rulesets) {
+        for (final TranscodingRule rules : rulesets) {
             final AttributeTranscoder<T> transcoder = TranscoderSupport.getTranscoder(rules);
             final IdPAttribute decodedAttribute = transcoder.decode(null, input, rules);
             if (decodedAttribute != null) {
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseAddAttributeStatementToAssertion.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseAddAttributeStatementToAssertion.java
index e281a8a..bcadefb 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseAddAttributeStatementToAssertion.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseAddAttributeStatementToAssertion.java
@@ -18,7 +18,6 @@
 package net.shibboleth.idp.saml.profile.impl;
 
 import java.util.Collection;
-import java.util.Properties;
 import java.util.function.Function;
 
 import javax.annotation.Nonnull;
@@ -30,6 +29,7 @@ import net.shibboleth.idp.attribute.context.AttributeContext;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoder;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
 import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.profile.AbstractProfileAction;
 import net.shibboleth.idp.profile.config.navigate.IdentifierGenerationStrategyLookupFunction;
 import net.shibboleth.idp.profile.context.RelyingPartyContext;
@@ -316,7 +316,7 @@ public abstract class BaseAddAttributeStatementToAssertion<T extends SAMLObject>
             @Nonnull final Class<T> to, @Nonnull @NonnullElements @Live final Collection<T> results)
                     throws AttributeEncodingException {
         
-        final Collection<Properties> transcodingRules = registry.getTranscodingProperties(attribute, to);
+        final Collection<TranscodingRule> transcodingRules = registry.getTranscodingRules(attribute, to);
         if (transcodingRules.isEmpty()) {
             log.debug("{} Attribute {} does not have any transcoding rules, nothing to do", getLogPrefix(),
                     attribute.getId());
@@ -325,7 +325,7 @@ public abstract class BaseAddAttributeStatementToAssertion<T extends SAMLObject>
         
         int count = 0;
         
-        for (final Properties rules : transcodingRules) {
+        for (final TranscodingRule rules : transcodingRules) {
             try {
                 final AttributeTranscoder<T> transcoder = TranscoderSupport.<T>getTranscoder(rules);
                 final T encodedAttribute = transcoder.encode(profileRequestContext, attribute, to, rules);
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/FilterByQueriedAttributeDesignators.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/FilterByQueriedAttributeDesignators.java
index e8dfbff..b773978 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/FilterByQueriedAttributeDesignators.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/FilterByQueriedAttributeDesignators.java
@@ -20,7 +20,6 @@ package net.shibboleth.idp.saml.saml1.profile.impl;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
-import java.util.Properties;
 import java.util.Set;
 import java.util.function.Function;
 
@@ -45,6 +44,7 @@ import net.shibboleth.idp.attribute.context.AttributeContext;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoder;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
 import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.profile.AbstractProfileAction;
 import net.shibboleth.idp.profile.context.RelyingPartyContext;
 import net.shibboleth.utilities.java.support.annotation.constraint.Live;
@@ -228,13 +228,13 @@ public class FilterByQueriedAttributeDesignators extends AbstractProfileAction {
             @Nonnull @NonnullElements @Live final Collection<String> results)
                     throws AttributeDecodingException {
         
-        final Collection<Properties> transcodingRules = registry.getTranscodingProperties(input);
+        final Collection<TranscodingRule> transcodingRules = registry.getTranscodingRules(input);
         if (transcodingRules.isEmpty()) {
             throw new AttributeDecodingException("No transcoding rule for AttributeDesignator '" +
                     input.getAttributeName() + "'");
         }
         
-        for (final Properties rules : transcodingRules) {
+        for (final TranscodingRule rules : transcodingRules) {
             final AttributeTranscoder<AttributeDesignator> transcoder = TranscoderSupport.getTranscoder(rules);
             final IdPAttribute decodedAttribute = transcoder.decode(profileRequestContext, input, rules);
             if (decodedAttribute != null) {
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/FilterByQueriedAttributes.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/FilterByQueriedAttributes.java
index 6f0061a..2c75274 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/FilterByQueriedAttributes.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/FilterByQueriedAttributes.java
@@ -19,7 +19,6 @@ package net.shibboleth.idp.saml.saml2.profile.impl;
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Properties;
 import java.util.function.Function;
 
 import javax.annotation.Nonnull;
@@ -46,6 +45,7 @@ import net.shibboleth.idp.attribute.context.AttributeContext;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoder;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
 import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.profile.AbstractProfileAction;
 import net.shibboleth.idp.profile.context.RelyingPartyContext;
 import net.shibboleth.utilities.java.support.annotation.constraint.Live;
@@ -238,12 +238,12 @@ public class FilterByQueriedAttributes extends AbstractProfileAction {
             @Nonnull @NonnullElements @Live final Multimap<String,IdPAttribute> results)
                     throws AttributeDecodingException {
         
-        final Collection<Properties> transcodingRules = registry.getTranscodingProperties(input);
+        final Collection<TranscodingRule> transcodingRules = registry.getTranscodingRules(input);
         if (transcodingRules.isEmpty()) {
             throw new AttributeDecodingException("No transcoding rule for Attribute '" + input.getName() + "'");
         }
         
-        for (final Properties rules : transcodingRules) {
+        for (final TranscodingRule rules : transcodingRules) {
             final AttributeTranscoder<Attribute> transcoder = TranscoderSupport.getTranscoder(rules);
             final IdPAttribute decodedAttribute = transcoder.decode(profileRequestContext, input, rules);
             if (decodedAttribute != null) {
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ByteAttributeTranscoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ByteAttributeTranscoderTest.java
index 8047cc4..ebce4b8 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ByteAttributeTranscoderTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ByteAttributeTranscoderTest.java
@@ -23,7 +23,6 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Properties;
 
 import net.shibboleth.idp.attribute.AttributeDecodingException;
 import net.shibboleth.idp.attribute.AttributeEncodingException;
@@ -35,8 +34,8 @@ import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
 import net.shibboleth.idp.attribute.StringAttributeValue;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
 import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
-import net.shibboleth.idp.attribute.transcoding.impl.TranscodingRule;
 import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML1AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAML1AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
@@ -114,9 +113,9 @@ public class SAML1ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
     @Test(expectedExceptions = {AttributeEncodingException.class,}) public void emptyEncode() throws Exception {
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -125,9 +124,9 @@ public class SAML1ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
     @Test public void emptyRequestedEncode() throws Exception {
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, AttributeDesignator.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, AttributeDesignator.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final AttributeDesignator attr = TranscoderSupport.<AttributeDesignator>getTranscoder(ruleset).encode(
                 null, inputAttribute, AttributeDesignator.class, ruleset);
@@ -144,9 +143,9 @@ public class SAML1ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
         samlAttribute.setAttributeName(ATTR_NAME);
         samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -161,9 +160,9 @@ public class SAML1ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
         samlAttribute.setAttributeName(ATTR_NAME);
         samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<AttributeDesignator>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -189,9 +188,9 @@ public class SAML1ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(null, inputAttribute, Attribute.class, ruleset);
     }
@@ -203,9 +202,9 @@ public class SAML1ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
         
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -238,9 +237,9 @@ public class SAML1ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
         final IdPRequestedAttribute inputAttribute = new IdPRequestedAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
         
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
 
         final AttributeDesignator attr = TranscoderSupport.<AttributeDesignator>getTranscoder(ruleset).encode(
                 null, inputAttribute, AttributeDesignator.class, ruleset);
@@ -260,9 +259,9 @@ public class SAML1ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
         samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
         samlAttribute.getAttributeValues().add(stringValue);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -282,9 +281,9 @@ public class SAML1ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
         samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
         samlAttribute.getAttributeValues().add(stringValue);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
     }
@@ -296,9 +295,9 @@ public class SAML1ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -353,9 +352,9 @@ public class SAML1ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
         samlAttribute.getAttributeValues().add(stringValue);
         samlAttribute.getAttributeValues().add(stringValue2);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ScopedStringAttributeTranscoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ScopedStringAttributeTranscoderTest.java
index 3d689e7..1071168 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ScopedStringAttributeTranscoderTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1ScopedStringAttributeTranscoderTest.java
@@ -23,7 +23,6 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Properties;
 
 import net.shibboleth.idp.attribute.AttributeEncodingException;
 import net.shibboleth.idp.attribute.ByteAttributeValue;
@@ -34,8 +33,8 @@ import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
 import net.shibboleth.idp.attribute.StringAttributeValue;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
 import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
-import net.shibboleth.idp.attribute.transcoding.impl.TranscodingRule;
 import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML1AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAML1AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
@@ -123,9 +122,9 @@ public class SAML1ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTe
     @Test(expectedExceptions = {AttributeEncodingException.class,}) public void emptyEncode() throws Exception {
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(null, inputAttribute, Attribute.class, ruleset);
     }
@@ -137,9 +136,9 @@ public class SAML1ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTe
         samlAttribute.setAttributeName(ATTR_NAME);
         samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -154,9 +153,9 @@ public class SAML1ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTe
         samlAttribute.setAttributeName(ATTR_NAME);
         samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<AttributeDesignator>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -183,9 +182,9 @@ public class SAML1ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTe
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(null, inputAttribute, Attribute.class, ruleset);
     }
@@ -200,9 +199,9 @@ public class SAML1ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTe
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
         
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -236,9 +235,9 @@ public class SAML1ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTe
         final IdPRequestedAttribute inputAttribute = new IdPRequestedAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
         
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
 
         final AttributeDesignator attr = TranscoderSupport.<AttributeDesignator>getTranscoder(ruleset).encode(
                 null, inputAttribute, AttributeDesignator.class, ruleset);
@@ -260,9 +259,9 @@ public class SAML1ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTe
         samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
         samlAttribute.getAttributeValues().add(scopedValue);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -284,9 +283,9 @@ public class SAML1ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTe
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -350,9 +349,9 @@ public class SAML1ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTe
         samlAttribute.getAttributeValues().add(stringValue3);
         samlAttribute.getAttributeValues().add(stringValue4);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1StringAttributeTranscoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1StringAttributeTranscoderTest.java
index 0534a08..ad33578 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1StringAttributeTranscoderTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML1StringAttributeTranscoderTest.java
@@ -23,7 +23,6 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Properties;
 
 import net.shibboleth.idp.attribute.AttributeEncodingException;
 import net.shibboleth.idp.attribute.ByteAttributeValue;
@@ -34,8 +33,8 @@ import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
 import net.shibboleth.idp.attribute.StringAttributeValue;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
 import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
-import net.shibboleth.idp.attribute.transcoding.impl.TranscodingRule;
 import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML1AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAML1AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
@@ -111,9 +110,9 @@ public class SAML1StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
     @Test(expectedExceptions = {AttributeEncodingException.class,}) public void emptyEncode() throws Exception {
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -122,9 +121,9 @@ public class SAML1StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
     @Test public void emptyRequestedEncode() throws Exception {
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, AttributeDesignator.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, AttributeDesignator.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final AttributeDesignator attr = TranscoderSupport.<AttributeDesignator>getTranscoder(ruleset).encode(
                 null, inputAttribute, AttributeDesignator.class, ruleset);
@@ -141,9 +140,9 @@ public class SAML1StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
         samlAttribute.setAttributeName(ATTR_NAME);
         samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -158,9 +157,9 @@ public class SAML1StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
         samlAttribute.setAttributeName(ATTR_NAME);
         samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<AttributeDesignator>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -187,9 +186,9 @@ public class SAML1StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(null, inputAttribute, Attribute.class, ruleset);
     }
@@ -201,9 +200,9 @@ public class SAML1StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
         
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -235,9 +234,9 @@ public class SAML1StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
         final IdPRequestedAttribute inputAttribute = new IdPRequestedAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
         
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
 
         final AttributeDesignator attr = TranscoderSupport.<AttributeDesignator>getTranscoder(ruleset).encode(
                 null, inputAttribute, AttributeDesignator.class, ruleset);
@@ -257,9 +256,9 @@ public class SAML1StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
         samlAttribute.setAttributeNamespace(ATTR_NAMESPACE);
         samlAttribute.getAttributeValues().add(stringValue);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -279,9 +278,9 @@ public class SAML1StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -312,9 +311,9 @@ public class SAML1StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
         samlAttribute.getAttributeValues().add(stringValue);
         samlAttribute.getAttributeValues().add(stringValue2);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ByteAttributeTranscoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ByteAttributeTranscoderTest.java
index e87c469..203a93c 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ByteAttributeTranscoderTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ByteAttributeTranscoderTest.java
@@ -23,7 +23,6 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Properties;
 
 import net.shibboleth.idp.attribute.AttributeDecodingException;
 import net.shibboleth.idp.attribute.AttributeEncodingException;
@@ -35,8 +34,8 @@ import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
 import net.shibboleth.idp.attribute.StringAttributeValue;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
 import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
-import net.shibboleth.idp.attribute.transcoding.impl.TranscodingRule;
 import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAML2AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
@@ -116,9 +115,9 @@ public class SAML2ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
     @Test public void emptyEncode() throws Exception {
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -136,9 +135,9 @@ public class SAML2ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
         samlAttribute.setName(ATTR_NAME);
         samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -154,9 +153,9 @@ public class SAML2ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
         samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
         samlAttribute.setIsRequired(true);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -182,9 +181,9 @@ public class SAML2ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(null, inputAttribute, Attribute.class, ruleset);
     }
@@ -196,9 +195,9 @@ public class SAML2ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
         
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -233,9 +232,9 @@ public class SAML2ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
         inputAttribute.setRequired(true);
         inputAttribute.setValues(values);
         
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
 
         final RequestedAttribute attr = TranscoderSupport.<RequestedAttribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, RequestedAttribute.class, ruleset);
@@ -273,9 +272,9 @@ public class SAML2ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
         samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
         samlAttribute.getAttributeValues().add(stringValue);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -295,9 +294,9 @@ public class SAML2ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
         samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
         samlAttribute.getAttributeValues().add(stringValue);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
     }
@@ -313,9 +312,9 @@ public class SAML2ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
         samlAttribute.setIsRequired(true);
         samlAttribute.getAttributeValues().add(stringValue);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -333,9 +332,9 @@ public class SAML2ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -390,9 +389,9 @@ public class SAML2ByteAttributeTranscoderTest extends OpenSAMLInitBaseTestCase {
         samlAttribute.getAttributeValues().add(stringValue);
         samlAttribute.getAttributeValues().add(stringValue2);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ScopedStringAttributeTranscoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ScopedStringAttributeTranscoderTest.java
index 4e059bf..05d1b7c 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ScopedStringAttributeTranscoderTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2ScopedStringAttributeTranscoderTest.java
@@ -23,7 +23,6 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Properties;
 
 import net.shibboleth.idp.attribute.AttributeEncodingException;
 import net.shibboleth.idp.attribute.ByteAttributeValue;
@@ -34,8 +33,8 @@ import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
 import net.shibboleth.idp.attribute.StringAttributeValue;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
 import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
-import net.shibboleth.idp.attribute.transcoding.impl.TranscodingRule;
 import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAML2AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
@@ -118,9 +117,9 @@ public class SAML2ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTe
     @Test public void emptyEncode() throws Exception {
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -138,9 +137,9 @@ public class SAML2ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTe
         samlAttribute.setName(ATTR_NAME);
         samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -156,9 +155,9 @@ public class SAML2ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTe
         samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
         samlAttribute.setIsRequired(true);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -185,9 +184,9 @@ public class SAML2ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTe
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(null, inputAttribute, Attribute.class, ruleset);
     }
@@ -202,9 +201,9 @@ public class SAML2ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTe
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
         
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -239,9 +238,9 @@ public class SAML2ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTe
         inputAttribute.setRequired(true);
         inputAttribute.setValues(values);
         
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
 
         final RequestedAttribute attr = TranscoderSupport.<RequestedAttribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, RequestedAttribute.class, ruleset);
@@ -278,9 +277,9 @@ public class SAML2ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTe
         samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
         samlAttribute.getAttributeValues().add(stringValue);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -305,9 +304,9 @@ public class SAML2ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTe
         samlAttribute.setIsRequired(true);
         samlAttribute.getAttributeValues().add(stringValue);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -330,9 +329,9 @@ public class SAML2ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTe
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -374,9 +373,9 @@ public class SAML2ScopedStringAttributeTranscoderTest extends OpenSAMLInitBaseTe
         samlAttribute.getAttributeValues().add(stringValue3);
         samlAttribute.getAttributeValues().add(stringValue4);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2StringAttributeTranscoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2StringAttributeTranscoderTest.java
index e5e2ab3..1182837 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2StringAttributeTranscoderTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2StringAttributeTranscoderTest.java
@@ -23,7 +23,6 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Properties;
 
 import net.shibboleth.idp.attribute.AttributeEncodingException;
 import net.shibboleth.idp.attribute.ByteAttributeValue;
@@ -34,8 +33,8 @@ import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
 import net.shibboleth.idp.attribute.StringAttributeValue;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
 import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
-import net.shibboleth.idp.attribute.transcoding.impl.TranscodingRule;
 import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAML2AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
@@ -113,9 +112,9 @@ public class SAML2StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
     @Test public void emptyEncode() throws Exception {
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -133,9 +132,9 @@ public class SAML2StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
         samlAttribute.setName(ATTR_NAME);
         samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -151,9 +150,9 @@ public class SAML2StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
         samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
         samlAttribute.setIsRequired(true);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -180,9 +179,9 @@ public class SAML2StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(null, inputAttribute, Attribute.class, ruleset);
     }
@@ -194,9 +193,9 @@ public class SAML2StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
         
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -230,9 +229,9 @@ public class SAML2StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
         inputAttribute.setRequired(true);
         inputAttribute.setValues(values);
         
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
 
         final RequestedAttribute attr = TranscoderSupport.<RequestedAttribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, RequestedAttribute.class, ruleset);
@@ -269,9 +268,9 @@ public class SAML2StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
         samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
         samlAttribute.getAttributeValues().add(stringValue);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -293,9 +292,9 @@ public class SAML2StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
         samlAttribute.setIsRequired(true);
         samlAttribute.getAttributeValues().add(stringValue);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -316,9 +315,9 @@ public class SAML2StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -349,9 +348,9 @@ public class SAML2StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
         samlAttribute.getAttributeValues().add(stringValue);
         samlAttribute.getAttributeValues().add(stringValue2);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2XMLObjectAttributeTranscoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2XMLObjectAttributeTranscoderTest.java
index 5b2e6f8..92f1e2c 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2XMLObjectAttributeTranscoderTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2XMLObjectAttributeTranscoderTest.java
@@ -23,7 +23,6 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Properties;
 
 import javax.xml.namespace.QName;
 
@@ -36,8 +35,8 @@ import net.shibboleth.idp.attribute.StringAttributeValue;
 import net.shibboleth.idp.attribute.XMLObjectAttributeValue;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
 import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
-import net.shibboleth.idp.attribute.transcoding.impl.TranscodingRule;
 import net.shibboleth.idp.saml.attribute.transcoding.AbstractSAML2AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAML2AttributeTranscoder;
 import net.shibboleth.idp.saml.attribute.transcoding.SAMLAttributeTranscoder;
@@ -120,9 +119,9 @@ public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestC
     @Test public void emptyEncode() throws Exception {
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -140,9 +139,9 @@ public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestC
         samlAttribute.setName(ATTR_NAME);
         samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -158,9 +157,9 @@ public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestC
         samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
         samlAttribute.setIsRequired(true);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -187,9 +186,9 @@ public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestC
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(null, inputAttribute, Attribute.class, ruleset);
     }
@@ -201,9 +200,9 @@ public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestC
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
         
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -232,9 +231,9 @@ public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestC
         inputAttribute.setRequired(true);
         inputAttribute.setValues(values);
         
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
 
         final RequestedAttribute attr = TranscoderSupport.<RequestedAttribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, RequestedAttribute.class, ruleset);
@@ -269,9 +268,9 @@ public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestC
         samlAttribute.setNameFormat(ATTR_NAMEFORMAT);
         samlAttribute.getAttributeValues().add(attrValue);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -300,9 +299,9 @@ public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestC
         samlAttribute.setIsRequired(true);
         samlAttribute.getAttributeValues().add(attrValue);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
@@ -323,9 +322,9 @@ public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestC
         final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
         inputAttribute.setValues(values);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(inputAttribute, Attribute.class);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(inputAttribute, Attribute.class);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final Attribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).encode(
                 null, inputAttribute, Attribute.class, ruleset);
@@ -371,9 +370,9 @@ public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestC
         samlAttribute.getAttributeValues().add(attrValue);
         samlAttribute.getAttributeValues().add(attrValue2);
 
-        final Collection<Properties> rulesets = registry.getTranscodingProperties(samlAttribute);
+        final Collection<TranscodingRule> rulesets = registry.getTranscodingRules(samlAttribute);
         Assert.assertEquals(rulesets.size(), 1);
-        final Properties ruleset = rulesets.iterator().next();
+        final TranscodingRule ruleset = rulesets.iterator().next();
         
         final IdPAttribute attr = TranscoderSupport.<Attribute>getTranscoder(ruleset).decode(null, samlAttribute, ruleset);
         
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertionTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertionTest.java
index 274928a..a0a4660 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertionTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertionTest.java
@@ -21,7 +21,6 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Properties;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -31,8 +30,8 @@ import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.attribute.StringAttributeValue;
 import net.shibboleth.idp.attribute.context.AttributeContext;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
-import net.shibboleth.idp.attribute.transcoding.impl.TranscodingRule;
 import net.shibboleth.idp.profile.ActionTestingSupport;
 import net.shibboleth.idp.profile.IdPEventIds;
 import net.shibboleth.idp.profile.RequestContextBuilder;
@@ -386,7 +385,7 @@ public class AddAttributeStatementToAssertionTest extends OpenSAMLInitBaseTestCa
         @Override
         @Nullable public Attribute encode(@Nullable final ProfileRequestContext profileRequestContext,
                 @Nonnull final IdPAttribute attribute, @Nonnull final Class<? extends AttributeDesignator> to,
-                @Nonnull final Properties properties) throws AttributeEncodingException {
+                @Nonnull final TranscodingRule rule) throws AttributeEncodingException {
             throw new AttributeEncodingException("Always thrown.");
         }
     }
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertionTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertionTest.java
index 252e802..762877a 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertionTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertionTest.java
@@ -21,7 +21,6 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Properties;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -31,8 +30,8 @@ import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.attribute.StringAttributeValue;
 import net.shibboleth.idp.attribute.context.AttributeContext;
 import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
 import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
-import net.shibboleth.idp.attribute.transcoding.impl.TranscodingRule;
 import net.shibboleth.idp.profile.ActionTestingSupport;
 import net.shibboleth.idp.profile.IdPEventIds;
 import net.shibboleth.idp.profile.RequestContextBuilder;
@@ -385,7 +384,7 @@ public class AddAttributeStatementToAssertionTest extends OpenSAMLInitBaseTestCa
         @Override
         @Nullable public Attribute encode(@Nullable final ProfileRequestContext profileRequestContext,
                 @Nonnull final IdPAttribute attribute, @Nonnull final Class<? extends Attribute> to,
-                @Nonnull final Properties properties) throws AttributeEncodingException {
+                @Nonnull final TranscodingRule rule) throws AttributeEncodingException {
             throw new AttributeEncodingException("Always thrown.");
         }
     }
diff --git a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/saml1Mapper.xml b/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/saml1Mapper.xml
index 8a88e7c..6a2351d 100644
--- a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/saml1Mapper.xml
+++ b/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/saml1Mapper.xml
@@ -17,7 +17,7 @@
         class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML1ScopedStringAttributeTranscoder" />
    
     <bean id="shibboleth.TranscodingRule"
-        class="net.shibboleth.idp.attribute.transcoding.impl.TranscodingRule" abstract="true" />
+        class="net.shibboleth.idp.attribute.transcoding.TranscodingRule" abstract="true" />
    
     <util:list id="DefaultAttributeRegistry">
 
diff --git a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/saml2Mapper.xml b/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/saml2Mapper.xml
index 88f878f..d7543da 100644
--- a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/saml2Mapper.xml
+++ b/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/profile/saml2Mapper.xml
@@ -19,7 +19,7 @@
         class="net.shibboleth.idp.saml.attribute.transcoding.impl.SAML2XMLObjectAttributeTranscoder" />
 
     <bean id="shibboleth.TranscodingRule"
-        class="net.shibboleth.idp.attribute.transcoding.impl.TranscodingRule" abstract="true" />
+        class="net.shibboleth.idp.attribute.transcoding.TranscodingRule" abstract="true" />
 
     <util:list id="DefaultAttributeRegistry">
     

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list