This is a follow up to: my previous question
My following line of code does not work:
IAccount account = (AccountModel) new AccountRepository().getByEmail(emailaddress);
The returntype of ...getByEmail(...) is Model<Account>, and AccountModel extends Model<Account>.
Yet I get a java.lang.ClassCastException: models.Model cannot be cast to models.AccountModel when I test it. I know this is because every AccountModel is a Model<Account>, but not the other way around.
Is there any way how I can make sure that I can fix this (or work around it).
public class AccountRepository extends Repository<Account> {
public AccountRepository() {
super(Account.class);
}
public Model<Account> getByEmail(String emailAddress) {
return this.getCustomHqlSingle("FROM Account a WHERE a.emailAddress = '" + emailAddress + "'");
}
}
public abstract class Repository<T> implements Serializable {
protected final Model<T> getCustomHqlSingle(String hql) {
List<Model<T>> t = this.getCustomHqlList(hql);
if (t != null && !t.isEmpty()) {
return t.get(0);
} else {
return null;
}
}
protected final List<Model<T>> getCustomHqlList(String hql) {
Session session = SESSION_FACTORY.openSession();
try {
session.beginTransaction();
List<T> entities = session.createQuery(hql).getResultList();
List<Model<T>> result = new ArrayList<>();
for (T t : entities) {
result.add(this.getByEntity(t));
}
return result;
} finally {
session.close();
}
}
To the person that marked this question as duplicate, let me rephrase the following sentence from my question:
I know this is because every AccountModel is a Model<Account>, but
not the other way around.
To
I know this is because every Dog is an Animal, but not the other
way around.
You have to devise a method in which to convert a Model<Account> to an AccountModel. Taking the code from your other question you could add a constructor for this to the AccountModel class:
public class AccountModel extends Model<Account> implements IAccount {
private static final AccountRepository REPOSITORY = new AccountRepository();
public AccountModel(Account entity) {
super(entity, REPOSITORY);
}
public AccountModel(Model<Account> model) { // <---
super(model._entity, REPOSITORY);
}
// Method implementations...
}
Then change your AccountRepository class to return an AccountModel from getByEmail:
public AccountModel getByEmail(String emailAddress) {
return new AccountModel(this.getCustomHqlSingle("FROM Account a WHERE a.emailAddress = '" + emailAddress + "'"));
}
Which uses the new constructor to convert the Model<Account> to an AccountModel.
There is another option. Rather than calling new Model<T>(...) in Repository, you could have implementing classes implement an abstract method that would return the desired Model type:
public abstract class Repository<T, R> implements Serializable
...
public Repository(Class<T> repositoryClass) {
if (!Repository._initiated)
setup();
this.cons = cons;
}
protected abstract R getModel(T entity, Repository<T> repo); // <--
Then somewhere in the factory methods:
public R getByFoo(...) {
...
T t = session.get(_repositoryClass, ...);
return getModel(t, this);
}
Where AccountRepository would return a new AccountModel:
public class AccountRepository extends Repository<Account, AccountModel> {
public AccountRepository() {
super(Account.class);
}
#Override
protected AccountModel getModel(Account entity, Repository<Account> repo) {
return new AccountModel(entity);
}
}
Since you say you understand why you get an error, let me try to explain something else about casting.
Except for some limited cases, the casting operator does not change the item being cast. Casting is an instruction to the compiler only, saying "My logic has guaranteed that the type of the cast object is different than the compiler can determine, so while you (the compiler) would tell me this is an error, I am certain that, at runtime, it will be fine. So don't give me an error".
It does NOT say "take this object and transform it into another, similar object". That operation is not possible in Java, thank heavens.
Related
I have this design which I self-proclaim to be Composite Pattern, though I'm not entirely sure about that. So I'm aksing for your statement on this.
This is the interface which collectively describes all of them
public interface DomainResourceBuilder<T extends DomainResource> {
T buildInsertion(T persistence, EntityManager entityManager) throws Exception;
T buildUpdate(T model, T persistence, EntityManager entityManger);
<E extends T> DomainResourceBuilder<E> and(DomainResourceBuilder<E> next);
}
This one describes DomainResourceBuilder as a pair
public abstract class AbstractDomainResourceBuilder<D extends
DomainResource> implements DomainResourceBuilder<D> {
#Override
public <E extends D> DomainResourceBuilder<E>
and(DomainResourceBuilder<E> next) {
return new CompositeDomainResourceBuilder<>(this, next);
}
private class CompositeDomainResourceBuilder<T extends D>
extends AbstractDomainResourceBuilder<T> {
private final DomainResourceBuilder<D> parentBuilder;
private final DomainResourceBuilder<T> childBuilder;
public
CompositeDomainResourceBuilder(DomainResourceBuilder<D>
parentBuilder,
DomainResourceBuilder<T> childBuilder) {
super();
this.parentBuilder = parentBuilder;
this.childBuilder = childBuilder;
}
#SuppressWarnings("unchecked")
#Override
public T buildInsertion(T model, EntityManager
entityManager) throws Exception {
return childBuilder.buildInsertion((T)
parentBuilder.buildInsertion(model, entityManager),
entityManager);
}
#SuppressWarnings("unchecked")
#Override
public T buildUpdate(T model, T persistence,
EntityManager entityManger) {
return childBuilder.buildUpdate(model, (T)
parentBuilder.buildUpdate(model, persistence,
entityManger), entityManger);
}
}
}
Concrete class plays the Leaf role
public class CustomerBuilder extends AbstractDomainResourceBuilder<Customer> {
#Override
public
Customer buildInsertion(Customer persistence, EntityManager entityManager) throws Exception {
return persistence;
}
#Override
public
Customer buildUpdate(Customer model, Customer persistence, EntityManager entityManger) {
return persistence;
}
}
Can I call this a Composite Pattern?
This is how I use it. Assumming I have the following hierarchy.
AbstractEntity
|___User
|___Customer
Now I want to implement different logics on each class, so with the design I'll create specific logic for those class and then ultimately compose them into one, which is still one of their kind. Something like this.
// group of objects
DomainResourceBuilder<AbstractEntity> abstractEntityBuilder = new AbstractEntityBuilder<>();
DomainResourceBuilder<User> userBuilder = new UserBuilder<>();
DomainResourceBuilder<Customer> customerBuilder = new CustomerBuilder<>();
// treat them as a whole (unify them all)
DomainResourceBuilder<Customer> compositeCustomerBuilder =
abstractEntityBuilder
.and(userBuilder)
.and(customerBuilder);
I do not think that it looks like Composite pattern as:
there is no a place where a group of objects that are treated the same way as a single instance of the same type of object.
In my view, it looks like it uses Builder pattern with generics that can treat hierarchy of entities.
UPDATE:
In my view it is not group of objects:
// group of objects
DomainResourceBuilder<AbstractEntity> abstractEntityBuilder = new AbstractEntityBuilder<>();
DomainResourceBuilder<User> userBuilder = new UserBuilder<>();
DomainResourceBuilder<Customer> customerBuilder = new CustomerBuilder<>();
If the above objects will be put in collection, then it can be called as group of objects. In my honour opinion, it is just object variables.
In the following lines of code, Fluent interface design pattern can be seen as methods can be chained:
// treat them as a whole (unify them all)
DomainResourceBuilder<Customer> compositeCustomerBuilder =
abstractEntityBuilder
.and(userBuilder)
.and(customerBuilder);
Let me show an example where group of objects can be treat as a whole.
The following literature has great examples and explanations:
this beautiful, very cool and interesting book by Eric Freeman
this article about composite pattern at wiki
this article about composite pattern at codemaze
Imagine you are building browser and you want to show controls. Your task is to show values of all of your controls placed in DOM browser.
So example code would look like this.
We need some base class for controls:
public abstract class ControlBase
{
protected string name;
protected string value;
public ControlBase(string name, string value)
{
this.name = name;
this.value = value;
}
public abstract string ShowValue();
}
and its operations:
public interface IControlOperations
{
void Add(ControlBase gift);
void Remove(ControlBase gift);
}
Then we create a composite control where we can have group of objects:
public class CompositeControl : ControlBase, IControlOperations
{
// group of objects
private List<ControlBase> _controls;
public CompositeControl(string name, string value)
: base(name, value)
{
_controls = new List<ControlBase>();
}
public void Add(ControlBase gift)
{
_controls.Add(gift);
}
public void Remove(ControlBase gift)
{
_controls.Remove(gift);
}
// group of objects can be treat as a whole
public override string ShowValue()
{
StringBuilder allValues = new StringBuilder();
Console.WriteLine($"{name} has the following values:");
foreach (var gift in _controls)
{
allValues.AppendLine(gift.ShowValue());
}
return allValues.ToString();
}
}
And our UI controls:
public class TextBox : ControlBase
{
public TextBox(string name, string value)
: base(name, value)
{
}
public override string ShowValue()
{
Console.WriteLine($"{name} has {value}");
return value;
}
}
public class CheckBox : ControlBase
{
public CheckBox(string name, string value)
: base(name, value)
{
}
public override string ShowValue()
{
Console.WriteLine($"{name} with value {value}");
return value;
}
}
And then we can call code like this:
var textBox_Phone = new TextBox("textBox_Phone", "1");
textBox_Phone.ShowValue();
Console.WriteLine();
//composite control
var divContainer = new CompositeControl("divContainer", string.Empty);
var textBox_Name = new TextBox("textBox_Name", "Joseph");
var textBox_Surname = new TextBox("textBox_Surname", "Albahari");
divContainer.Add(textBox_Name);
divContainer.Add(textBox_Surname);
Console.WriteLine($"Total values of this composite control " +
$"is: {divContainer.ShowValue()}");
I am working on a Spring Boot application and I have the following doubt.
I have this service method (that works fine) that insert an object into the DB calling the repository:
#Override
#Transactional
public CoinDTO createCoin(CoinDTO coin) throws DuplicateException {
Coin checkCoinExists = coinRepository.findByCode(coin.getCode());
if (checkCoinExists != null) {
String MsgErr = String.format("Coin %s already registered in the system !!! "
+ "Impossible to use POST", coin.getCode());
log.warning(MsgErr);
throw new DuplicateException(MsgErr);
}
Coin result = coinRepository.save(conversionService.convert(coin,Coin.class));
return conversionService.convert(result,CoinDTO.class);
}
As you can see the save() methjod return the inserted Coin object (that is an Hibernate entity class mapping my table). The service method than convert this Coin object into the CoinDTO object in order to return the DTO object instead the entity instance. It works fine and it is the expected behavior.
Now I created this second service method that simply retrieve the list of all the Coin objects and must return the list of the related CoinDTO objects:
#Override
public List<CoinDTO> getCoinList() {
List<Coin> coinsList = this.coinRepository.findAll();
return null;
}
and here I have the following doubt: I think that I can implement thid ENTITY to DTO conversion behavior iterating on the coinsList element, converting each element of the list one by one and then adding it to a new List list. It should work
Exist some more modern and smarter way to do it? Maybe using lambda function? Can you help me to implement this behavior in a modern and a smart way?
You may create an generic abstract class like this:
public abstract class AbstractConverter<T, DTO> {
public abstract T fromDto(DTO dto);
public abstract DTO toDTO(T t);
public List<T> fromDTOs(List<DTO> dtos) {
if (dtos == null || dtos.isEmpty()) {
return null;
} else {
return dtos.stream().map(this::fromDTO).collect(Collectors.toList());
}
}
public List<DTO> toDTOs(List<T> ts) {
if (ts == null || ts.isEmpty()) {
return null;
} else {
return ts.stream().map(this::toDTO).collect(Collectors.toList());
}
}
}
Then create another class that implements the aforecreated abstract class by assigning your desired values like this:
#Component(value = "coinConverter")
public class CoinConverter extends AbstractConverter<Coin, CoinDTO> {
#Override
public Coin fromDTO(CoinDTO dto) {
if (dto == null) {
return null;
} else {
Coin coin = new Coin();
// Assign all values you wanted to consume
// of the following form
// coin.setYourAttribite(dto.getYourAttribute())
return coin;
}
}
#Override
public CoinDTO toDTO(Coin coin) {
if (t == null) {
return null;
} else {
CoinDTO coinDTO = new CoinDTO();
// Assign all values you wanted to expose
// of the following form
// coinDTO.setYourAttribite(coin.getYourAttribute())
return coinDTO;
}
}
}
In controller layer you may change your existing code by this one:
#Autowired
#Qualifier("coinConverter")
AbstractConverter<Coin, CoinDTO> abstractConverter;
#Override
public List<CoinDTO> getCoinList() {
List<Coin> coinsList = this.coinRepository.findAll();
return abstractConverter.toDTOs(cointList);
}
This way your code is flexible to add more converters without changing the existing ones.
As far as I understand, you are looking for a way that makes the conversion process shorter and more convenient. if so use ModelMapper class in this case, read this http://modelmapper.org/ documentation, ModelMapper uses TypeTokens to allow mapping of generic parameterized types.
Not sure if I understood your question, but is the following what you are looking for:
#Override
public List<CoinDTO> getCoinList() {
return this.coinRepository.findAll().stream()
.map(coin -> conversionService.convert(coin, CoinDTO.class))
.collect(Collectors.toList());
}
Note: this question is more about generics than it is about enums.
I have few enum types, all implementing a common interface IEffect.
For example
enum ElementalEffect implements IEffect {
FIRE, WATER;
}
enum CombatEffect implements IEffect {
PARALYSIS, SLEEP;
}
I would like to parse a config-file, that should add effects to a weapon. For that I have to resolve a given name to one of the effects. To keep it simple to maintain, I thought of writing a method like this (mostly pseudo-code, this does not compile. In fact the point of the question is how to make this compile):
IEffect resolveEffectName(String name, Class... clazzes) {
for(Class clazz : clazzes) {
try {
return Enum.valueOf(clazz, name);
} catch(IllegalArgumentException) { /* ignore, try next class */}
}
throw new IllegalArgumentException("No matching effect found for " + name);
}
// resolveEffectName(readNameFromFile, ElementalEffect.class, CombatEffect.class);
Now the problem I have is that I can't figure out how to write that method without the compiler telling me
The method valueOf(Class<T>, String) in the type Enum is not applicable for the arguments ...
People saying it should be
private static ICombatEffectType getFirstResolved(String name, Class<? extends Enum<?>>... classes) {
for (Class<? extends Enum<?>> clazz : classes) {
try {
return Enum.valueOf(clazz, name);
} catch (IllegalArgumentException e) {
}
}
return null;
}
This is not working. Feel free to try it (if you don't believe me).
The method valueOf(Class<T>, String) in the type Enum is not applicable for the arguments (Class<capture#6-of ? extends Enum<?>>, String)
You can write this fluently, if that's your style:
class FluentGetter {
private final String name;
private IEffect found;
FluentGetter(String name) { this.name = name; }
<T extends Enum<T> & IEffect> FluentGetter search(Class<T> clazz) {
if (found == null) { // If you've already found something, don't overwrite that.
try {
found = Enum.valueOf(clazz, name);
} catch (IllegalArgumentException e) {}
}
return this;
}
IEffect get() {
return found; // + check if it's null, if you want.
}
}
Then:
IEffect effect =
new FluentGetter(name)
.search(ElementalEffect.class)
.search(CombatEffect.class)
.get();
This avoids the problem of the generic bounds on the array of classes by having separate method calls for each.
Pretty sure I wouldn't use this myself; just tossing it out as an option.
What you really want is a map of names to enum constants, which you can easily make using streams:
private static final Map<String, IEffect> constants
= Stream.of(ElementalEffect.values(), CombatEffect.values())
.flatMap(Arrays::stream)
.collect(Collectors.toMap(Enum::name, Function.identity()));
IEffect resolveEffectName(String name) {
if(!constants.containsKey(name))
throw new IllegalArgumentException("No matching effect found for " + name);
return constants.get(name);
}
I found a way to make everything work without warnings using a wrapper class:
private static class Wrapper<T extends Enum<T> & IEffect> {
private Class<T> clazz;
public Wrapper(Class<T> clazz) {
this.clazz = clazz;
}
public IEffect resolveName(String name) {
return Enum.valueOf(clazz, name);
}
}
private static IEffect getFirstResolved(String name, Wrapper<?>... clazzes) {
for (Wrapper<?> clazz : clazzes) {
try {
return clazz.resolveName(name);
} catch (IllegalArgumentException e) {}
}
throw new IllegalArgumentException("No enum has a member " + name);
}
// Example call
ICombatEffectType elemental = getFirstResolved(
type,
new Wrapper<>(ElementalType.class),
new Wrapper<>(StatusEffect.class));
This should compile (with warnings), using your first method:
return (IEffect) Enum.valueOf((Class<Enum>) clazz, name);
I have two unrelated java classes (only *.class, no *.java) like this:
public class Trick {
public String getName() { return "Jack"; }
public String trick() { ... }
}
and
public class Treat {
public String getName() { return "John"; }
public String treat() { ... }
}
and I would like to generate a sort of Proxy class at runtime that represents the union of both classes and forwards them to the respective instance, and maybe throw if that's not possible. I assume that can be done with cglib but I don't know where to start.
This is what I would like to do (pseudocode):
// prepare: generate a common interface
TrickOrTreat trickOrTreat = magic.createUnionInterface(Trick.class, Treat.class);
// use with concrete interface A:
Trick trick = new Trick();
TrickOrTreat proxyA = magic.createProxy(trickOrTreat.class, trick);
System.out.println("trick name: " + proxyA.getName());
// use with concrete interface B:
Treat treat = new Treat();
TrickOrTreat proxyB = magic.createProxy(trickOrTreat.class, treat);
System.out.println("treat name: " + proxyB.getName());
Or something to that effect. I would like to do it completely dynamically, probably cglib-based? If thats not possible I would do it with a code generation step in between?
If you are willing to trade in cglib, you can do this with Byte Buddy. I typically refuse to call it magic but here you go:
class Magic {
Class<?> createUnionInterface(Class<?> a, Class<?> b) {
DynamicType.Builder<?> builder = new ByteBuddy().makeInterface();
Set<MethodDescription.SignatureToken> tokens = new HashSet<>();
for (MethodDescription m : new TypeDescription.ForLoadedType(a)
.getDeclaredMethods()
.filter(ElementMatchers.isVirtual())) {
tokens.add(m.asSignatureToken());
builder = builder.defineMethod(m.getName(),
m.getReturnType(),
m.getModifiers()).withoutCode();
}
for (MethodDescription m : new TypeDescription.ForLoadedType(b)
.getDeclaredMethods()
.filter(ElementMatchers.isVirtual())) {
if (!tokens.contains(m.asSignatureToken())) {
builder = builder.defineMethod(m.getName(),
m.getReturnType(),
m.getModifiers()).withoutCode();
}
}
return builder.make()
.load(Magic.class.getClassLoader())
.getLoaded();
}
Object createProxy(Class<?> m, final Object delegate) throws Exception {
return new ByteBuddy()
.subclass(m)
.method(new ElementMatcher<MethodDescription>() {
#Override
public boolean matches(MethodDescription target) {
for (Method method : delegate.getClass()
.getDeclaredMethods()) {
if (new MethodDescription.ForLoadedMethod(method)
.asSignatureToken()
.equals(target.asSignatureToken())) {
return true;
}
}
return false;
}
}).intercept(MethodDelegation.to(delegate))
.make()
.load(Magic.class.getClassLoader())
.getLoaded()
.newInstance();
}
}
Note that you cannot reference a runtime-generated type at compile-time. This is however a given constraint with runtime code generation.
Magic magic = new Magic();
Class<?> trickOrTreat = magic.createUnionInterface(Trick.class, Treat.class);
Trick trick = new Trick();
Object proxyA = magic.createProxy(trickOrTreat, trick);
System.out.println("trick name: " + trickOrTreat.getDeclaredMethod("getName").invoke(proxyA));
Treat treat = new Treat();
Object proxyB = magic.createProxy(trickOrTreat, treat);
System.out.println("trick name: " + trickOrTreat.getDeclaredMethod("getName").invoke(proxyB));
You can overcome this by generating your TrickOrTreat class prior to runtime such that you can reference the type at runtime.
As for the suggested union-type approach, this would require you to have at least one class to be an interface type as Java does not support multiple inheritance.
If you need functionality of both classes/interfaces you can use
public <TT extends Trick & Treat> void process(TT thing){
//...
}
edit:
Implement new Interface MyProxyHandler
public interface MyProxyHandler {}
Extend it with interfaces of classes say TreatInterface and TrickInterface
Create class ProxyManager that implements java.lang.reflect.InvocationHandler
public abstract class ProxyManager<T extends MyProxyHandler> implements InvocationHandler {
protected static String LOCK_OBJECT = new String("LOCK");
protected T proxyHandler;
protected List<T> handlers = new ArrayList<>();
#SuppressWarnings("unchecked")
public ProxyManager(Class<T> _clazz) {
proxyHandler = (T) Proxy.newProxyInstance(_clazz.getClassLoader(), new Class[]{_clazz}, this);
}
public T getProxy() {
return proxyHandler;
}
public List<T> getHandlers() {
return handlers;
}
public void setHandlers(List<T> handlers) {
this.handlers = handlers;
}
public boolean registerHandler(T handler) {
synchronized (LOCK_OBJECT) {
boolean add = true;
for (T item : this.handlers) {
if (item.getClass().equals(handler.getClass())) {
add = false;
}
}
if (add)
this.handlers.add(handler);
return add;
}
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String result = "";
for (MyProxyHandler handler : getHandlers()) {
try {
//I recommend that methods returns some enum like HANDLED/NOTHANDLED
result = (String) method.invoke(handler, args);
if (result.equals("Some flag"))
break;
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
return result;
}
}
Extend that class with your concrete class
public class TreatTrickProxyManager<T extends TreatInterface & TreatInterface> extends ProxyManager<T> {
public TreatTrickProxyManager(Class<T> _clazz) {
super(_clazz);
}
}
In your bussines logic class get an instance of TreatTrickProxyManager
In your method
public void retrieveSomeData(){
((TreatTrickProxyManager)getTreatTrickProxyManager().getProxy()).someMethodInvocation()
}
I could workaround this problem but I cannot understand it, so I am asking for some explanation (and maybe a better question title as well).
Please consider this:
public class TBGService {
// TBGObject is an abstract base class which is extended by model classes
public <T> T doGet(TBGObject model) throws TBGServiceException {
String uri = model.buildUrl(repository) + model.getObjectKey();
GetMethod method = new GetMethod(uri);
T returned = execute(method, credentials, model.getClass());
return returned;
}
}
and this:
public enum TBGTaskAttributes {
private TBGTaskAttributes(String id, String type, String label, Object... flags) {
builder = new TaskAttributeBuilder();
builder.withId(id).withLabel(label);
for (Object flag : flags) {
processFlag(flag);
}
}
public abstract String getValueFromIssue(TBGIssue issue);
public abstract void setValueInIssue(TBGIssue issue, String value);
}
when I write this code to define an enum item:
PROJECT(TaskAttribute.PRODUCT, TaskAttribute.TYPE_SINGLE_SELECT, "Project", new OptionProvider() {
#Override
public Set<Entry<String, String>> getOptions(TaskRepository repository) {
try {
List<TBGProject> list = TBGService.get(repository)
.doGet(new TBGProjects()).getProjects();
[...]
return map.entrySet();
} catch (TBGServiceException e) { [...] }
return null;
}
}) {
#Override
public String getValueFromIssue(TBGIssue issue) {
return issue.getProjectKey();
}
#Override
public void setValueInIssue(TBGIssue issue, String value) {
issue.setProjectKey(value);
}
},
[... other items ...]
I get compiler error (also eclipse auto-completion does not work):
The method getProjects() is undefined for the type Object
and if I hover the doGet method, eclipse show it as defined like:
<Object> Object TBGService.doGet(TBGObject model)
Elsewhere, hovering shows the signature correctly as:
<TBGProjects> TBGProjects TBGService.doGet(TBGObject model)
when called with parameter new TBGProjects().
Just changing:
List<TBGProject> list = TBGService.get(repository)
.doGet(new TBGProjects()).getProjects();
with:
TBGProjects projects = TBGService.get(repository).doGet(new TBGProjects());
List<TBGProject> = projects.getProjects();
makes it work. But what's happening here? What am I missing?
Java infers the type of T based on what you assign the return value of the method to.
If you don't assign the return value to anything, Java has no idea what T should be.
To fix this, you can change the parameter to be of type T so Java can infer T from the parameter you pass:
public <T extends TBGObject> T doGet(T model) throws TBGServiceException {