diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/JoranConfiguratorBase.java b/logback-core/src/main/java/ch/qos/logback/core/joran/JoranConfiguratorBase.java index f98ca69c1f..170245d19b 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/JoranConfiguratorBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/JoranConfiguratorBase.java @@ -129,6 +129,8 @@ public SaxEventInterpretationContext getInterpretationContext() { @Override protected void addModelHandlerAssociations(DefaultProcessor defaultProcessor) { + // code moved to ModelClassToModelHandlerLinkerBase + // the code below is inactive defaultProcessor.addHandler(ImportModel.class, ImportModelHandler::makeInstance); defaultProcessor.addHandler(ShutdownHookModel.class, ShutdownHookModelHandler::makeInstance); diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/ImcplicitActionDataForBasicProperty.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/ImcplicitActionDataForBasicProperty.java index 46edae65ca..d9cac398bb 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/ImcplicitActionDataForBasicProperty.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/ImcplicitActionDataForBasicProperty.java @@ -17,7 +17,7 @@ import ch.qos.logback.core.util.AggregationType; /** - * Lump together several fields for use by {@link NestedBasicPropertyIA}. + * Lump together several fields for use by {@link ImcplicitActionDataForBasicProperty}. * * @author Ceki Gulcu */ diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/util/AggregationAssessor.java b/logback-core/src/main/java/ch/qos/logback/core/joran/util/AggregationAssessor.java new file mode 100644 index 0000000000..78e02860ef --- /dev/null +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/util/AggregationAssessor.java @@ -0,0 +1,211 @@ +/* + * Logback: the reliable, generic, fast and flexible logging framework. + * Copyright (C) 1999-2024, QOS.ch. All rights reserved. + * + * This program and the accompanying materials are dual-licensed under + * either the terms of the Eclipse Public License v1.0 as published by + * the Eclipse Foundation + * + * or (per the licensee's choosing) + * + * under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation. + */ + +package ch.qos.logback.core.joran.util; + +import ch.qos.logback.core.joran.spi.DefaultClass; +import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry; +import ch.qos.logback.core.joran.util.beans.BeanDescription; +import ch.qos.logback.core.joran.util.beans.BeanDescriptionCache; +import ch.qos.logback.core.joran.util.beans.BeanUtil; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.util.AggregationType; + +import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * + * Various utility methods for computing the {@link AggregationType} of a given property or + * the class name of a property given implicit rules. + * + *

This class was extracted from {@link PropertySetter}.

+ * + * @since 1.5.1 + */ +public class AggregationAssessor extends ContextAwareBase { + + protected final Class objClass; + protected final BeanDescription beanDescription; + + public AggregationAssessor(BeanDescriptionCache beanDescriptionCache, Class objClass) { + this.objClass = objClass; + this.beanDescription = beanDescriptionCache.getBeanDescription(objClass); + } + + /** + * Given a property name, this method computes/assesses {@link AggregationType} + * for the property for the class passed to the constructor. + * + * @param name + * @return the computed {@link AggregationType} + */ + public AggregationType computeAggregationType(String name) { + String cName = capitalizeFirstLetter(name); + + Method addMethod = findAdderMethod(cName); + + if (addMethod != null) { + AggregationType type = computeRawAggregationType(addMethod); + switch (type) { + case NOT_FOUND: + return AggregationType.NOT_FOUND; + case AS_BASIC_PROPERTY: + return AggregationType.AS_BASIC_PROPERTY_COLLECTION; + + case AS_COMPLEX_PROPERTY: + return AggregationType.AS_COMPLEX_PROPERTY_COLLECTION; + case AS_BASIC_PROPERTY_COLLECTION: + case AS_COMPLEX_PROPERTY_COLLECTION: + addError("Unexpected AggregationType " + type); + } + } + + Method setter = findSetterMethod(name); + if (setter != null) { + return computeRawAggregationType(setter); + } else { + // we have failed + return AggregationType.NOT_FOUND; + } + } + + String capitalizeFirstLetter(String name) { + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + + Method findAdderMethod(String name) { + String propertyName = BeanUtil.toLowerCamelCase(name); + return beanDescription.getAdder(propertyName); + } + + Method findSetterMethod(String name) { + String propertyName = BeanUtil.toLowerCamelCase(name); + return beanDescription.getSetter(propertyName); + } + + private AggregationType computeRawAggregationType(Method method) { + Class parameterClass = getParameterClassForMethod(method); + if (parameterClass == null) { + return AggregationType.NOT_FOUND; + } + if (StringToObjectConverter.canBeBuiltFromSimpleString(parameterClass)) { + return AggregationType.AS_BASIC_PROPERTY; + } else { + return AggregationType.AS_COMPLEX_PROPERTY; + } + } + + private Class getParameterClassForMethod(Method method) { + if (method == null) { + return null; + } + Class[] classArray = method.getParameterTypes(); + if (classArray.length != 1) { + return null; + } else { + return classArray[0]; + } + } + + public Class getClassNameViaImplicitRules(String name, AggregationType aggregationType, + DefaultNestedComponentRegistry registry) { + + Class registryResult = registry.findDefaultComponentType(objClass, name); + if (registryResult != null) { + return registryResult; + } + // find the relevant method for the given property name and aggregationType + Method relevantMethod = getRelevantMethod(name, aggregationType); + if (relevantMethod == null) { + return null; + } + Class byAnnotation = getDefaultClassNameByAnnonation(name, relevantMethod); + if (byAnnotation != null) { + return byAnnotation; + } + return getByConcreteType(name, relevantMethod); + } + + T getAnnotation(String name, Class annonationClass, Method relevantMethod) { + + if (relevantMethod != null) { + return relevantMethod.getAnnotation(annonationClass); + } else { + return null; + } + } + + Class getDefaultClassNameByAnnonation(String name, Method relevantMethod) { + DefaultClass defaultClassAnnon = getAnnotation(name, DefaultClass.class, relevantMethod); + if (defaultClassAnnon != null) { + return defaultClassAnnon.value(); + } + return null; + } + Method getRelevantMethod(String name, AggregationType aggregationType) { + Method relevantMethod; + if (aggregationType == AggregationType.AS_COMPLEX_PROPERTY_COLLECTION) { + relevantMethod = findAdderMethod(name); + } else if (aggregationType == AggregationType.AS_COMPLEX_PROPERTY) { + relevantMethod = findSetterMethod(name); + } else { + throw new IllegalStateException(aggregationType + " not allowed here"); + } + return relevantMethod; + } + + Class getByConcreteType(String name, Method relevantMethod) { + + Class paramType = getParameterClassForMethod(relevantMethod); + if (paramType == null) { + return null; + } + + boolean isUnequivocallyInstantiable = isUnequivocallyInstantiable(paramType); + if (isUnequivocallyInstantiable) { + return paramType; + } else { + return null; + } + } + + /** + * Can the given clazz instantiable with certainty? + * + * @param clazz The class to test for instantiability + * @return true if clazz can be instantiated, and false otherwise. + */ + private boolean isUnequivocallyInstantiable(Class clazz) { + if (clazz.isInterface()) { + return false; + } + // checking for constructors would be more elegant, but in + // classes without any declared constructors, Class.getConstructor() + // returns null. + Object o; + try { + o = clazz.getDeclaredConstructor().newInstance(); + if (o != null) { + return true; + } else { + return false; + } + } catch (InstantiationException | IllegalAccessException | InvocationTargetException + | NoSuchMethodException e) { + return false; + } + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/util/PropertySetter.java b/logback-core/src/main/java/ch/qos/logback/core/joran/util/PropertySetter.java index 100ffd345f..3d29a94458 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/util/PropertySetter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/util/PropertySetter.java @@ -14,19 +14,16 @@ // Contributors: Georg Lundesgaard package ch.qos.logback.core.joran.util; -import java.lang.annotation.Annotation; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import ch.qos.logback.core.joran.spi.DefaultClass; +import ch.qos.logback.core.Context; import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry; import ch.qos.logback.core.joran.util.beans.BeanDescription; import ch.qos.logback.core.joran.util.beans.BeanDescriptionCache; -import ch.qos.logback.core.joran.util.beans.BeanUtil; import ch.qos.logback.core.spi.ContextAwareBase; import ch.qos.logback.core.util.AggregationType; import ch.qos.logback.core.util.PropertySetterException; +import java.lang.reflect.Method; + /** * General purpose Object property setter. Clients repeatedly invokes * {@link #setProperty setProperty(name,value)} in order to invoke setters on @@ -55,6 +52,7 @@ public class PropertySetter extends ContextAwareBase { protected final Object obj; protected final Class objClass; protected final BeanDescription beanDescription; + protected final AggregationAssessor aggregationAssessor; /** * Create a new PropertySetter for the specified Object. This is done in @@ -66,8 +64,16 @@ public PropertySetter(BeanDescriptionCache beanDescriptionCache, Object obj) { this.obj = obj; this.objClass = obj.getClass(); this.beanDescription = beanDescriptionCache.getBeanDescription(objClass); + this.aggregationAssessor = new AggregationAssessor(beanDescriptionCache, this.objClass); } + @Override + public void setContext(Context context) { + super.setContext(context); + aggregationAssessor.setContext(context); + } + + /** * Set a property on this PropertySetter's Object. If successful, this method * will invoke a setter method on the underlying Object. The setter is the one @@ -88,12 +94,12 @@ public void setProperty(String name, String value) { if (value == null) { return; } - Method setter = findSetterMethod(name); + Method setter = aggregationAssessor.findSetterMethod(name); if (setter == null) { addWarn("No setter for property [" + name + "] in " + objClass.getName() + "."); } else { try { - setProperty(setter, name, value); + setProperty(setter, value); } catch (PropertySetterException ex) { addWarn("Failed to set property [" + name + "] to value \"" + value + "\". ", ex); } @@ -101,14 +107,13 @@ public void setProperty(String name, String value) { } /** - * Set the named property given a {@link PropertyDescriptor}. + * Set the named property using a {@link Method setter}. * - * @param prop A PropertyDescriptor describing the characteristics of the + * @param setter A Method describing the characteristics of the * property to set. - * @param name The named of the property to set. * @param value The value of the property. */ - private void setProperty(Method setter, String name, String value) throws PropertySetterException { + private void setProperty(Method setter, String value) throws PropertySetterException { Class[] paramTypes = setter.getParameterTypes(); Object arg; @@ -130,102 +135,51 @@ private void setProperty(Method setter, String name, String value) throws Proper } public AggregationType computeAggregationType(String name) { - String cName = capitalizeFirstLetter(name); - - Method addMethod = findAdderMethod(cName); - - if (addMethod != null) { - AggregationType type = computeRawAggregationType(addMethod); - switch (type) { - case NOT_FOUND: - return AggregationType.NOT_FOUND; - case AS_BASIC_PROPERTY: - return AggregationType.AS_BASIC_PROPERTY_COLLECTION; - - case AS_COMPLEX_PROPERTY: - return AggregationType.AS_COMPLEX_PROPERTY_COLLECTION; - case AS_BASIC_PROPERTY_COLLECTION: - case AS_COMPLEX_PROPERTY_COLLECTION: - addError("Unexpected AggregationType " + type); - } - } - - Method setter = findSetterMethod(name); - if (setter != null) { - return computeRawAggregationType(setter); - } else { - // we have failed - return AggregationType.NOT_FOUND; - } + return this.aggregationAssessor.computeAggregationType(name); } - private Method findAdderMethod(String name) { - String propertyName = BeanUtil.toLowerCamelCase(name); - return beanDescription.getAdder(propertyName); - } +// private Method findAdderMethod(String name) { +// String propertyName = BeanUtil.toLowerCamelCase(name); +// return beanDescription.getAdder(propertyName); +// } +// +// private Method findSetterMethod(String name) { +// String propertyName = BeanUtil.toLowerCamelCase(name); +// return beanDescription.getSetter(propertyName); +// } + +// private Class getParameterClassForMethod(Method method) { +// if (method == null) { +// return null; +// } +// Class[] classArray = method.getParameterTypes(); +// if (classArray.length != 1) { +// return null; +// } else { +// return classArray[0]; +// } +// } + +// private AggregationType computeRawAggregationType(Method method) { +// Class parameterClass = getParameterClassForMethod(method); +// if (parameterClass == null) { +// return AggregationType.NOT_FOUND; +// } +// if (StringToObjectConverter.canBeBuiltFromSimpleString(parameterClass)) { +// return AggregationType.AS_BASIC_PROPERTY; +// } else { +// return AggregationType.AS_COMPLEX_PROPERTY; +// } +// } - private Method findSetterMethod(String name) { - String propertyName = BeanUtil.toLowerCamelCase(name); - return beanDescription.getSetter(propertyName); - } - private Class getParameterClassForMethod(Method method) { - if (method == null) { - return null; - } - Class[] classArray = method.getParameterTypes(); - if (classArray.length != 1) { - return null; - } else { - return classArray[0]; - } - } - - private AggregationType computeRawAggregationType(Method method) { - Class parameterClass = getParameterClassForMethod(method); - if (parameterClass == null) { - return AggregationType.NOT_FOUND; - } - if (StringToObjectConverter.canBeBuiltFromSimpleString(parameterClass)) { - return AggregationType.AS_BASIC_PROPERTY; - } else { - return AggregationType.AS_COMPLEX_PROPERTY; - } - } - - /** - * Can the given clazz instantiable with certainty? - * - * @param clazz The class to test for instantiability - * @return true if clazz can be instantiated, and false otherwise. - */ - private boolean isUnequivocallyInstantiable(Class clazz) { - if (clazz.isInterface()) { - return false; - } - // checking for constructors would be more elegant, but in - // classes without any declared constructors, Class.getConstructor() - // returns null. - Object o; - try { - o = clazz.getDeclaredConstructor().newInstance(); - if (o != null) { - return true; - } else { - return false; - } - } catch (InstantiationException | IllegalAccessException | InvocationTargetException - | NoSuchMethodException e) { - return false; - } - } public Class getObjClass() { return objClass; } public void addComplexProperty(String name, Object complexProperty) { - Method adderMethod = findAdderMethod(name); + Method adderMethod = aggregationAssessor.findAdderMethod(name); // first let us use the addXXX method if (adderMethod != null) { Class[] paramTypes = adderMethod.getParameterTypes(); @@ -254,8 +208,8 @@ public void addBasicProperty(String name, String strValue) { return; } - name = capitalizeFirstLetter(name); - Method adderMethod = findAdderMethod(name); + name = aggregationAssessor.capitalizeFirstLetter(name); + Method adderMethod =aggregationAssessor.findAdderMethod(name); if (adderMethod == null) { addError("No adder for property [" + name + "]."); @@ -278,7 +232,7 @@ public void addBasicProperty(String name, String strValue) { } public void setComplexProperty(String name, Object complexProperty) { - Method setter = findSetterMethod(name); + Method setter = aggregationAssessor.findSetterMethod(name); if (setter == null) { addWarn("Not setter method for property [" + name + "] in " + obj.getClass().getName()); @@ -320,76 +274,18 @@ private boolean isSanityCheckSuccessful(String name, Method method, Class[] p return true; } - private String capitalizeFirstLetter(String name) { - return name.substring(0, 1).toUpperCase() + name.substring(1); - } - public Object getObj() { return obj; } - Method getRelevantMethod(String name, AggregationType aggregationType) { - Method relevantMethod; - if (aggregationType == AggregationType.AS_COMPLEX_PROPERTY_COLLECTION) { - relevantMethod = findAdderMethod(name); - } else if (aggregationType == AggregationType.AS_COMPLEX_PROPERTY) { - relevantMethod = findSetterMethod(name); - } else { - throw new IllegalStateException(aggregationType + " not allowed here"); - } - return relevantMethod; - } - - T getAnnotation(String name, Class annonationClass, Method relevantMethod) { - - if (relevantMethod != null) { - return relevantMethod.getAnnotation(annonationClass); - } else { - return null; - } - } - Class getDefaultClassNameByAnnonation(String name, Method relevantMethod) { - DefaultClass defaultClassAnnon = getAnnotation(name, DefaultClass.class, relevantMethod); - if (defaultClassAnnon != null) { - return defaultClassAnnon.value(); - } - return null; + public Class getClassNameViaImplicitRules(String name, AggregationType aggregationType, + DefaultNestedComponentRegistry registry) { + return aggregationAssessor.getClassNameViaImplicitRules(name, aggregationType, registry); } - Class getByConcreteType(String name, Method relevantMethod) { - Class paramType = getParameterClassForMethod(relevantMethod); - if (paramType == null) { - return null; - } - - boolean isUnequivocallyInstantiable = isUnequivocallyInstantiable(paramType); - if (isUnequivocallyInstantiable) { - return paramType; - } else { - return null; - } - } - public Class getClassNameViaImplicitRules(String name, AggregationType aggregationType, - DefaultNestedComponentRegistry registry) { - Class registryResult = registry.findDefaultComponentType(obj.getClass(), name); - if (registryResult != null) { - return registryResult; - } - // find the relevant method for the given property name and aggregationType - Method relevantMethod = getRelevantMethod(name, aggregationType); - if (relevantMethod == null) { - return null; - } - Class byAnnotation = getDefaultClassNameByAnnonation(name, relevantMethod); - if (byAnnotation != null) { - return byAnnotation; - } - return getByConcreteType(name, relevantMethod); } - -} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/util/AggregationAssessorTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/util/AggregationAssessorTest.java new file mode 100644 index 0000000000..ce3f59e47e --- /dev/null +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/util/AggregationAssessorTest.java @@ -0,0 +1,73 @@ +/* + * Logback: the reliable, generic, fast and flexible logging framework. + * Copyright (C) 1999-2024, QOS.ch. All rights reserved. + * + * This program and the accompanying materials are dual-licensed under + * either the terms of the Eclipse Public License v1.0 as published by + * the Eclipse Foundation + * + * or (per the licensee's choosing) + * + * under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation. + */ + +package ch.qos.logback.core.joran.util; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry; +import ch.qos.logback.core.joran.util.beans.BeanDescriptionCache; +import ch.qos.logback.core.util.AggregationType; +import org.junit.jupiter.api.Test; + +import java.lang.reflect.Method; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class AggregationAssessorTest { + Context context = new ContextBase(); + AggregationAssessor aggregationAssessor = new AggregationAssessor(new BeanDescriptionCache(context), House.class); + DefaultNestedComponentRegistry defaultComponentRegistry = new DefaultNestedComponentRegistry(); + + @Test + public void testgetClassNameViaImplicitRules() { + Class compClass = aggregationAssessor.getClassNameViaImplicitRules("door", AggregationType.AS_COMPLEX_PROPERTY, + defaultComponentRegistry); + assertEquals(Door.class, compClass); + } + + @Test + public void testgetComplexPropertyColleClassNameViaImplicitRules() { + Class compClass = aggregationAssessor.getClassNameViaImplicitRules("window", + AggregationType.AS_COMPLEX_PROPERTY_COLLECTION, defaultComponentRegistry); + assertEquals(Window.class, compClass); + } + + @Test + public void testDefaultClassAnnotationForLists() { + Method relevantMethod = aggregationAssessor.getRelevantMethod("LargeSwimmingPool", + AggregationType.AS_COMPLEX_PROPERTY_COLLECTION); + assertNotNull(relevantMethod); + Class spClass = aggregationAssessor.getDefaultClassNameByAnnonation("LargeSwimmingPool", relevantMethod); + assertEquals(LargeSwimmingPoolImpl.class, spClass); + + Class classViaImplicitRules = aggregationAssessor.getClassNameViaImplicitRules("LargeSwimmingPool", + AggregationType.AS_COMPLEX_PROPERTY_COLLECTION, defaultComponentRegistry); + assertEquals(LargeSwimmingPoolImpl.class, classViaImplicitRules); + } + + @Test + public void testDefaultClassAnnonation() { + Method relevantMethod = aggregationAssessor.getRelevantMethod("SwimmingPool", AggregationType.AS_COMPLEX_PROPERTY); + assertNotNull(relevantMethod); + Class spClass = aggregationAssessor.getDefaultClassNameByAnnonation("SwimmingPool", relevantMethod); + assertEquals(SwimmingPoolImpl.class, spClass); + + Class classViaImplicitRules = aggregationAssessor.getClassNameViaImplicitRules("SwimmingPool", + AggregationType.AS_COMPLEX_PROPERTY, defaultComponentRegistry); + assertEquals(SwimmingPoolImpl.class, classViaImplicitRules); + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/util/PropertySetterTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/util/PropertySetterTest.java index edc345cf4c..d4bcddb23d 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/util/PropertySetterTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/util/PropertySetterTest.java @@ -37,8 +37,6 @@ public class PropertySetterTest { - DefaultNestedComponentRegistry defaultComponentRegistry = new DefaultNestedComponentRegistry(); - Context context = new ContextBase(); StatusChecker checker = new StatusChecker(context); House house = new House(); @@ -123,19 +121,7 @@ public void testSetComplexProperty() { assertEquals(door, house.getDoor()); } - @Test - public void testgetClassNameViaImplicitRules() { - Class compClass = setter.getClassNameViaImplicitRules("door", AggregationType.AS_COMPLEX_PROPERTY, - defaultComponentRegistry); - assertEquals(Door.class, compClass); - } - @Test - public void testgetComplexPropertyColleClassNameViaImplicitRules() { - Class compClass = setter.getClassNameViaImplicitRules("window", - AggregationType.AS_COMPLEX_PROPERTY_COLLECTION, defaultComponentRegistry); - assertEquals(Window.class, compClass); - } @Test public void testPropertyCollection() { @@ -193,30 +179,7 @@ public void testEnum() { assertEquals(HouseColor.BLUE, house.getHouseColor()); } - @Test - public void testDefaultClassAnnonation() { - Method relevantMethod = setter.getRelevantMethod("SwimmingPool", AggregationType.AS_COMPLEX_PROPERTY); - assertNotNull(relevantMethod); - Class spClass = setter.getDefaultClassNameByAnnonation("SwimmingPool", relevantMethod); - assertEquals(SwimmingPoolImpl.class, spClass); - - Class classViaImplicitRules = setter.getClassNameViaImplicitRules("SwimmingPool", - AggregationType.AS_COMPLEX_PROPERTY, defaultComponentRegistry); - assertEquals(SwimmingPoolImpl.class, classViaImplicitRules); - } - @Test - public void testDefaultClassAnnotationForLists() { - Method relevantMethod = setter.getRelevantMethod("LargeSwimmingPool", - AggregationType.AS_COMPLEX_PROPERTY_COLLECTION); - assertNotNull(relevantMethod); - Class spClass = setter.getDefaultClassNameByAnnonation("LargeSwimmingPool", relevantMethod); - assertEquals(LargeSwimmingPoolImpl.class, spClass); - - Class classViaImplicitRules = setter.getClassNameViaImplicitRules("LargeSwimmingPool", - AggregationType.AS_COMPLEX_PROPERTY_COLLECTION, defaultComponentRegistry); - assertEquals(LargeSwimmingPoolImpl.class, classViaImplicitRules); - } @Test public void charset() {