Allow SubclassClassifier to work with interfaces

Up to now it only traversed superclasses. Now it looks at the
interfaces as well.
This commit is contained in:
Dave Syer
2019-04-05 14:19:49 +01:00
parent 73568416a8
commit a717e47043
3 changed files with 95 additions and 23 deletions

View File

@@ -86,8 +86,9 @@ public class SubclassClassifier<T, C> implements Classifier<T, C> {
}
/**
* Add a classification. The keys is the type and this will be mapped along with all
* subclasses to the corresponding value. The most specific types will match first.
* <<<<<<< HEAD Add a classification. The keys is the type and this will be mapped
* along with all subclasses to the corresponding value. The most specific types will
* match first.
* @param type the type of the input object
* @param target the target value for all such types
*/
@@ -96,8 +97,9 @@ public class SubclassClassifier<T, C> implements Classifier<T, C> {
}
/**
* Return the value from the type map whose key is the class of the given Throwable,
* or its nearest ancestor if a subclass.
* ======= >>>>>>> f60e17b... Allow SubclassClassifier to work with interfaces Return
* the value from the type map whose key is the class of the given Throwable, or its
* nearest ancestor if a subclass.
* @return C the classified value
* @param classifiable the classifiable thing
*/
@@ -121,6 +123,19 @@ public class SubclassClassifier<T, C> implements Classifier<T, C> {
value = this.classified.get(cls);
}
// check for interfaces subclasses
if (value == null) {
for (Class<?> cls = exceptionClass; !cls.equals(Object.class)
&& value == null; cls = cls.getSuperclass()) {
for (Class<?> ifc : cls.getInterfaces()) {
value = this.classified.get(ifc);
if (value != null) {
break;
}
}
}
}
// ConcurrentHashMap doesn't allow nulls
if (value != null) {
this.classified.put(exceptionClass, value);

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2006-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.classify;
import java.util.Collections;
import java.util.function.Supplier;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class SubclassClassifierTests {
@Test
public void testClassifyInterface() {
SubclassClassifier<Object, String> classifier = new SubclassClassifier<Object, String>();
classifier.setTypeMap(
Collections.<Class<?>, String>singletonMap(Supplier.class, "foo"));
assertEquals("foo", classifier.classify(new Foo()));
}
@Test
public void testClassifyInterfaceOfParent() {
SubclassClassifier<Object, String> classifier = new SubclassClassifier<Object, String>();
classifier.setTypeMap(
Collections.<Class<?>, String>singletonMap(Supplier.class, "foo"));
assertEquals("foo", classifier.classify(new Bar()));
}
public class Bar extends Foo {
}
public static class Foo implements Supplier<String> {
@Override
public String get() {
return "foo";
}
}
}

View File

@@ -16,8 +16,6 @@
package org.springframework.classify;
import org.junit.Test;
import java.io.FileNotFoundException;
import java.net.ConnectException;
import java.net.SocketException;
@@ -25,6 +23,8 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.NoSuchElementException;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@@ -34,68 +34,68 @@ public class SubclassExceptionClassifierTests {
@Test
public void testClassifyNullIsDefault() {
assertEquals(classifier.classify(null), classifier.getDefault());
assertEquals(this.classifier.classify(null), this.classifier.getDefault());
}
@Test
public void testClassifyNull() {
assertNull(classifier.classify(null));
assertNull(this.classifier.classify(null));
}
@Test
public void testClassifyNullNonDefault() {
classifier = new SubclassClassifier<Throwable, String>("foo");
assertEquals("foo", classifier.classify(null));
this.classifier = new SubclassClassifier<Throwable, String>("foo");
assertEquals("foo", this.classifier.classify(null));
}
@Test
public void testClassifyRandomException() {
assertNull(classifier.classify(new IllegalStateException("Foo")));
assertNull(this.classifier.classify(new IllegalStateException("Foo")));
}
@Test
public void testClassifyExactMatch() {
classifier
this.classifier
.setTypeMap(Collections.<Class<? extends Throwable>, String>singletonMap(
IllegalStateException.class, "foo"));
assertEquals("foo", classifier.classify(new IllegalStateException("Foo")));
assertEquals("foo", this.classifier.classify(new IllegalStateException("Foo")));
}
@Test
public void testClassifySubclassMatch() {
classifier
this.classifier
.setTypeMap(Collections.<Class<? extends Throwable>, String>singletonMap(
RuntimeException.class, "foo"));
assertEquals("foo", classifier.classify(new IllegalStateException("Foo")));
assertEquals("foo", this.classifier.classify(new IllegalStateException("Foo")));
}
@Test
public void testClassifySuperclassDoesNotMatch() {
classifier
this.classifier
.setTypeMap(Collections.<Class<? extends Throwable>, String>singletonMap(
IllegalStateException.class, "foo"));
assertEquals(classifier.getDefault(),
classifier.classify(new RuntimeException("Foo")));
assertEquals(this.classifier.getDefault(),
this.classifier.classify(new RuntimeException("Foo")));
}
@SuppressWarnings("serial")
@Test
public void testClassifyAncestorMatch() {
classifier.setTypeMap(new HashMap<Class<? extends Throwable>, String>() {
this.classifier.setTypeMap(new HashMap<Class<? extends Throwable>, String>() {
{
put(Exception.class, "foo");
put(IllegalArgumentException.class, "bar");
put(RuntimeException.class, "spam");
}
});
assertEquals("spam", classifier.classify(new IllegalStateException("Foo")));
assertEquals("spam", this.classifier.classify(new IllegalStateException("Foo")));
}
@SuppressWarnings("serial")
@Test
public void testClassifyAncestorMatch2() {
classifier = new SubclassClassifier<Throwable, String>();
classifier.setTypeMap(new HashMap<Class<? extends Throwable>, String>() {
this.classifier = new SubclassClassifier<Throwable, String>();
this.classifier.setTypeMap(new HashMap<Class<? extends Throwable>, String>() {
{
put(SocketException.class, "1");
put(FileNotFoundException.class, "buz");
@@ -106,7 +106,7 @@ public class SubclassExceptionClassifierTests {
put(ConnectException.class, "2");
}
});
assertEquals("2", classifier.classify(new SubConnectException()));
assertEquals("2", this.classifier.classify(new SubConnectException()));
}
public static class SubConnectException extends ConnectException {