Permalink
Browse files

breaking: Name are composed by a Type and a String

Before the Name was a couple (Class, String), from now on it's a
couple (Type, String). The string stay the same, but the Class becomes a Type.
Like this we will have a better granularity in order to inject parameterized types.

This commit is breaking because the Name class was having a public constructor with a class, and
the class have been changed to a Type.
WIP: Should we really have a public constructor ?! Personally I think that only private constructors
and public static factories should be enough.

If you want to build a name with a type, there is multiple solutions. If you want to use a simple generic type
(only one depth of generic) like `SomeGeneric<SomeType>`, the easiest way is to use this signature:
```java
Name.of(aStringName, SomeGeneric.class, SomeType.class)
```
This method is using the `Types.newParameterizedType` static factory, which is an easy way to build parameterized types.
An equivalent technique would be to use something like this:
```java
Name.of(Types.newParameterizedType(SomeGeneric.class, SomeType.class), aStringName)
```
(It will be almost equivalent, as the first way will be a little bit more efficient, as the raw type will not be calculated,
it is already given in parameter: `SomeGeneric.class`)

If you need to build a complex generic type, like `One<Two<Three, Four<Five>>>`, the easiest way will be to use the abstract
class `TypeReference` like this:
```java
Name.of(new TypeReference<One<Two<Three, Four<Five>>>() {}, aStringName)
```
  • Loading branch information...
a-peyrard committed Apr 8, 2015
1 parent 88e1be3 commit 460715b711061a50f4405036bb200bb3386b9473
@@ -1,5 +1,8 @@
package restx.common;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* Date: 29/11/13
* Time: 11:13
@@ -12,6 +15,24 @@ public static String toString(Class clazz) {
return clazz.getName() + "[" + toString(clazz.getClassLoader()) + "]";
}
public static String toString(Type type) {
if (type == null) {
return "null";
}
String typeString;
/*
in jse8 another case should be done, using type.getTypeName() if
type is an instanceof ParameterizedType
*/
if (type instanceof Class) {
typeString = ((Class) type).getName();
} else {
typeString = String.valueOf(type);
}
return typeString + "[" + toString(Types.getRawType(type).getClassLoader()) + "]";
}
public static String toString(ClassLoader classLoader) {
if (classLoader == null) {
return "";
@@ -1,56 +1,90 @@
package restx.factory;
import restx.common.MoreObjects;
import static com.google.common.base.Preconditions.checkNotNull;
import java.lang.reflect.Type;
import restx.common.MoreObjects;
import restx.common.TypeReference;
import restx.common.Types;
/**
* User: xavierhanin
* Date: 1/31/13
* Time: 5:40 PM
*/
public final class Name<T> {
private final String name;
private final Class<T> clazz;
private final Type type;
private final Class<T> rawType;
public static <T> Name<T> of(Class<T> clazz, String name) {
return new Name<>(clazz, name);
return new Name<>(clazz, clazz, name);
}
public static <T> Name<T> of(Class<T> clazz) {
return new Name<>(clazz, clazz.getSimpleName());
return new Name<>(clazz, clazz, clazz.getSimpleName());
}
public Name(Class<T> clazz, String name) {
public static <T> Name<T> of(Type type, String name) {
return new Name<>(type, name);
}
@SuppressWarnings("unchecked")
public static <T> Name<T> of(Type type) {
Class<T> rawType = (Class<T>) Types.getRawType(type);
return new Name<>(type, rawType, rawType.getSimpleName());
}
@SuppressWarnings("unchecked")
public static <T> Name<T> of(String name, Class<?> rawType, Type... arguments) {
return (Name<T>) new Name<>(Types.newParameterizedType(rawType, arguments), rawType, name);
}
public static <T> Name<T> of(TypeReference<T> typeReference, String name) {
return new Name<>(checkNotNull(typeReference).getType(), name);
}
@SuppressWarnings("unchecked")
public Name(Type type, String name) {
this(type, (Class<T>) Types.getRawType(type), name);
}
private Name(Type type, Class<T> rawType, String name) {
this.name = checkNotNull(name);
this.clazz = checkNotNull(clazz);
this.type = checkNotNull(type);
this.rawType = checkNotNull(rawType);
}
public String getSimpleName() {
String simpleName = clazz.getSimpleName();
String simpleName = String.valueOf(type);
if (!simpleName.equalsIgnoreCase(name)) {
simpleName = name + "[" + simpleName + "]";
}
return simpleName;
}
public String asId() {
return "[" + clazz.getName() + "]" + name;
return "[" + String.valueOf(type) + "]" + name;
}
public String getName() {
return name;
}
public Type getType() {
return type;
}
public Class<T> getClazz() {
return clazz;
}
return rawType;
}
@Override
public String toString() {
return "Name{" +
"name='" + name + '\'' +
", clazz=" + MoreObjects.toString(clazz) +
", type=" + MoreObjects.toString(type) +
'}';
}
@@ -61,7 +95,8 @@ public boolean equals(Object o) {
Name name1 = (Name) o;
if (!clazz.equals(name1.clazz)) return false;
if (!rawType.equals(name1.rawType)) return false;
if (!type.equals(name1.type)) return false;
if (!name.equals(name1.name)) return false;
return true;
@@ -70,7 +105,8 @@ public boolean equals(Object o) {
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + clazz.hashCode();
result = 31 * result + rawType.hashCode();
result = 31 * result + type.hashCode();
return result;
}
}
@@ -1,8 +1,11 @@
package restx.factory;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Function;
import static com.google.common.base.Preconditions.checkNotNull;
import java.lang.reflect.Type;
/**
* User: xavierhanin
@@ -29,13 +32,23 @@ public T apply(NamedComponent<T> namedComponent) {
}
public static <T> NamedComponent<T> of(Class<T> clazz, String name, T component) {
return new NamedComponent<>(new Name<>(clazz, name), component);
return new NamedComponent<>(Name.of(clazz, name), component);
}
public static <T> NamedComponent<T> of(Class<T> clazz, String name, int priority, T component) {
return new NamedComponent<>(new Name<>(clazz, name), priority, component);
return new NamedComponent<>(Name.of(clazz, name), priority, component);
}
@SuppressWarnings("unchecked")
public static <T> NamedComponent<T> of(Type type, String name, T component) {
return new NamedComponent<>((Name<T>) Name.of(type, name), component);
}
@SuppressWarnings("unchecked")
public static <T> NamedComponent<T> of(Type type, String name, int priority, T component) {
return new NamedComponent<>((Name<T>) Name.of(type, name), priority, component);
}
private final Name<T> name;
private final int priority;
private final T component;
@@ -1,15 +1,17 @@
package restx.factory;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static restx.factory.Factory.LocalMachines.threadLocal;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import org.junit.After;
import org.junit.Test;
import java.util.Set;
import static org.assertj.core.api.Assertions.*;
import static restx.factory.Factory.LocalMachines.threadLocal;
/**
* User: xavierhanin
* Date: 1/31/13
@@ -179,12 +181,12 @@ public void should_fail_with_missing_deps() throws Exception {
assertThat(e)
.hasMessageStartingWith(
"\n" +
" QueryByName{name=Name{name='test', clazz=java.lang.String[]}}\n" +
" | \\__=> Name{name='test', clazz=java.lang.String[]}\n" +
" QueryByName{name=Name{name='test', type=class java.lang.String[]}}\n" +
" | \\__=> Name{name='test', type=class java.lang.String[]}\n" +
" |\n" +
" +-> QueryByName{name=Name{name='missing', clazz=java.lang.String[]}}\n" +
" +-> QueryByName{name=Name{name='missing', type=class java.lang.String[]}}\n" +
" |\n" +
" +--: Name{name='missing', clazz=java.lang.String[]} can't be satisfied")
" +--: Name{name='missing', type=class java.lang.String[]} can't be satisfied")
;
}
}
@@ -217,9 +219,9 @@ public void should_find_one_when_multiple_available_fail() throws Exception {
" Please select which one you want with a more specific query,\n" +
" or by deactivating one of the available components.\n" +
" Available components:\n" +
" - NamedComponent{name=Name{name='test', clazz=java.lang.String[]}, priority=0, component=value1}\n" +
" - NamedComponent{name=Name{name='test', type=class java.lang.String[]}, priority=0, component=value1}\n" +
" [Activation key: 'restx.activation::java.lang.String::test']\n" +
" - NamedComponent{name=Name{name='test2', clazz=java.lang.String[]}, priority=0, component=value1}\n" +
" - NamedComponent{name=Name{name='test2', type=class java.lang.String[]}, priority=0, component=value1}\n" +
" [Activation key: 'restx.activation::java.lang.String::test2']\n")
;
}

0 comments on commit 460715b

Please sign in to comment.