Rearranging objects in Java (e.g. for Minecraft NBT files) - java

These are some preliminary sorts for something that is going to be a conversion tool for NBT-Files. This is a file format providing nested objects, those of you knowing Minecraft might know it.
So lets consider we have an object like this:
object.name = String
object.id = int
object.randomInformation = Object
object.storedObjects = Object[]
What I'm trying to achieve is this:
The user should be able to give config files for different versions of the object.
This may look like this:
Version1.dat:
someCoolObjectName.id = 1
Version2.dat:
someCoolObjectName.id = 2
So on conversion from Version1 to Version 2 the program reads the NBT-File, search for any object with an id of 1, change it to 2 and write it into another file.
So far not a big deal.
The Problem starts, when it comes to real changes in the version. This includes:
renamed properties
moved properties
added/deleted properties
properties that contains objects which have to be treated as if they where a "normal" object itself (if you are into Minecraft, you may think of items in a chest)
I thought about something like this:
Version1.dat:
foo:object.id=1
bar:object.randomInformation
*:object.storedObjects
Version2.dat:
foo:object.id=2
bar:object.usefulInformation
blubb:object.(int)addedInformation
*:object.storedObjects
This would mean on conversion from 1 to 2:
change id from 1 to 2
rename randomInformation to usefulInformation
add a property addedInformation, which is an integer
convert every Object in object.storedObjects just like a normal object
just copy every other property
This would mean i have to implement a whole "language" for the config file and convert that into a list of "commands" that have to be done to each object. Isn't there an easier way to do this? Or is this already a good idea?
Remember, I'll have a whole lot of different objects in each version, where mostly only the id has to be changed. But on some objects, identified by their id, various changes has to be made. And I don't want to change the program code for every new version.

It's not so hard! But you need to write the conversion methods from the two object or if the second object extends the first object, then you can simple copy the fields of the first object. If the fields aren't visible, then you can use reflection for copying them.
For Minecraft NBT management you can use the JNBT library.

Related

Java Object Clone (additional class member) using Prototype, Builder Pattern

It is not easy to explain my issue.
JPA creates some complex objects for calculations, which are stored in a database.
We decided to set the results in a working copy of this objects.
This means for each object model we created a seperated working copy model file with the same fields but some other LocalDates values and new result fields.
When the calculation was starting the working copies are instantiated.
This approach is not the best i think.
I think of the prototype pattern to clone the object.
There i come to the problem how to add the new fields. How?
Instantion costs and ist creates lots of additionals model class files.
I only think of put the result field in the calculation data models as transient fields.
Maybe inner class or local class?
I also tried to use an interface as data bucket.
But thats not the realy purpose of interfaces and also it works only with many curious trick.
For Unit Tests and user input i think it is the best to use the builder pattern and then tell JPA to store the parent object, or not?
Sorry but my answer was to long for a comment :(
There is big complex object relationship with Lists and Sets One To Many etc. relationship. When i set the result i a new class i cant determine the right object e.g. in a list. So we bild the same structurefor these result and seperated these classes in a package. Maybe it is possible to dont build the structure a second time with also references to the "basic classes". It should be sufficient to reference to each basic class a result class. It would only a little bit more navigation to get values from deeper classes. For a similiar use case there must be a best practise, or? Interfaces or sth. I very dislike the many classes for the result. Is it not possible to clone and add classmember to it for the result or to logical group easier or something like this?
It could be a solution for somebody:
http://help.eclipse.org/luna/index.jsp?topic=%2Forg.eclipse.jdt.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fjdt%2Fcore%2FIWorkingCopy.html
Here you will work with the Eclipse API and create IWorkingCopies.
For the described task toooo much.

Setting properties using strings

Is it possible to set a property on an object using a string as the property name? I am quite new to Java but in JavaScript I would just do something like this:
Object[propertyNameAsString] = value
After searching around I found how to get a property using a string, but not how to set one. I also came across something called a Properties object, is that what I need to be using?
Basically I just want to loop through an array filled with image names and then set their respective properties onto an object which I will use to store the actual images. Is this possible in Java or should I do it another way?
Edit:
This is what my array looks like:
static String pngs[] = {"staminaBox", "staminaBoxR", "healthBox", "healthBoxR", "moveBox", "goButton"};
Ideally I want to loop through them and add properties to an assets class like so:
for (int i = 0; i < pngs.length; i++) {
Assets.pngs[i] = createImageFromUrl(pngs[i] + ".png");
}
But now I'm realizing this wouldn't work because in my assets class I have to previously define the properties like:
public static Image staminaBox;
And the whole point of me wanting to do this in the first place was so that I didn't have to write out declarations for every single image I wanted to add. I'm used to the loose nature of JavaScript, but does this mean there is no way of getting around these explicit declarations of properties? Will a HashMap let me accomplish this?
You might be talking about a couple different things. Are you talking about setting the value of variables defined inside a class? If so, you might be able to hack something together using reflection, but it's not a "gimme" in Java like it is in javascript.
You might also look into using a HashMap of properties to their values, or like you said, the Properties object (which is pretty much just a Map itself).
You can use the Reflection API. Keep in mind that it will get messy very quickly.
Because Java uses the Getter and Setter pattern, you likely won't be assigning a value to a member variable but calling a method which itself assigns the value.
How do I invoke a Java method when given the method name as a string?

Convert a string into a variable in java

I am building a DAQ in a Java based Platform called KMax. This platform, has a design interface to use objects like histograms. Each histogram has a name, which is declared on the design interface.
To call the histogram in the code you have to use
hist = tlsh.getKmaxHist("DATA");
The string DATA is the name that the user gives in the design interface and hist is the variable that refers to the object. Every histogram object has certain classes it can use. For instance hist.getSum() gives the total sum of the histogram.
In my DAQ I have many histograms. My plan is to create a slider box that will pick the histogram, that the user wants to apply some functions(such as getSum()). The slider box has a class(string getProperty("VALUE")) that returns the value that the user has selected.
The plan is to use something like sliderBox.getProperty("VALUE").getSum(). Of course something like that is not valid, therefore I was wondering if there is a way to "convert" the string that the getProperty() returns, into a variable already defined in the code.
Sounds like a Map will do what you need. You can put the histograms in a Map keyed by whatever the property value is.
Map<String,Histogram> histograms = new HashMap<String,Histogram>();
histograms.put("PropertyValue1", histogram1);
histograms.put("PropertyValue2", histogram2);
String desiredHistogram = silderBox.getProperty("VALUE");
Histogram histogramToUse = histograms.get(desiredHistogram);
histogramToUse.getSum(); // do whatever you need to with this
You'll want to check for nulls and all that stuff too.
It looks to me like you need a Map<String, Histogram>. Variable names are lost when java code gets compiled.
You can use the *BeanInfo class mechanism. For instance. Having a class Hist, one can write a HistBeanInfo with a "sum" property. Though these classes were intended for GUI builders with components on palettes listing heterogene properties, one can use them indepedantly.
The BeanInfo classes might be generated.
This still is a far way to actually instrument that information, maybe using reflection.
An alternative to BeanInfo would be using home-brew annotations, but with BeanInfo you have an API supported by some IDEs.
Store it in a map:
yourHistogramsMap.get(sliderBox.getProperty("VALUE")).getSum();
Of course, you have to store your histograms there first.

Transfer of a Java Serialized Object

Is it possible to declare an instance of a serializable object in one Java program / class, then repeat the definitions of the internal objects in a different program /class entirely, and load in a big complex object from a data file? The goal is to be able to write an editor for items that's kept locally on my build machine, then write the game itself and distribute it to people who would like to play the game.
I'm writing a game in Java as a hobbyist project. Within my game, there's an a family of classes that extend a parent class, GameItem. Items might be in various families like HealingPotion, Bomb, KeyItem, and so on.
class GameItem implements Serializable {
String ItemName
String ImageResourceLocation
....}
What I want to do is include definitions of how to create each item in a particularly family of items, but then have a big class called GameItemList, which contains all possible items that can occur as you play the game.
class GameItemList implements Serializable {
LinkedList<GameItem>gameItemList;
//methods here like LookUpByName, LookUpByIndex that return references to an item
}
Maybe at some point - as the player starts a new game, or as the game launches, do something like:
//create itemList
FileInputStream fileIn = new FileInputStream("items.dat");
ObjectInputStream in = new ObjectInputStream(fileIn);
GameItemList allItems = (GameItemList)in.readObject();
in.close();
//Now I have an object called allItems that can be used for lookups.
Thanks guys, any comments or help would be greatly appreciated.
When you serialize an object, every field of the object is serialized, unless marked with transient. And this behavior is of course recursive. So yes, you can serialize an object, then deserialize it, and the deserialized object will have the same state as the serialized one. A different behavior would make serialization useless.
I wouldn't use native serialization for long-term storage of data, though. Serialized objects are hard to inspect, impossible to modify using a text editor, and maintaining backward compatibility with older versions of the classes is hard. I would use a more open format like XML or JSON.
Yes, that is possible. If an object is correctly serialized, it can be deserialized in any other machine as long as the application running there knowns the definition of the class to be deserialized.
This will work, but Java serialization is notorious for making it hard to "evolve" classes -- the internal representation is explicitly tied to the on-disk format. You can work around this with custom reader / writer methods, but you might consider a more portable format like JSON or XML instead of object serialization.

Is it possible to send an object to a file in a format that is human readable?

I am working on a project for my advanced Java class, and the assignment says he wants us
to send an object to a file, which is easy enough, but that he also wants the file to be human readable and editable. I sent him an e-mail 3 days ago and he hasn't responded, so
I am kind of stuck between a rock and hard place since the project is due in 3 days.
So would any of you clever programmers be able to fill me in on the secret that apparently I am left out of.
How do you send an object to a file that reads like English?
I want to have the ability to both read and write a to-do item to a
file. I see our application looking like:
When it first starts, the program asks the user if there is a file containing to-do items. If so, the user will name the file, the
program will read it in and continue.
When the user decides to exit, the program will prompt the user - to ask if the to-do items should be saved to a file - if so, the
user will name the file and the program will write them out in
such a fashion that it can read them in again.
I want these file to be human readable (and editable). No binary data.
No counting. My advice to you would be to have a method somewhere that
looked like:
public ToDoItem getToDoItem(FileInputStream fis) {
// ...
}
and
public void writeToDoItem(FileOutputStream fos) {
// ...
}
Think of your serialization model. The ObjectOutputStream might write bytes, but is there another way you could represent the object and write it through some other output stream that writes human-readable text?
This is going to depend on the type of object you have. You will have to tailor it to a particular type of data.
For example, if you have an Object
String title;
List<Integer> ids;
then you could save it as JSON
{
title: 'aaaa',
ids: [ 1,2,3,4,5 ]
}
which is equivalent, but much more readable than a binary ObjectOutputStream.
Again, this won't work for all kinds of data.
There is an XML-based bean serialization, too, which also works with almost all data, but I would not call that human-readable.
Think how you would represent an object on paper in such a way that it could be reconstructed unambiguously. You'd probably list the class name, then you'd list each field name and its current value. If the field was a primitive, the value would be just the primitive value. If it was a reference type, you'd represent the object recursively using this procedure. If it was an array, you'd list each element value.
There are various standard ways of formatting such a representation (XML and JSON to name a couple). The key is to make it a text-only representation so it is human-readable.
You can have a try with JAXB.(Java Architecture for XML Binding)
It can send a JAXB styled object to a xml file.
But you should define a XML Schema file at first.
For more:http://jaxb.java.net/tutorial/
The human readable that you desire could be XML or JSON. My answer How to create object tree from xsd in Java?
might help in giving you pointers to the approach you can follow to achieve what you want.

Categories