Trying to create my own shiny ORM system (not that important information), I'm currently struggling with java inheritance limits. Here is the concept:
public class UserDescriptor implements TableDescriptor {
public static final UserDescriptor INSTANCE = new UserDescriptor();
private UserDescriptor() {
}
public String getTableName() {
return "user";
}
// ======= Columns definition
public static final AbstractColumn<Integer> ID =
new IntegerColumn("id", AbstractColumn.Attribute.NOT_NULL);
public static final AbstractColumn<String> ALIAS =
new StringColumn("alias");
// ... and some more...
}
Hope it's clear enough. These are then used with static import like:
map = JDBCHelper.selectFirst(UserDescriptor.INSTANCE, Arrays.asList(ID, ALIAS));
where the list (2. param) is what I need to fetch from table defined by UserDescriptor. map variable holds custom map, which internally has signature similar to <AbstractColumn<T>, T> and method
public T getValue(AbstractColumn<T> col);
so I'm getting the value then type-safe
Integer id = map.getValue(ID);
String alias = map.getValue(ALIAS);
This concept is currently working, but:
TableDescriptor concept is a bit verbose. I have many tables and need many times to write twice the type and this long start of each column definition
public static final AbstractColumn<Integer>
This line is result of well-know java limitation - not possible to extend enum class. Otherwise the TableDescriptor would be abstract class with field AbstractColumn<T> defined by explicit constructor and every successor would be enum with columns defined within instances.
This would come with following advantages:
Possibility to make whole thing (conditions, returning columns definition, .....) more type-safe, eg. only enum of specific type can be listed in List parameter for select from single table,
better readability and basis for new developers,
getAllColumns functionality can be done without reflection.
This is unfortunately not possible, so you're now my last hope. I know enum inheritance stuff is on SO many times, but I already have already working solution and maybe it's possible to improve it some other way in this specific case..
What may be some kind of hint - these descriptors must now be int the API part of project to selects to be possible. I was struggling with the way I'd put it to impl. and in API I'll let only some enum listing only overview of the columns:
public enum UserTableColumns {
ID,
ALIAS
}
and map it somehow to UserDescriptor - then I'd be able to use in most cases only this enum, but I didn't figure out yet how this should work..
Current signature of selectFisrt method is following:
CustomResultMap selectFirst(TableDescriptor td, List<AbstractColumn<?>> cols);
and one possible modification would be to change List<AbstractColumn<?>> to some list of enum values, which will be mapped to TableDescriptor so I can check that the values are from single table.
Edit: clarification
I'll try to summarize what I understood from your question and the comments:
Your API should contain an enum like UserTableColumn as well as a method that currently looks like T get(AbstractColumn<T>) but should return the correct type based on the generic type of the column. Since AbstractColumn basically is meant to be an implementation detail you'd like to replace that with the enum, e.g. to get something like this (which won't compile): T get(UserTableColumn<T>).
(Please correct me if I made a mistake somewhere.)
The problem with that is that generics are a compile time tool, i.e. the compiler needs to know about the type that is being used. However, enum values can't have generic types and any parameter (e.g. ID(Integer.class)) would not be available at compile time since it's basically an instance (i.e. runtime) value.
Thus you'll need something like AbstractColumn<T> although that might be another class that only contains the generic type (and implements some interface). That probably requires some manual definition or the use of a preprocessor (have a look at how Hibernate does it for its criteria api).
Related
I am designing a program that allows you to create an object with traits and then add it to a database. For example, a renting property like so:
public class Property
{
PropertyType type;
int bedrooms;
int bathrooms;
double squareFootage;
boolean furnished;
}
Then, you or other users can search the database for objects based on those traits. But here are the restrictions:
All properties have one of each trait defined (you can't leave one trait blank)
You may search for properties by any one trait, combination of traits, or no traits (to see all). AND you can specify a multiplicity for each trait. For example, you can specify a HOUSE with 2, 3 or 4 bedrooms and 2 or 3 bathrooms. Thereby not putting restrictions on square footage or furnishing.
This poses a problem, as the existence of a trait in the search criteria may or may not exist, and may have a multiplicity. Here is my current solution to hold the search criteria:
public class SearchCriteria
{
ArrayList<PropertyType> type;
ArrayList<int> bedrooms;
ArrayList<int> bathrooms;
ArrayList<double> squareFootage;
ArrayList<boolean> furnished;
}
The problem is that when I want to add another trait to Property, I have to add it to both these classes (and probably more in database controller etc) and add additional functions for it in each. What is a design pattern I can utilize to make this code more modular and abstract?
Essentially, a good answer would be a solution that allows the addition or removal of traits by only changing one class/file.
Simply using an interface Trait with an overidden function getTrait() wouldn't work because the return types aren't the same across all traits.
EDIT: I have to implement a SearchCriteria class because this program is run on a client/server connection, so SearchCriteria will be serialized and sent over a socket, not sent directly to the database.
If you only have a handful of traits, and they're fundamental to your business model, it's totally reasonable to have to change more than one class when you add a new trait or want to change the type of behavior of one of those traits.
However, if you're trying to come up with a model that can handle dynamically adding different types of traits to your object, you may consider not encoding the traits as class properties at all. Rather, have your model contain a list of Traits, where each Trait knows its TraitType. Each TraitType has a specific shape for its data, as well as a specific shape for its Criteria. This would enable you to define your model in a file or database somewhere, and change it on demand, and only have to change the code when you identify a new TraitType. But it would also be an enormous amount of work, and would only be worthwhile if your business needs require a high degree of configurability.
I have a class with different enums, for example:
class EligibilityRule{
ProductEligibility productEligibility;
CountryEligibility countryEligibility
}
enum ProductEligibility{
PRODUCT_X,
PRODUCT_Y
}
enum CountryEligibility{
US,
IN,
CN
..
}
I want to store these different enum class name and their value to database table called eligibility rule, and my table schema looks likes this,
String id => auto_increment id
String ruleType => enum class name (ex: ProductEligibility)
String ruleValue => enum value (ex: PRODUCT_X)
I am using JOOQ, in the past I had used forced type to just store the enum value. But, in this case I want to store enum class name and enum value. I also want to reconstruct the enum object when I query the records from db.
Are there any patterns I can follow or is there any functionality in JOOQ which I can extend to solve this problem?
JOOQ supports custom data types. This means that you can define a converter for your database field which is then automatically mapped to your custom type upon loading. The database field will still be a String, but the generated Record for the field will contain a Field<EligibilityRule>. This means that you do not have to explicitly store the class name.
To do this, you must register your converter in the code generator (taken from the above docs page):
<database>
<!-- Then, associate custom types with database columns -->
<forcedTypes>
<forcedType>
<!-- Specify the Java type of your custom type. This corresponds to the Converter's <U> type. -->
<userType>java.util.GregorianCalendar</userType>
<!-- Associate that custom type with your converter. -->
<converter>com.example.CalendarConverter</converter>
<!-- Add a Java regular expression matching fully-qualified columns. Use the pipe to separate several expressions.
If provided, both "expressions" and "types" must match. -->
<expression>.*\.DATE_OF_.*</expression>
<!-- Add a Java regular expression matching data types to be forced to
have this type.
Data types may be reported by your database as:
- NUMBER regexp suggestion: NUMBER
- NUMBER(5) regexp suggestion: NUMBER\(5\)
- NUMBER(5, 2) regexp suggestion: NUMBER\(5,\s*2\)
- any other form
It is thus recommended to use defensive regexes for types.
If provided, both "expressions" and "types" must match. -->
<types>.*</types>
</forcedType>
</forcedTypes>
</database>
See also the custom data type binding that JOOQ supports.
I see what you mean, in my case I am not creating new database field for each enum instead they will be stored as rule_type and rule_value(key/value) pair, where the key is the class name and the value is the enum value.
I see. Unfortunately, I do not think that it would be possible to do this in a type-safe manner. I believe this answer is pretty much what you're asking - a binding of a special type based on column value.
Since you are using enums however, you cannot have them extend a superclass as in the above answer (since all Enums implicitly extend java.lang.Enum and Java does not support multiple-inheritance). You might however try to slightly refactor your code and have all your enums implement some interface, i.e. :
enum ProductEligibility implements Rule {...};
enum CountryEligibility implements Rule {...};
With Rule being:
interface Rule { String getRuleType(); String getRuleValue(); }
And then creating a converter like in the example in the docs page or in the separate linked answer.
Of course, this also means that your Records would have a Field<Rule> field in them, not the specific type of the enum. If this is acceptable for you, it might be a possible way to go.
I did not get this part, Of course, this also means that your Records would have a Field<Rule> field in them, not the specific type of the enum.. Does this mean I will still store two fields in db, rule_type and rule_value with CustomConverter for each one of them?
No. You would still have only one converter, of type Converter<Object, Rule>. This converter would return either ProductEligibility or CountryEligibility, but it can't return both.
So, if your database table had something like:
eligiblity_rules
------------------
id user type value
234 223 com.foo.bar.ProductEligibility PRODUCT_Y
856 855 com.foo.bar.CountryEligibility US
Your converter would look something like this:
public Converter<Object, Rule> converter() {
return new Converter<Object, Rule>() {
#Override
public Rule from(Object t) {
// t here refers to the "value" db field above
if (checkIsProductEligibilityRule())
return ProductEligibility.fromValue(...);
else
return CountryEligibility.fromValue(...)
}
// Other converter methods
};
}
So in your JOOQ-based code, you would end up having:
EligibilityRuleRecord record = dslContext.selectFrom(ELIGIBILITY_RULE).where(...).fetchOne();
Rule rule = record.getValue();
Afterwards, if you want to use the specific rule type, you would need a check and a cast:
if (rule instanceof ProductEligibility) {
ProductEligibility peRule = (ProductEligibility) rule;
...
}
if (rule instanceof CountryEligibility) {
CountryEligibility ceRule = (CountryEligibility) rule;
...
}
...
The only reason for the type database field is for selecting the correct data. Unfortunately, the Java code does not know (at compile-time) what the type is going to be, hence you will need the class checks at runtime every time you wish to do know that field's specific type.
I have quite complex object structure (with bunch of primitive fields and object references) and want to test all fields except -a few- of them. As an example;
ComplexObject actual = generateMagically("someInput");
ComplexObject expected = ActualFunction.instance.workMagically(actual);
// we want to be sure that workMagically() would create a new ComplexObject
// with some fields are different than "actual" object.
// assertThat(actual, samePropertyValuesAs(expected)); would check all fields.
// what I want is actually; - notice that "fieldName1" and "fieldName2" are
// primitives belong to ComplexObject
assertThat(actual, samePropertyValuesExceptAs(expected, "fieldName1", "fieldName2"))
Since I don't want to check all fields manually, I believe there must be a way to write that test elegantly. Any ideas?
Cheers.
You should have a look at shazamcrest, a great Hamcrest extension that offers what you need.
assertThat(expected, sameBeanAs(expectedPerson).ignoring("fieldName1").ignoring("fieldName2"));
See https://github.com/shazam/shazamcrest#ignoring-fields
Just pass the list of properties to ignore as 2nd parameter to samePropertyValuesAs.
Hamcrest matcher API
public static <B> Matcher<B> samePropertyValuesAs(B expectedBean, String... ignoredProperties)
e.g.
samePropertyValuesAs(salesRecord,"id")
In general I see two solutions if ComplexObject can be modified by yourself.
You could introduce an interface that represents the properties of ComplexObject that are being changed by ActualFunction. Then you can test that all properties of that new interface have changed. This would require that ComplexObject implements that new interface.
Another approach would be to replace the properties of ComplextObject that are changed by ActualFunction with a new property of a new type that contains all those properties. A better design would then be to let ActualFunction return an instance of the new type.
Last time I had a similar requirements I came to the conclusion that manually writing both code and tests to assert that some values are updated is inherently fagile and error-prone.
I externalized the fields in a bag object and generated the Java source files for both the bag class itself and the copier at compile time. This way you can test actual code (the generator) and have the actual definition of the domain in exactly one place, so the copy code can't be out-of-date.
The language to describe the property can be anything you are comfortable with, from JSON-schema to XML to Java itself (Java example follows - custom annotations are to be consumed from the generator)
public class MyBag {
#Prop public int oh;
#Prop public String yeah;
}
I am designing an application that has two widgets:
-A list that contains arbitrary objects
-A table that displays specific properties of the currently selected object
The goal is to be able to pick an object from the list, look at the properties, and modify them as necessary. The list can hold objects of various types.
So say the list contains Vehicle objects and Person objects
public class Person
{
public String name;
public Integer age;
}
public class Vehicle
{
public String make;
public String model;
}
If I click on a Person object, the table will display the name and age, and I can assign new values to them. Similarly, if I click on a Vehicle object, it will display the make and model in the table and allow me to modify them.
I have considered writing a method like
public String[] getFields()
{
return new String[] {"name", "age"};
}
Which returns a list of strings that represent the instance variables I want to look at, and use some reflection methods to get/set them. I can define this getFields method in all of the classes so that I can use the table to handle arbitrary objects that might be thrown into the list.
But is there a way to design this so that I don't resort to reflection? The current approach seems like bad design.
On the other hand, I could create multiple TableModel objects, one for every possible class. The table would know what rows to display and how to access the object's instance variables. But then everytime a new class is added I would have to define a new table model, which also sounds like a weak design.
You have a class (Vehicle) and you know the names of some properties (make, model) that you want to be able to manipulate dynamically for an instance of this class through a JTable UI.
You have various different approaches to chose from.
A. Use the reflection API
This is what the reflection API is made for. If you want something so dynamic, there is nothing wrong with using reflection. The performance overhead will not be significant for this use case.
B. Use a library like beanutils that is based on the reflection API
This should be easier than directly using the reflection API, but it has the drawback that you need to include another dependency in your project.
C. Create dynamically at runtime the different TableModel classes.
You can do this using either the java compiler API or javassist. Based on information available at runtime, you are able to compile a new class for each different type of table model. If you follow this approach you must be aware that the creation of the class is a heavy task, so the first time you create a TableModel the application will take some time to respond.
What to chose?
Of course this is your decision. For the specific use case, the overhead added by reflection or beanutils is insignificant, so probably it is better to chose between A or B. In another use case where performance is more critical, then you could examine the C approach, without forgetting the class creation response time problem.
EDIT:
I just realized that in this specific use case there is another important functionality required. Convert from String to the appropriate data type of each property and vice cersa. Beanutils has perfect support for that, so it gets a plus here.
This is again, I guess, a 'best practices' question because i can think of some inelegant ways of getting my use case implemented.
My use case is as follows
Im writing a MethodManager(sort of) module which helps in the end user dealing with actual method(function) calls through a UI.
For this specific purpose i have a methodDefinition class which is an object form of what a method(function) looks like to my system.
A brief overview of what my methodDefinition's members look like is as follows
methodName -- String
methodInputs -- ArrayList<String>
methodResultType -- enum(STRING,MAP,LIST)
methodResult -- <<variable, on the basis of methodResultType>>
Now methodResult is variable and can be any of String, Map or List based on what methodResultType is set as.
I have created a MethodResultType class to account for methodResultType and it looks as follows
public enum MethodResultType {
LIST,
MAP,
STRING;
}
Now i know i have to write a class to account for methodResult and its variable nature based on methodResultType but cant think of a non botched up way to.
Any suggestions/ pointers in this regard would be greatly appreciated.
Thanks
p1ng
List, Map and String have a common ancestor class: java.lang.Object. methodResult can thus be an Object.
You could also wrap the result and its type into a MethodResult object, that would provide methods such as getType(), getValueAsString(), getValueAsList() and getValueAsMap(). These last three methods would throw an IllegalStateException if the type of the value is not the type returned by the method.