Let's say the following XML is given:
<?xml version="1.0" encoding="UTF-8"?>
<ResC>
<Err text="Error text 1"/>
<ConRes>
<Err text="Error text 2"/>
<ConList>
<Err text="Error text 3"/>
<Con>
<Err text="Error text 4"/>
</Con>
</ConList>
</ConRes>
</ResC>
As you can see the <Err> element may appear on every level of the XML.
Using Simple I would like to deserialize this XML. So, I have created the following class:
#Element(required=false)
public class Err {
#Attribute
private String text;
public void setText(String text) { this.text = text; }
public String getText() { return text; }
}
However, how do I have to annotate the classes for <ResC>, <ConRes>, <ConList> and <Con>? Do I really have to declare an attribute of type <Err> in every single class in which it may appear? This seems like a lot of overhead. If so, then I would have to check every single object if it contains an error.
Is there any better and easier way? :-)
Thanks,
Robert
The important thing to remember is that Simple XML should be able to follow any structure that you can logically generate using classes. So you could just create a BaseClass that uses an error interface and applies the Decorator pattern so that it passes all of that through to a concrete error class without any of the implementing objects needing to know what they have been given.
That probably made no sense. How about I just show you...okay...I just went away and implemented exactly what I was thinking and here are the results (full code link):
The Main File:
package com.massaiolir.simple.iface;
import java.io.File;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
public class Main {
public static void main(String[] args) throws Exception {
Serializer serial = new Persister();
ResC resc = serial.read(ResC.class, new File("data/testdata.xml"));
System.out.println(" == Printing out all of the error text. == ");
System.out.println(resc.getErrorText());
System.out.println(resc.conRes.getErrorText());
System.out.println(resc.conRes.conList.getErrorText());
for (Con con : resc.conRes.conList.cons) {
System.out.println(con.getErrorText());
}
System.out.println(" == Finished printing out all of the error text. == ");
}
}
It just runs simple and displays the results.
The BaseObject.java class:
package com.massaiolir.simple.iface;
import org.simpleframework.xml.Element;
public class BaseObject implements Error {
#Element(name = "Err", required = false, type = ConcreteError.class)
private Error err;
#Override
public String getErrorText() {
return err.getErrorText();
}
#Override
public void setErrorText(String errorText) {
err.setErrorText(errorText);
}
}
This is the class that everything should extend if it wants 'Err'.
The Error interface:
package com.massaiolir.simple.iface;
public interface Error {
void setErrorText(String errorText);
String getErrorText();
}
The ConcreteError class:
package com.massaiolir.simple.iface;
import org.simpleframework.xml.Attribute;
public class ConcreteError implements Error {
#Attribute
private String text;
#Override
public String getErrorText() {
return text;
}
#Override
public void setErrorText(String errorText) {
this.text = errorText;
}
}
The actual implementing classes are after this point. You will see that they are rather trivial because the real work is being handled in the classes above.
The Con class:
package com.massaiolir.simple.iface;
public class Con extends BaseObject {
}
The ConList class:
package com.massaiolir.simple.iface;
import java.util.ArrayList;
import org.simpleframework.xml.ElementList;
public class ConList extends BaseObject {
#ElementList(entry = "Con", inline = true)
public ArrayList<Con> cons;
}
The ConRes class:
package com.massaiolir.simple.iface;
import org.simpleframework.xml.Element;
public class ConRes extends BaseObject {
#Element(name = "ConList")
public ConList conList;
}
The ResC class:
package com.massaiolir.simple.iface;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
#Root
public class ResC extends BaseObject {
#Element(name = "ConRes")
public ConRes conRes;
}
And that is all that there is to it. Pretty simple right. I was able to bang that all out in ten minutes. It actually took me longer to write this response than it took me to write the code that I am giving you. If you do not understand anything about the code that I have just written then please let me know. I hope this helps you to understand how you might go about doing something like this.
Related
I've tried to modify minecraft by adding a new item called "uranium". Therefore I created the class "Trauma.java" in the main package and a few other classes listed below.
All packages and classes:
Package Explorer
Trauma.java
package main;
import items.ItemUranium;
import net.minecraft.item.Item;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.registry.GameRegistry;
import proxy.ServerProxy;
#Mod(modid = Trauma.MODID)
public class Trauma {
public static final String MODID = "Trauma";
#SidedProxy(clientSide = "proxy.ClientProxy", serverSide = "proxy.ServerProxy")
public static ServerProxy proxy;
public static ItemUranium uranium = new ItemUranium();
#EventHandler
public void preInit(FMLPreInitializationEvent event) {
GameRegistry.register(uranium);
}
#EventHandler
public void init(FMLInitializationEvent event) {
proxy.registerClientStuff();
}
#EventHandler
public void postInit(FMLPostInitializationEvent event) {
}
}
BasicItem.java
package items;
import net.minecraft.item.Item;
public class BasicItem extends Item {
public BasicItem(String name) {
setUnlocalizedName(name);
setRegistryName(name);
}
}
ItemUranium.java
package items;
public class ItemUranium extends BasicItem {
public ItemUranium() {
super("uranium");
}
}
ClientProxy.java
package proxy;
import items.BasicItem;
import main.Trauma;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
public class ClientProxy extends ServerProxy {
#Override
public void registerClientStuff () {
registerItemModel(Trauma.uranium);
}
public static void registerItemModel(BasicItem item) {
Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(item, 0, new ModelResourceLocation(Trauma.MODID + ":" + item.getRegistryName(), "inventory"));
}
}
ServerProxy.java
package proxy;
public class ServerProxy {
public void registerClientStuff() {}
}
uranium.json
{
"parent": "item/generated",
"textures": {
"layer0": "Trauma:items/uranium"
}
}
uranium.png
ingame
Also I don't know why the item in inventory isn't called uranium...
I spent two hours on fixing the problem and it didn't help so it would be really nice if somebody of you may help me.
Thanks :)
Don't use the Model Mesher:
The model mesher is Vanilla (Mojang) code and using it correctly has always been finicky and unreliable, failing if you called it too early and failing if you called it too late. So Forge added the ModelLoader class to resolve that problem.
Replace this line:
Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(...)
With this line:
ModelLoader.setCustomModelResourceLocation(...)
The ... contents are identical.
Second, depending on what version of Minecraft you're using, you should...:
Stop using GameRegistry.Register
Instead use the RegistryEvent.Register<T> events (where <T> will be <Block> to register blocks, <Item> to register items, etc)
Register your models in the ModelRegistryEvent and no where else.
This event is #SideOnly(CLIENT) and can be subscribed to in your client proxy, avoiding the need to forward references through your proxy class. Eg. I do it like this, where lines 197-199 is the most common scenario needed, where the array is populated during the item registration event. The rest of that method handles the custom state mappers and custom mesh definitions that are used by only a handful of items/blocks and not relevant here.
Include your Mod ID in your unlocalized name. The best way to do this would be setUnlocalizedName(getRegistryName().toString());
See also the Forge documentation on events.
I want to build a custom renderer for some of my grids columns to hide the text if the user doesn't have the right to read it. It's still important that the data is accessible even if the user is not able to read it.
So I wrote a custom renderer which looks like this:
package <package>.util.renderer;
import com.vaadin.client.renderers.Renderer;
import com.vaadin.client.widget.grid.RendererCellReference;
import <package>.util.CustomSecurityConstants;
import <package>.BaseUI;
public class BlockedStringRendererClient implements Renderer<String> {
private boolean canReadBlocked = BaseUI.getCurrentPrincipal().get().getAuthorities().contains(CustomSecurityConstants.READ_PERMISSION_BLOCKED);
#Override
public void render(RendererCellReference rendererCellReference, String s) {
if (canReadBlocked) {
rendererCellReference.getElement().setInnerText(s);
} else {
rendererCellReference.getElement().setInnerText("");
}
}
}
Then I wrote the server side of the renderer, following this tutorial https://vaadin.com/docs/-/part/framework/clientsidewidgets/clientsidewidgets-grid.html
package <package>.util.renderer;
import com.vaadin.ui.Grid;
public class BlockedStringRendererServer extends Grid.AbstractRenderer<String> {
public BlockedStringRendererServer() {
super(String.class);
}
}
And finally the connector to connect these components:
package <package>.util.renderer;
import com.vaadin.client.connectors.AbstractRendererConnector;
import com.vaadin.shared.ui.Connect;
#Connect(BlockedStringRendererServer.class)
public class BlockedStringRendererConnector extends AbstractRendererConnector<String> {
#Override
public BlockedStringRendererClient getRenderer() {
return (BlockedStringRendererClient) super.getRenderer();
}
}
But now when I try to use the connector like follows:
grunddatenGrid.getColumn("name").setRenderer(new BlockedStringRendererServer());
The grid doesn't show any columns that contains strings anymore.
I really don't know what I'm doing wrong but I think it might has to do with the Connector-Annotation not working as expected because when I try to debug the client side logic it doesn't even get called.
Can somebody point me to what steps I'm missing?
Kind regards,
Fabian
I am trying to add a texture to an item, yet the texture just doesn't appear. I have the texture made, and in the right file directory, but while in game it doesn't display. Thus, I think it's an error in my code.
For the whole class file, see below:
package Moonstone;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.common.util.EnumHelper;
#Mod(modid = "ms", name = "Moonstone", version = "1.0")
public class MoonstoneMain {
public static Item moonstone;
#EventHandler
public void preInit(FMLPreInitializationEvent event) {
//All init
moonstone = new Moonstone().setUnlocalizedName("Moonstone").setTextureName("moonstone").setMaxStac kSize(64);
GameRegistry.registerItem(moonstone, moonstone.getUnlocalizedName().substring(5));
}
#EventHandler
public void init(FMLInitializationEvent event) {
//Proxy, TileEntity, entity, GUI and packet registering
}
#EventHandler
public void postInit(FMLPostInitializationEvent event) {
}
public static CreativeTabs tabMoonstone = new CreativeTabs("tabMoonstone"){
#Override
public Item getTabIconItem(){
return new ItemStack(Items.stick).getItem();
}
};
}
For just the item, look below-
moonstone = new Moonstone().setUnlocalizedName("Moonstone").setTextureName("moonstone").setMaxStackSize(64);// I have tried with ms:moonstone and without, both don't work.
GameRegistry.registerItem(moonstone, moonstone.getUnlocalizedName().substring(5));
Recommended changes but not necessary:
First:
When registering the item you should remove the .substring(5),
having this in will name the item "Moons" instead of "Moonstone".
Second:
unlocalized names should always be lowercase and should be formatted
as modid_itemname
Third:
Package names should be lowercase, package moonstone
Fourth:
Your should make a Refstrings.java file and put the modid, version and name in it
package Moonstone
public RefStrings{
public static String NAME = "Moonstone";
public static String MODID = "ms";
public static String VERSION = "1.0";
}
Necessary changes:
Your setTextureName should be passed "ms:moonstone"
You didn't post your folder structure but it should look like this:
src/main/java/Moonstone/MoonstoneMain.java
src/main/resources/assests/ms/textures/items/moonstone.png
it is possible that some of the recommend changes will be what fixes the problem, minecraft can be a bit finicky with naming.
I already made MontiCore generate the PrettyPrinter classes with the options explained in Configure pom.xml to generate PrettyPrinters for MontiCore Languages.
How can I generate the formatted text output of my MontiArcAutomaton (Type: ASTEmbeddedAutomaton) ?
After asking the MontiCore team, the following solution turned out be a good approach:
I wrote a helper class for pretty printing the embedded automaton ASTNode (see Listing 1).
This helper class can be used e.g. with the following code line:
System.out.println(PrettyPrintFactory.getInstance().printNode(autMoore));
Listing 1:
import mc.ast.ASTCNode;
import mc.ast.PrettyPrinter;
import mc.helper.IndentPrinter;
import mc.maautomaton._prettyprint.MontiArcAutomatonConcretePrettyPrinter;
/**
* Prints the AST-Content to a file
**/
public class PrettyPrintFactory {
private static PrettyPrintFactory instance;
private PrettyPrinter pretty;
public static PrettyPrintFactory getInstance() {
if (instance == null) {
instance = new PrettyPrintFactory();
}
return instance;
}
private PrettyPrintFactory() {
pretty = new PrettyPrinter();
pretty.addConcretePrettyPrinter(new MontiArcAutomatonConcretePrettyPrinter());
}
/** prints the syntax of the astNode to a String */
public String printNode(ASTCNode astNode) {
IndentPrinter ip = new IndentPrinter();
pretty.prettyPrint(astNode, ip);
return ip.getContent();
}
}
I create a form with Play framework. but I get a error: cannot find symbol
I reviewed the example codes in play directory, still can not figure it out. by the way, can I use Play to access PostgresSQL in heroku?
This is following code:
This is piece of code in /controllers/Application.java
final static Form<Geo> geoForm = form(Geo.class);
public static Result showDBpage(){
//get problem here :-<
Form<Geo> filledForm = geoForm.bindFormRequest();
Geo loc = filledForm.get();
return ok(database.render(loc));
}
This is conf/routes:
POST /database controllers.Application.showDBpage()
views/database.scala.html
#(loc: Geo)
#main("") {
<p>This is Database pages</p>
<p>#loc.longitute and #loc.latitute</p>
<a href=#routes.Application.index>Back to form</a>
}
models/Geo.java:
package models;
import java.util.*;
import javax.validation.*;
import play.data.validation.Constraints.*;
public class Geo
{
#Required
public String longitute;
#Required
public String latitute;
public Geo()
{
}
public Geo(String longitude,String latitute)
{
this.longitute = longitute;
this.latitute = latitute;
//this.length = length;
}
}
There is NO method bindFormRequest() but bindFromRequest() - you have a typo in your code.
Check the API http://www.playframework.org/documentation/api/2.0.2/java/play/data/Form.html