I need to create a structure that need to represent the following (For Category and Sub-Category).Its just one level deep. I am thinking of doing it using Java Enums and not sure how to represent this hierarchical structure.
My java objects (business objects) that represent a device will have both category and sub-category properties and I want to use an Enum instead of using integer codes like 100, 1 etc.. Some devices will have only category but not the sub-category (like 300 in the following example).
100 Switch
1 Interior
2 Exterior
200 Security Sensor
1 Door Sensor
2 Leak Sensor
3 Motion Sensor
300 Camera
Any help is appreciated.
Thanks
This java.dzone article showcases is a beautiful example of hierarchical enums:
public enum OsType {
OS(null),
Windows(OS),
WindowsNT(Windows),
WindowsNTWorkstation(WindowsNT),
WindowsNTServer(WindowsNT),
Windows2000(Windows),
Windows2000Server(Windows2000),
Windows2000Workstation(Windows2000),
WindowsXp(Windows),
WindowsVista(Windows),
Windows7(Windows),
Windows95(Windows),
Windows98(Windows),
Unix(OS) {
#Override
public boolean supportsXWindows() {
return true;
}
},
Linux(Unix),
AIX(Unix),
HpUx(Unix),
SunOs(Unix),
;
private OsType parent = null;
private OsType(OsType parent) {
this.parent = parent;
}
}
The article show cases lots of little tricks you can pull off with this set up.
I think this answer would be an excellent solution for you. With a type hierarchy like this:
public enum Component {
Interior(Part.Switch),
Exterior(Part.Switch),
DoorSensor(Part.SecuritySensor),
LeakSensor(Part.SecuritySensor),
MotionSensor(Part.SecuritySensor),
Camera(Part.Camera);
private final Part kindOf;
Component(Part kindOf) {
this.kindOf = kindOf;
}
enum Part {
Switch, SecuritySensor, Camera
}
}
More detail can be found in Chapter Enum from Effective Java 2nd Edition.
It seems unusual that you want to express this with an enumeration as opposed to inheritance. The thing with enumerations is that they're essentially compile-time constants, and if you wanted to generate more information in your hierarchy, you'd have to add more enumerations.
That can get messy, fast. It's also slightly contradictory to the real purpose of enumerations - as predefined constants instead of hierarchical entities.
What I propose is using an abstract class called CategoryBase in which to draw everything out of. Then, create your inheritance tree based off of that.
Here's a diagram:
The bulk of the work is really holding properties, and we don't ever expect those properties to be changed once created, so we can allow our abstract class to hold them. We've also set them as final, so they can't be modified, either.
public abstract class CategoryBase {
protected final int ranking;
protected final String name;
protected final SubCategory[] subCategories;
protected CategoryBase(int ranking, String name, SubCategory... subCategories) {
this.ranking = ranking;
this.name = name;
this.subCategories = subCategories;
}
public int getRanking() {
return ranking;
}
public String getName() {
return name;
}
public SubCategory[] getSubCategories() {
return subCategories;
}
}
From there, we can start basing our marker classes off of this - including SubCategory, since it's really just a holder of information that's represented in a different way.
This would also make writing the marker classes straightforward and simple. For example, here's Camera:
public class Camera extends CategoryBase {
protected Camera(int ranking, String name) {
super(ranking, name);
}
}
It's got a striking similarity to SubCategory - a SubCategory doesn't have any nested SubCategorys, so we don't pass in anything to the vararg portion of the constructor.
For something that does have SubCategorys, we need to instantiate them on construction. Here's SecuritySensor as an example.
public class SecuritySensor extends CategoryBase {
public SecuritySensor(int ranking, String name) {
super(ranking, name,
new SubCategory(1, "Door Sensor"),
new SubCategory(2, "Leak Sensor"),
new SubCategory(3, "Motion Sensor"));
}
}
This approach gives you some flexibility around ranking as well - if you wanted to be able to specify the exact ranking of the subcategories at runtime, you'd replace this constructor with one that supported the vararg signature.
you can do something like the code below. but that is probably not quite what you want. you could add the child enums to the constructor for the parent enum like here.
enum Stuff {
Swich,Sensor,Camera;
enum swich {
interior,exterior;
enum Where {
bathroom,kitchen
}
}
enum sensor {
door,leak,motion
}
}
Perhaps reconsider and do use integers here. However, instead of basing them on a decimal system (100, 200, 300,... for first level; 1, 2, 3,... for second level) base them on a binary representation.
// top-level
public static final int SWITCH = 1 << 16;
public static final int SECURITY_SENSOR = 2 << 16;
public static final int CAMERA = 4 << 16;
// sub-types of 'switch'
public static final int INTERIOR = SWITCH | 1;
public static final int EXTERIOR = SWITCH | 2;
// sub-types of 'security sensor'
public static final int DOOR_SENSOR = SECURITY_SENSOR | 1;
public static final int LEAK_SENSOR = SECURITY_SENSOR | 2;
public static final int MOTION_SENSOR = SECURITY_SENSOR | 4;
This allows you to do a weak form of inheritance testing:
if (value == SWITCH) {
// value is a switch, but not interior or exterior
} else if (value & SWITCH != 0) {
// value is interior or exterior
}
Does following code meet your request?
public enum Category {Switch, ...}
public enum SubCategory {Interior, ...}
Related
My question is how to use constant field values defined in predefined classes like I am practicing on the events program, and currently on action event, I have understand
the action listener part but when I go to action event part , I don't know how to use the static field constant, only I am able to use methods of the that classes, it will be more helpful if a simple example is given by you (simple not complex)
Elaboration:
I want to know how to use the ALT_MASK, ACTION_FIRST, ACTION_LAST constant
Also please show me how to create events of my own
Let's imagine you have class:
public Class ConstantsHere {
public static final int INTEGER_CONSTANT = 5;
}
Then, you want to use it in another class, and you write code like this:
//some code
if (myValue < ConstantsHere.INTEGER_CONSTANT) {
//do something
}
As mentioned in commens, Java Enum may be a good choice for this task:
public enum Action {
ALT_MASK, ACTION_FIRST, ACTION_LAST;
}
Usage:
//some code
if (myValue == Action.ACTION_LAST) {
//do something
}
To make things clear, Enum should be used in case when some variable may take limited number of values. For example, human gender can be only male or female (please do not take this as offensive for transsexuals, statement used only for explanation purposes), so it might be a good idea to use Enum for that instead of constants 0 and 1 (or M and F), just because we can put other number (or constant) there and break the logic.
Using enums example.
public enum UserStatus {
PENDING("P"), ACTIVE("A"), INACTIVE("I"), DELETED("D");
private String statusCode;
private UserStatus(String s) {
statusCode = s;
}
public String getStatusCode() {
return statusCode;
}
}
public void method(UserStatus status) {
System.out.println(status.getStatusCode());
}
}
I have several hypothetical 2 - dimensional tables, from which I am to fetch data. I need to make a method that will take in the table id and the "coordinates" of the desired item, and return the item. So far, I have tried making it with multi-layered switches, but I am wondering whether there is any better way to go about this, as the switch code seems too long to be the optimal solution. Any help would be greatly appreciated.
An idea of what my code looks like:
switch(tableId) {
case "table 1":
switch(top) {
case "whatever":
switch(side) {
// et cetera
case "table 2":
// etc
}
Use polymorphism.
Create an interface SearchableTable:
public interface SearchableTable<T> {
T getItem(int x, int y);
}
If these tables are under your control, let them implement this interface. Otherwise, wrap the tables with your own wrapper-classes like so:
public class SearchableTableWrapper implements SearchableTable<MyItemType> {
private final Table wrappedThirdPartyTable;
public SearchableTableWrapper(Table wrappedThirdPartyTable) {
this.wrappedThirdPartyTable = wrappedThirdPartyTable;
}
public MyItemType getItem(int x, int y) {
...
}
}
Now, in the general class where you want to implement a general method that accepts a table id and indices of the item, accept the table itself and invoke its getItem method, like so:
public class TableUtils {
public static <T> T getItem(SearchableTable<T> table, int x, int y) {
return table.getItem(x, y);
}
}
If you have to get table id instead of table, just keep a Map from table id to the relevant SearchableTable, like so:
public class TableUtils {
private static Map<Long, SearchableTable> tableIdToSearchableTable;
public static <T> T getItem(SearchableTable<T> table, int x, int y) {
return table.getItem(x, y);
}
}
This map can be loaded with the actual SearchableTables in several ways, either via static initializer block or static addTable method or you could turn TableUtils to be non-static at all, whatever fits you best.
The main thing here is to use polymorphism.
EDIT
You don't need an enum. Your Table1 from your comment should look like this:
public class Table1 implements SearchableTable<String> {
public String getItem(int x, int y) {
// use x and y to fetch the item friom the 2-dimensional data structure
}
}
You have to rewrite everything in a more object oriented way, one smart way to do it in Java cold be the use of some 'tuned' enums :
enum activity { WHATEVER, SOMETHINGELSE } //Use the same principle as in the enum below ...
enum tables {
TABLE1(activity.WHATEVER),
TABLE2(activity.SOMETHINGELSE),
private activity activity;
tables(activity activity) {
this.activity = activity;
}
public activity activity() {
return this.activity;
}
}
After creating all the needed enum for each needed level, you can use the following "trick" to avoid the long and multilevel switch conditional statement :
String tableId = ...
//Load the table
tables table = tables.valueOf(tableId);
//Call the related attached activity ...
table.activity();
Of course the enum element must have the same name as the variable name that you want to intercept(the same name that you would have put into the check condition of the if or switch statement).
Another similar result can be achieved using a map instead of an enum ...
Take a look at the Command Pattern, for further information .
I have a class and there are variables inside it as well. Sometimes I want to ignore some fields and sometimes not when deserializing (maybe at serializing too). How can I do it at Jackson?
For serialization, "filtering properties" blog entry should help. Deserialization side has less support, since it is more common to want to filter out stuff that is written.
One possible approach is to sub-class JacksonAnnotationIntrospector, override method(s) that introspect ignorability of methods (and/or fields) to use whatever logic you want.
It might also help if you gave an example of practical application, i.e what and why you are trying to prevent from being deserialized.
You might want to use JsonViews ( took it originally from http://wiki.fasterxml.com/JacksonJsonViews - broken now - web archive link: https://web.archive.org/web/20170831135842/http://wiki.fasterxml.com/JacksonJsonViews )
Quoting it:
First, defining views means declaring classes; you can reuse existing ones, or just create bogus classes -- they are just view identifiers with relationship information (child inherits view membership from parents):
// View definitions:
class Views {
static class Public { }
static class ExtendedPublic extends PublicView { }
static class Internal extends ExtendedPublicView { }
}
public class Bean {
// Name is public
#JsonView(Views.Public.class) String name;
// Address semi-public
#JsonView(Views.ExtendPublic.class) Address address;
// SSN only for internal usage
#JsonView(Views.Internal.class) SocialSecNumber ssn;
}
With such view definitions, serialization would be done like so:
// short-cut:
objectMapper.writeValueUsingView(out, beanInstance, ViewsPublic.class);
// or fully exploded:
objectMapper.getSerializationConfig().setSerializationView(Views.Public.class);
// (note: can also pre-construct config object with 'mapper.copySerializationConfig'; reuse)
objectMapper.writeValue(out, beanInstance); // will use active view set via Config
// or, starting with 1.5, more convenient (ObjectWriter is reusable too)
objectMapper.viewWriter(ViewsPublic.class).writeValue(out, beanInstance);
and result would only contain 'name', not 'address' or 'ssn'.
You should probably look at the modules feature of recent Jackson versions.
One possible mechanism would be to use a BeanDeserializerModifier.
I've been looking for a useful online tutorial or example, but nothing immediately appears. It might be possible to work something up if more is known of your context. Are you managing your ObjectMappers manually, or using them in a JAX-RS setting, injected in Spring, or what?
I searched the entire web (yes I did) to find the answer. then I wrote something on my own.
I'm working with Jackson ion deserialisation. I wrote a custom reader that ignores the fields dynamically.
You can do the same thing for json deserialisation.
Lets assume an entity like this.
User {
id
name
address {
city
}
}
Create a tree structure to represent field selection.
public class IonField {
private final String name;
private final IonField parent;
private final Set<IonField> fields = new HashSet<>();
// add constructs and stuff
}
Custom Ion Reader extending from amazon ion-java https://github.com/amzn/ion-java
public class IonReaderBinaryUserXSelective extends IonReaderBinaryUserX {
private IonField _current;
private int hierarchy = 0;
public IonReaderBinaryUserXSelective(byte[] data, int offset, int length,
IonSystem system, IonField _current) {
super(system, system.getCatalog(), UnifiedInputStreamX.makeStream(data, offset, length));
this._current = _current;
}
#Override
public IonType next() {
IonType type = super.next();
if (type == null) {
return null;
}
String file_name = getFieldName();
if (file_name == null || SystemSymbols.SYMBOLS.equals(file_name)) {
return type;
}
if (type == IonType.STRUCT || type == IonType.LIST) {
IonField field = _current.getField(getFieldName());
if (field != null) {
this._current = field;
return type;
} else {
super.stepIn();
super.stepOut();
}
return next();
} else {
if (this._current.contains(file_name)) {
return type;
} else {
return next();
}
}
}
#Override
public void stepIn() {
hierarchy = (hierarchy << 1);
if (getFieldName() != null && !SystemSymbols.SYMBOLS.equals(getFieldName())) {
hierarchy = hierarchy + 1;
}
super.stepIn();
}
#Override
public void stepOut() {
if ((hierarchy & 1) == 1) {
this._current = this._current.getParent();
}
hierarchy = hierarchy >> 1;
super.stepOut();
}
Construct dynamic view. This Tree dynamically created and passed to the reader to deserialise.
Let's say we only need city inside the address.
IonField root = new IonField("user", null);
IonField address = new IonField("address", root);
IonField city = new IonField("city", address);
address.addChild(city);
root.addChild(id);
//now usual stuff.
IonFactory ionFactory = new IonFactory();
IonObjectMapper mapper = new IonObjectMapper(ionFactory);
File file = new File("file.bin"); // ion bytes
byte[] ionData = Files.readAllBytes(file.toPath());
IonSystem ionSystem = IonSystemBuilder.standard().build();
IonReader ionReader = new IonReaderBinaryUserXSelective(ionData, 0, ionData.length, ionSystem, root);
User user = mapper.readValue(ionReader, User.class);
I am going to develop a web crawler using java to capture hotel room prices from hotel websites.
In this case I want to capture room price with the room type and the meal type, so my algorithm should be intelligent to handle that.
For example:
Room type: Deluxe
Meal type: HalfBoad
price : $20.00
The main problem is room prices can be in different ways in different hotel sites. So my algorithm should be independent from hotel sites.
I am plan to use above room types and meal types as a fuzzy sets and compare the words in webpage with above fuzzy sets using a suitable membership function.
Anyone experienced with this? or have an idea for my problem?
There are two ways to approach this problem:
You can customize your crawler to understand the formats used by different Websites; or
You can come up with a general ("fuzzy") solution.
(1) will, by far, be the easiest. Ideally you want to create some tools that make this easier so you can create a filter for any new site in minimal time. IMHO your time will be best spent with this approach.
(2) has lots of problems. Firstly it will be unreliable. You will come across formats you don't understand or (worse) get wrong. Second, it will require a substantial amount of development to get something working. This is the sort of thing you use when you're dealing with thousands or millions of sites.
With hundreds of sites you will get better and more predictable results with (1).
As with all problems, design can let you deliver value adapt to situations you haven't considered much more quickly than the general solution.
Start by writing something that parses the data from one provider - the one with the simplest format to handle. Find a way to adapt that handler into your crawler. Be sure to encapsulate construction - you should always do this anyway...
public class RoomTypeExtractor
{
private RoomTypeExtractor() { }
public static RoomTypeExtractor GetInstance()
{
return new RoomTypeExtractor();
}
public string GetRoomType(string content)
{
// BEHAVIOR #1
}
}
The GetInstance() ,ethod lets you promote to a Strategy pattern for practically free.
Then add your second provider type. Say, for instance, that you have a slightly more complex data format which is a little more prevalent than the first format. Start by refactoring what was your concrete room type extractor class into an abstraction with a single variation behind it and have the GetInstance() method return an instance of the concrete type:
public abstract class RoomTypeExtractor
{
public static RoomTypeExtractor GetInstance()
{
return SimpleRoomTypeExtractor.GetInstance();
}
public abstract string GetRoomType(string content);
}
public final class SimpleRoomTypeExtractor extends RoomTypeExtractor
{
private SimpleRoomTypeExtractor() { }
public static SimpleRoomTypeExtractor GetInstance()
{
return new SimpleRoomTypeExtractor();
}
public string GetRoomType(string content)
{
// BEHAVIOR #1
}
}
Create another variation that implements the Null Object pattern...
public class NullRoomTypeExtractor extends RoomTypeExtractor
{
private NullRoomTypeExtractor() { }
public static NullRoomTypeExtractor GetInstance()
{
return new NullRoomTypeExtractor();
}
public string GetRoomType(string content)
{
// whatever "no content" behavior you want... I chose returning null
return null;
}
}
Add a base class that will make it easier to work with the Chain of Responsibility pattern that is in this problem:
public abstract class ChainLinkRoomTypeExtractor extends RoomTypeExtractor
{
private final RoomTypeExtractor next_;
protected ChainLinkRoomTypeExtractor(RoomTypeExtractor next)
{
next_ = next;
}
public final string GetRoomType(string content)
{
if (CanHandleContent(content))
{
return GetRoomTypeFromUnderstoodFormat(content);
}
else
{
return next_.GetRoomType(content);
}
}
protected abstract bool CanHandleContent(string content);
protected abstract string GetRoomTypeFromUnderstoodFormat(string content);
}
Now, refactor the original implementation to have a base class that joins it into a Chain of Responsibility...
public final class SimpleRoomTypeExtractor extends ChainLinkRoomTypeExtractor
{
private SimpleRoomTypeExtractor(RoomTypeExtractor next)
{
super(next);
}
public static SimpleRoomTypeExtractor GetInstance(RoomTypeExtractor next)
{
return new SimpleRoomTypeExtractor(next);
}
protected string CanHandleContent(string content)
{
// return whether or not content contains the right format
}
protected string GetRoomTypeFromUnderstoodFormat(string content)
{
// BEHAVIOR #1
}
}
Be sure to update RoomTypeExtractor.GetInstance():
public static RoomTypeExtractor GetInstance()
{
RoomTypeExtractor extractor = NullRoomTypeExtractor.GetInstance();
extractor = SimpleRoomTypeExtractor.GetInstance(extractor);
return extractor;
}
Once that's done, create a new link for the Chain of Responsibility...
public final class MoreComplexRoomTypeExtractor extends ChainLinkRoomTypeExtractor
{
private MoreComplexRoomTypeExtractor(RoomTypeExtractor next)
{
super(next);
}
public static MoreComplexRoomTypeExtractor GetInstance(RoomTypeExtractor next)
{
return new MoreComplexRoomTypeExtractor(next);
}
protected string CanHandleContent(string content)
{
// Check for presence of format #2
}
protected string GetRoomTypeFromUnderstoodFormat(string content)
{
// BEHAVIOR #2
}
}
Finally, add the new link to the chain, if this is a more common format, you might want to give it higher priority by putting it higher in the chain (the real forces that govern the order of the chain will become apparent when you do this):
public static RoomTypeExtractor GetInstance()
{
RoomTypeExtractor extractor = NullRoomTypeExtractor.GetInstance();
extractor = SimpleRoomTypeExtractor.GetInstance(extractor);
extractor = MoreComplexRoomTypeExtractor.GetInstance(extractor);
return extractor;
}
As time passes, you may want to add ways to dynamically add new links to the Chain of Responsibility, as pointed out by Cletus, but the fundamental principle here is Emergent Design. Start with high quality. Keep quality high. Drive with tests. Do those three things and you will be able to use the fuzzy logic engine between your ears to overcome almost any problem...
EDIT
Translated to Java. Hope I did that right; I'm a little rusty.
Does anyone know a library or some at least some research on creating and using persistent data structures in Java? I don't refer to persistence as long term storage but persistence in terms of immutability (see Wikipedia entry).
I'm currently exploring different ways to model an api for persistent structures. Using builders seems to be a interesting solution:
// create persistent instance
Person p = Builder.create(Person.class)
.withName("Joe")
.withAddress(Builder.create(Address.class)
.withCity("paris")
.build())
.build();
// change persistent instance, i.e. create a new one
Person p2 = Builder.update(p).withName("Jack");
Person p3 = Builder.update(p)
.withAddress(Builder.update(p.address())
.withCity("Berlin")
.build)
.build();
But this still feels somewhat boilerplated. Any ideas?
Builders will make your code too verbose to be usable. In practice, almost all immutable data structures I've seen pass in state through the constructor. For what its worth, here are a nice series of posts describing immutable data structures in C# (which should convert readily into Java):
Part 1: Kinds of Immutability
Part 2: Simple Immutable Stack
Part 3: Covariant Immutable Stack
Part 4: Immutable Queue
Part 5: Lolz! (included for completeness)
Part 6: Simple Binary Tree
Part 7: More on Binary Trees
Part 8: Even More on Binary Trees
Part 9: AVL Tree Implementation
Part 10: Double-ended Queue
Part 11: Working Double-ended Queue Implementation
C# and Java are extremely verbose, so the code in these articles is quite scary. I recommend learning OCaml, F#, or Scala and familiarizing yourself with immutability with those languages. Once you master the technique, you'll be able to apply the same coding style to Java much more easily.
I guess the obvious choices are:
o Switch to a transient data structure (builder) for the update. This is quite normal. StringBuilder for String manipulation for example. As your example.
Person p3 =
Builder.update(p)
.withAddress(
Builder.update(p.address())
.withCity("Berlin")
.build()
)
.build();
o Always use persistent structures. Although there appears to be lots of copying, you should actually be sharing almost all state, so it is nowhere near as bad as it looks.
final Person p3 = p
.withAddress(
p.address().withCity("Berlin")
);
o Explode the data structure into lots of variables and recombine with one huge and confusing constructor.
final Person p3 = Person.of(
p.name(),
Address.of(
p.house(), p.street(), "Berlin", p.country()
),
p.x(),
p.y(),
p.z()
);
o Use call back interfaces to provide the new data. Even more boilerplate.
final Person p3 = Person.of(new PersonInfo(
public String name () { return p.name(); )
public Address address() { return Address.of(new AddressInfo() {
private final Address a = p.address();
public String house () { return a.house() ; }
public String street () { return a.street() ; }
public String city () { return "Berlin" ; }
public String country() { return a.country(); }
})),
public Xxx x() { return p.x(); }
public Yyy y() { return p.y(); }
public Zzz z() { return p.z(); }
});
o Use nasty hacks to make fields transiently available to code.
final Person p3 = new PersonExploder(p) {{
a = new AddressExploder(a) {{
city = "Berlin";
}}.get();
}}.get();
(Funnily enough I was just put down a copy of Purely Functional Data Structures by Chris Okasaki.)
Have a look at Functional Java. Currently provided persistent datastructures include:
Singly-linked list (fj.data.List)
Lazy singly-linked list (fj.data.Stream)
Nonempty list (fj.data.NonEmptyList)
Optional value (a container of length 0 or 1) (fj.data.Option)
Set (fj.data.Set)
Multi-way tree (a.k.a. rose tree) (fj.data.Tree)
Immutable map (fj.data.TreeMap)
Products (tuples) of arity 1-8 (fj.P1..P8)
Vectors of arity 2-8 (fj.data.vector.V2..V8)
Pointed list (fj.data.Zipper)
Pointed tree (fj.data.TreeZipper)
Type-safe, generic heterogeneous list (fj.data.hlist.HList)
Immutable arrays (fj.data.Array)
Disjoint union datatype (fj.data.Either)
A number of usage examples are provided with the binary distribution. The source is available under a BSD license from Google Code.
I implemented a few persistent data structures in Java. All open source (GPL) on Google code for anyone who is interested:
http://code.google.com/p/mikeralib/source/browse/#svn/trunk/Mikera/src/mikera/persistent
The main ones I have so far are:
Persistent mutable test object
Persistent hash maps
Persistent vectors/lists
Persistent sets (including a specialised persistent set of ints)
Follow a very simple tentative with dynamic proxy:
class ImmutableBuilder {
static <T> T of(Immutable immutable) {
Class<?> targetClass = immutable.getTargetClass();
return (T) Proxy.newProxyInstance(targetClass.getClassLoader(),
new Class<?>[]{targetClass},
immutable);
}
public static <T> T of(Class<T> aClass) {
return of(new Immutable(aClass, new HashMap<String, Object>()));
}
}
class Immutable implements InvocationHandler {
private final Class<?> targetClass;
private final Map<String, Object> fields;
public Immutable(Class<?> aTargetClass, Map<String, Object> immutableFields) {
targetClass = aTargetClass;
fields = immutableFields;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("toString")) {
// XXX: toString() result can be cached
return fields.toString();
}
if (method.getName().equals("hashCode")) {
// XXX: hashCode() result can be cached
return fields.hashCode();
}
// XXX: naming policy here
String fieldName = method.getName();
if (method.getReturnType().equals(targetClass)) {
Map<String, Object> newFields = new HashMap<String, Object>(fields);
newFields.put(fieldName, args[0]);
return ImmutableBuilder.of(new Immutable(targetClass, newFields));
} else {
return fields.get(fieldName);
}
}
public Class<?> getTargetClass() {
return targetClass;
}
}
usage:
interface Person {
String name();
Person name(String name);
int age();
Person age(int age);
}
public class Main {
public static void main(String[] args) {
Person mark = ImmutableBuilder.of(Person.class).name("mark").age(32);
Person john = mark.name("john").age(24);
System.out.println(mark);
System.out.println(john);
}
}
grow directions:
naming policy (getName, withName, name)
caching toString(), hashCode()
equals() implementations should be straightforward (although not implemented)
hope it helps :)
It is very difficult, if not impossible, to make things immutable that ain't designed so.
If you can design from ground up:
use only final fields
do not reference non immutable objects
Do you want immutability :
so external code cannot change the data?
so once set a value cannot be changed?
In both cases there are easier ways to accomplish the desired result.
Stopping external code from changing the data is easy with interfaces:
public interface Person {
String getName();
Address getAddress();
}
public interface PersonImplementor extends Person {
void setName(String name);
void setAddress(Address address);
}
public interface Address {
String getCity();
}
public interface AddressImplementor {
void setCity(String city);
}
Then to stop changes to a value once set is also "easy" using java.util.concurrent.atomic.AtomicReference (although hibernate or some other persistence layer usage may need to be modified):
class PersonImpl implements PersonImplementor {
private AtomicReference<String> name;
private AtomicReference<Address> address;
public void setName(String name) {
if ( !this.name.compareAndSet(name, name)
&& !this.name.compareAndSet(null, name)) {
throw new IllegalStateException("name already set to "+this.name.get()+" cannot set to "+name);
}
}
// .. similar code follows....
}
But why do you need anything more than just interfaces to accomplish the task?
Google Guava now hosts a variety of immutable/persistent data structures.