connecting vertices in jung by edges results in another extra vertex being created - jung

I am implementing an interface for taking commands for creating , connecting and coloring vertices in JUNG when I want to connect two already existing vertices JUNG connects to vertices and creates an extra vertex , why?
Here is my code for connect method:
public class Connect extends Command {
private CommandMaster cm;
private BehGraphUndirected behGraph;
private static int edgenumber=0;
#Override
public Object run(BehGraphUndirected behGraph, VisualizationImageServer panel, InterpretMaster interpretMaster, String... args) {
System.out.print("connect Runs\n");
this.cm = new CommandMaster();
this.behGraph = behGraph;
if(cm.exists(args[0]))
{
//got to another command
}else
{
switch (args[0]) {
case "edge":
this.createEdge(args[1] , args[2]);
break;
}
}
interpretMaster.refreshAndRepaint();
return null;
}
public void createEdge(String nodeName1 , String nodeName2)
{
this.behGraph.addEdge(edgenumber++,nodeName1, nodeName2);
System.out.println(this.behGraph.getVertexCount());
System.out.println("edge between: "+nodeName1+" and "+ nodeName2+" added");
}
And it's the create method just in case you want to know the way I implemented the code:
package interpreter.command;
import GraphHandling.BehGraphUndirected;
import edu.uci.ics.jung.visualization.VisualizationImageServer;
import interpreter.Command;
import interpreter.CommandMaster;
import interpreter.InterpretMaster;
/**
*
* #author Administrator
*/
public class Create extends Command{
private CommandMaster cm;
private BehGraphUndirected behGraph;
#Override
public Object run(BehGraphUndirected behGraph, VisualizationImageServer panel, InterpretMaster interpretMaster, String... args) {
System.out.print("create Runs \n");
this.cm = new CommandMaster();
this.behGraph = behGraph;
if(cm.exists(args[0]))
{
//got to another command
}else
{
switch (args[0]) {
case "node":
this.createNode(args[1]);
break;
case "label":
this.createLabel(args[1]);
break;
}
}
interpretMaster.refreshAndRepaint();
return null;
}
public void createNode(String nodeName)
{
this.behGraph.addVertex(nodeName);
System.out.print("vertex: "+nodeName+" added");
}
private void createLabel(String string) {
}
class str
{
int i;
long j;
}
}
Graph images before and after connecting two nodes:
and Here is my BehGraphUndirected class:
package GraphHandling;
import edu.uci.ics.jung.graph.UndirectedSparseGraph;
import java.util.LinkedList;
/**
*
* #author Administrator
*/
public class BehGraphUndirected extends UndirectedSparseGraph{
private final LinkedList<Node> nodeList;
public BehGraphUndirected()
{
this.nodeList = new LinkedList<>();
}
public void addNode(Node newNode)
{
this.nodeList.add(newNode);
}
}

You should look at what BehGraphUndirected is doing; it's not a JUNG class or interface.
What is the name of the vertex that's being created, and how does that relate to what's being passed to the create method?

I have compiled and tested your code , The Jung library seems working right and It extinguishes the different nodes by the different object that was given to it It seems you have some other problem , Like a problem in processing the input strings that are used as objects that create nodes.

Related

jface tableviewer tooltip text cut

I am using the jface tableviewer in an eclipse rcp application to display some values.
Therefore I have written the following snipped ...
tableviewer = new TableViewer(container, SWT.FULL_SELECTION | SWT.BORDER | SWT.SINGLE);
tableviewer.setContentProvider(new ArrayContentProvider());
ColumnViewerToolTipSupport.enableFor(tableviewer, ToolTip.RECREATE);
final Table table = tableviewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(true);
TableViewerColumn column = new TableViewerColumn(tableviewer, SWT.NONE);
column.getColumn().setText("col1");
column.getColumn().setResizable(true);
column.setLabelProvider(new ConfigLabelProvider("col1"));
And here here ConfigLabelProvider definition
private class ConfigLabelProvider extends StyledCellLabelProvider {
private String property;
public ConfigLabelProvider(String property) {
this.property = property;
}
#Override
public void update(ViewerCell cell) {
GenericConfigInterfaceEntity config = (GenericConfigInterfaceEntity) cell.getElement();
switch (property) {
case "col1":
cell.setText(AppHelper.preventNull("col1Text col1Text col1Text col1Text col1Text"));
break;
case ...
}
super.update(cell);
}
}
Now my problem is if the column is too small, the default tooltip is displayed trying to show the full cell text value.
BUT I get a tooltip box that is large enough for the whole text but the text isn't shown outside the cell rectange.
If I extend the ConfigLabelProvider from CellLabelProvider the Tooltip is showing up like expected ...
But I need the paint method of the StyledCellLabelProvider.
Any ideas?
Edit 1
I have written a small Java Example Project using SWT and JFACE, because my problems still remain.
My goal is to have an table with a cell-Background without the mousehover (because its looking ugly together) and a custom tooltip.
Here's my TestTable implementation
package main;
import java.util.ArrayList;
import java.util.List;
import model.TestModel;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
public class TestTable extends Dialog {
private TableViewer tableviewer;
private List<TestModel> entities;
protected TestTable(Shell parentShell) {
super(parentShell);
}
#Override
public void create() {
super.create();
loadData();
}
#Override
protected Control createDialogArea(Composite parent) {
GridData dataLayout;
Composite area = (Composite) super.createDialogArea(parent);
dataLayout = new GridData(GridData.FILL_BOTH);
dataLayout.heightHint = 150;
dataLayout.widthHint = 500;
Composite wrapper = new Composite(area, SWT.NONE);
wrapper.setLayoutData(dataLayout);
wrapper.setLayout(new FillLayout());
tableviewer = new TableViewer(wrapper, SWT.BORDER | SWT.MULTI);
tableviewer.setContentProvider(new ArrayContentProvider());
ColumnViewerToolTipSupport.enableFor(tableviewer);
final Table table = tableviewer.getTable();
table.setLinesVisible(true);
table.setHeaderVisible(true);
createColumns(wrapper);
return area;
}
private void createColumns(Composite wrapper) {
TableViewerColumn firstnameColumn = new TableViewerColumn(tableviewer, SWT.NONE);
firstnameColumn.getColumn().setText("Vorname");
firstnameColumn.setLabelProvider(new StyledCellLabelProvider(StyledCellLabelProvider.COLORS_ON_SELECTION) {
#Override
public void initialize(ColumnViewer viewer, ViewerColumn column) {
super.initialize(viewer, column);
this.setOwnerDrawEnabled(false);
}
#Override
public void update(ViewerCell cell) {
TestModel model = (TestModel) cell.getElement();
cell.setText(model.getFirstname());
cell.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_DARK_GREEN));
}
#Override
public String getToolTipText(Object element) {
TestModel model = (TestModel) element;
return "USE THIS AS TOOLTIP";
}
});
TableViewerColumn lastnameColumn = new TableViewerColumn(tableviewer, SWT.NONE);
lastnameColumn.getColumn().setText("Nachname");
lastnameColumn.setLabelProvider(new StyledCellLabelProvider(StyledCellLabelProvider.COLORS_ON_SELECTION) {
#Override
public void initialize(ColumnViewer viewer, ViewerColumn column) {
super.initialize(viewer, column);
this.setOwnerDrawEnabled(false);
}
#Override
public void update(ViewerCell cell) {
TestModel model = (TestModel) cell.getElement();
cell.setText(model.getLastname());
cell.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_DARK_GREEN));
}
#Override
public String getToolTipText(Object element) {
TestModel model = (TestModel) element;
return "USE THIS AS TOOLTIP";
}
});
for (TableColumn c : tableviewer.getTable().getColumns()) {
c.pack();
}
}
private void loadData() {
entities = new ArrayList<TestModel>();
entities.add(new TestModel("___Firstname1___", "Lastname1", "Username1", "Kommentar"));
entities.add(new TestModel("___Firstname2___", "Lastname2", "Username2", "Kommentar"));
entities.add(new TestModel("___Firstname3___", "Lastname3", "Username3", "Kommentar"));
entities.add(new TestModel("___Firstname4___", "Lastname4", "Username4", "Kommentar"));
entities.add(new TestModel("___Firstname5___", "Lastname5", "Username5", "Kommentar"));
tableviewer.setInput(entities);
tableviewer.refresh();
}
}
And here are some faulty pictures
Here the native TableViewer Tooltip and my custom ToolTip is shown, also the row gets selected (COLORS_ON_SELECTION should prevent that)
Here no tooltip is shown on the second column
And here no tooltip is shown and as you can see the first cell isn't filled up
If I add SWT.FULL_SELECTION the tooltip on column 2 appears but the other issues remain.
I think it's a kind of buggy that Tooltip Support or I am doing it totally wrong.
This solved my problem
https://stackoverflow.com/a/28991593/1822033
The underlaying second tip was shown because the column was too narrow. Setting tableviewer.getTavle().setTooltipText(""); stopped showing the native tip.
Setting it to null displays it anyway!

Converting a Foo into a Foo.ByValue?

I am integrating with an aged lm_sensors library using JNA and JNAerator, with a view to creating MBeans for each of the temperature sensors inside my box. Firstly I'm calling this method:
// C edition
const sensors_chip_name *sensors_get_detected_chips(int *nr);
// Java edition
sensors_chip_name sensors_get_detected_chips(IntByReference nr);
.. which works just fine. Subsequently I need to call:
// C edition
int sensors_get_feature(sensors_chip_name name, int feature, double *result);
// Java edition
int sensors_get_feature(sensors_chip_name.ByValue name, int feature, DoubleByReference result);
.. what I am lacking is how to take the result of sensors_get_detected_chips and pass it by value to the 1st argument of sensors_get_feature.
The following allows a ByValue version of the struct to be initialized from the base class.
public class sensors_chip_name extends Structure {
public class ByValue extends sensors_chip_name implements Structure.ByValue {
public ByValue(sensors_chip_name orig) {
this(orig.getPointer().share());
}
public ByValue(Pointer p) {
super(p);
}
public ByValue() { }
}
public sensors_chip_name() { }
public sensors_chip_name(Pointer p) {
super(p);
read();
}
}

Chaining InputOperations in Rhino-Etl

I've just recently started using Rhino-Etl for very simple ETL processes and have had great success with it. I have a slightly more complicated scenario to address now and I didn't find the ConventionInputCommandOperation behaving the way I expected.
I've done up a very simplified example of what I'm trying to do. Basically I have two systems involved and I don't know what I want to get from system 2 until I first query system 1. I thought registering an InputOperation immediately after another InputOperation would behave like a loop. So that each row in operation 1 would be fed to operation 2. The below code fails with "Failed to execute operation DetailReader: Must declare the scalar variable #PlanetAbbrv." So my question is how are you meant to handle situations where the input operation is dependent a previous input operation?
Thanks,
Brian
using System;
using Rhino.Etl.Core;
using Rhino.Etl.Core.ConventionOperations;
namespace ETLTest
{
class Program
{
static void Main()
{
new MainProcess().Execute();
Console.ReadLine();
}
}
public class MainProcess : EtlProcess
{
protected override void Initialize()
{
Register(new MainReader());
Register(new DetailReader());
}
protected override void PostProcessing()
{
foreach (var exception in GetAllErrors())
{
throw exception;
}
}
}
public class MainReader : ConventionInputCommandOperation
{
public MainReader() : base("Galactic1")
{
Command = #"select * from Planet";
}
}
public class DetailReader : ConventionInputCommandOperation
{
public DetailReader() : base("Galactic2")
{
Command = #"select * from Delivery where DeliveryPlanetAbbrv = #PlanetAbbrv";
}
}
}
You'll need to have your DetailReader select all rows (take out the where operation).
Then use a JoinOperation to match the details to the main information.
Register(new JoinPlanets()
.Right(new MainReader())
.Left(new DetailReader()));
public class JoinPlanets: JoinOperation
{
protected override Row MergeRows(Row leftRow, Row rightRow)
{
Row row = leftRow.Clone();
foreach (var column in leftRow.Columns)
row[column] = leftRow[column];
return row;
}
protected override void SetupJoinConditions()
{
FullOuterJoin.Left("PlanetAbbrv")
.Right("DeliveryPlanetAbbrv");
}
}

How to run another instance of Main() in AS3

How would you run a new instance of your Main function in AS3? Basically I want the program to rerun itself from the start, once it reaches the end of the program. I thought about removing all my childs from the tree at the end, then running the first method again, but that just seems unnecessary and messy. The class extends Sprite.
EDIT: Trying to create a Custom Event and using dispatchEvent to trigger this at the end of the program but having a little problem. This is my current code below.
Entire RunMain.as:
package
{
import flash.display.Sprite;
import flash.events.Event;
public class RunMain extends Sprite {
public function RunMain():void {
addEventListener(Event.ENTER_FRAME, loop);
}
private function loop(event:Event){
removeEventListener(Event.ENTER_FRAME, loop);
dispatchEvent(new EndEvent(EndEvent.END_EVENT));
}
}
}
Entire EndEvent.as:
package
{
import flash.events.Event;
public class EndEvent extends Event
{
// Event types.
public static const END_EVENT:String = "event1";
public function EndEvent(type:String = EndEvent.END_EVENT)
{
super(type);
}
override public function clone():Event {
// Return a new instance of this event with the same parameters.
return new EndEvent(type);
}
}
}
Parts of Main.as:
public function Main() {
runMain = new RunMain();
runMain.addEventListener(EndEvent.END_EVENT, onProgramFinish);
addChild(runMain);
init();
otherMethods();
}
public function onProgramFinish() {
removeChild(runMain);
runMain = null;
runMain = new RunMain() ;
}
Inside my Main class, I have the line onProgramFinish(); at the end of the program.
At the moment, when I run the compiler it comes up with the error:
ArgumentError: Error #1063: Argument count mismatch on Main/onProgramFinish().
Expected 0, got 1.
When I choose to continue, the program runs fine, but it doesn't run a new instance at the end of it.
In fact you must create a special class container and swap him (create new or delete) exactly in main class. This game class can dispatch events, at least sprites can dispatch events. Creating your custom events and passing them to higher and higher level will allow you to perform actions in Main class.
class Main extends Sprite {
public var game:Game ;
public function Main():void {
game = new Game(new Player(), "asd") ;
game.addEventListener(GameEvent.GAME_OVER, onGameOver) ;
addChild(game) ;
}
public function onGameOver(){
removeChild(game) ;
//also you can try removing heavy children of game
game = null ; //Let garbage collector know about object without reference.
game = new Game(new Player(), "example") ;
}
}
public class Game extends Sprite {
public var hero:Hero = new Hero() ;
public function Game(player:Player, name:String):void {
addEventListener(Event.ENTER_FRAME, loop) ;
}
private function loop(event:Event){
if (hero.hp == 0){
removeEventListener(Event.ENTER_FRAME, loop) ;
dispatchEvent(new GameEvent(GameEvent.GAME_OVER)) ;
}
}
}
Your event:
package {
import flash.events.Event;
public class ProgramEvent extends Event
{
public static const FINISH:String = "Finished" ;
public function ProgramEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
public override function clone():Event
{
return new ProgramEvent(type, bubbles, cancelable);
}
public override function toString():String
{
return formatToString("ProgramEvent", "type", "bubbles", "cancelable", "eventPhase");
}
}
}
RunMain:
package
{
import flash.display.Sprite;
import flash.events.Event;
public class RunMain extends Sprite {
public function RunMain():void {
addEventListener(Event.ENTER_FRAME, loop);
}
private function loop(event:Event){
removeEventListener(Event.ENTER_FRAME, loop);
dispatchEvent(new ProgramEvent(ProgramEvent.FINISH));
}
}
}
And Main:
public function Main() {
startProgram() ;
init();
otherMethods();
}
public function onProgramFinish(event:ProgramEvent) {
runMain.removeEventListener(ProgramEvent.FINISH, onProgramFinish) ;
removeChild(runMain);
runMain = null;
startProgram() ;
}
public function startProgram(){
runMain = new RunMain() ;
runMain.addEventListener(ProgramEvent.FINISH, onProgramFinish);
addChild(runMain);
}

How to sort the choices in a Wicket dropdown according to the current user locale?

I have the following issue:
a drop down with a list of elements
each of these elements has a fixed key, which is used by the IChoiceRenderer implementation to look up the localized version of the key (it's a standard, utility renderer implemented in a different package)
the list of localized keys is in a properties file, linked to the panel which instantiates the dropdown.
Is there an elegant/reusable solution to have the dropdown display its elements sorted alphabetically ?
In the end, I think using the render is probably the best approach. To make it reusable and efficient, I isolated this in a Behavior.
Here's the code:
import org.apache.wicket.Component;
import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.markup.html.form.AbstractChoice;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import static java.util.Arrays.sort;
/**
* This {#link Behavior} can only be used on {#link AbstractChoice} subclasses. It will sort the choices
* according to their "natural display order" (i.e. the natural order of the display values of the choices).
* This assumes that the display value implements {#link Comparable}. If this is not the case, you should
* provide a comparator for the display value. An instance of this class <em>cannot be shared</em> between components.
* Because the rendering can be costly, the sort-computation is done only once, by default,
* unless you set to <code>false</code> the <code>sortOnlyOnce</code> argument in the constructor.
*
* #author donckels (created on 2012-06-07)
*/
#SuppressWarnings({"unchecked"})
public class OrderedChoiceBehavior extends Behavior {
// ----- instance fields -----
private Comparator displayValueComparator;
private boolean sortOnlyOnce = true;
private boolean sorted;
// ----- constructors -----
public OrderedChoiceBehavior() {
}
public OrderedChoiceBehavior(boolean sortOnlyOnce) {
this.sortOnlyOnce = sortOnlyOnce;
}
public OrderedChoiceBehavior(boolean sortOnlyOnce, Comparator displayValueComparator) {
this.sortOnlyOnce = sortOnlyOnce;
this.displayValueComparator = displayValueComparator;
}
// ----- public methods -----
#Override
public void beforeRender(Component component) {
if (this.sorted && this.sortOnlyOnce) { return;}
AbstractChoice owner = (AbstractChoice) component;
IChoiceRenderer choiceRenderer = owner.getChoiceRenderer();
List choices = owner.getChoices();
// Temporary data structure: store the actual rendered value with its initial index
Object[][] displayValuesWithIndex = new Object[choices.size()][2];
for (int i = 0, valuesSize = choices.size(); i < valuesSize; i++) {
Object value = choices.get(i);
displayValuesWithIndex[i][0] = choiceRenderer.getDisplayValue(value);
displayValuesWithIndex[i][1] = i;
}
sort(displayValuesWithIndex, new DisplayValueWithIndexComparator());
List valuesCopy = new ArrayList(choices);
for (int i = 0, length = displayValuesWithIndex.length; i < length; i++) {
Object[] displayValueWithIndex = displayValuesWithIndex[i];
int originalIndex = (Integer) displayValueWithIndex[1];
choices.set(i, valuesCopy.get(originalIndex));
}
this.sorted = true;
}
public Comparator getDisplayValueComparator() {
return this.displayValueComparator;
}
// ----- inner classes -----
private class DisplayValueWithIndexComparator implements Comparator<Object[]> {
// ----- Comparator -----
public int compare(Object[] left, Object[] right) {
Object leftDisplayValue = left[0];
Object rightDisplayValue = right[0];
if (null == leftDisplayValue) { return -1;}
if (null == rightDisplayValue) { return 1;}
if (null == getDisplayValueComparator()) {
return ((Comparable) leftDisplayValue).compareTo(rightDisplayValue);
} else {
return getDisplayValueComparator().compare(leftDisplayValue, rightDisplayValue);
}
}
}
}
Use this extension of DropDownChoice using Java's Collator (basically locale sensitive sorting - take national characters and national sorting rules into account)
Code tested with Wicket 6 and Java 5+:
import java.text.Collator;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import org.apache.wicket.Session;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.model.IModel;
import com.google.common.collect.Ordering;
/**
* DropDownChoice which sort its choices (or in HTML's terminology select's options) according it's localized value
* and using current locale based Collator so it's sorted how it should be in particular language (ie. including national characters,
* using right order).
*
* #author Michal Bernhard michal#bernhard.cz 2013
*
* #param <T>
*/
public class OrderedDropDownChoice<T> extends DropDownChoice<T> {
public OrderedDropDownChoice(String id, IModel<? extends List<? extends T>> choices, IChoiceRenderer<? super T> renderer) {
super(id, choices, renderer);
}
public OrderedDropDownChoice(String id, IModel<? extends List<? extends T>> choices) {
super(id, choices);
}
public OrderedDropDownChoice(String id) {
super(id);
}
public OrderedDropDownChoice(
String id,
IModel<T> model,
IModel<? extends List<? extends T>> choices,
IChoiceRenderer<? super T> renderer) {
super(id, model, choices, renderer);
}
#Override
public List<? extends T> getChoices() {
List<? extends T> unsortedChoices = super.getChoices();
List<? extends T> sortedChoices = Ordering.from(displayValueAlphabeticComparator()).sortedCopy(unsortedChoices);
return sortedChoices;
}
private Collator localeBasedTertiaryCollator() {
Locale currentLocale = Session.get().getLocale();
Collator collator = Collator.getInstance(currentLocale);
collator.setStrength(Collator.TERTIARY);
return collator;
}
private Comparator<T> displayValueAlphabeticComparator() {
final IChoiceRenderer<? super T> renderer = getChoiceRenderer();
return new Comparator<T>() {
#Override
public int compare(T o1, T o2) {
Object o1DisplayValue = renderer.getDisplayValue(o1);
Object o2DisplayValue = renderer.getDisplayValue(o2);
return localeBasedTertiaryCollator().compare(o1DisplayValue, o2DisplayValue);
}
};
}
}
Copied from https://gist.github.com/michalbcz/7236242
If you want a Wicket-based solution you can try to sort the list with something like that:
public class ChoiceRendererComparator<T> implements Comparator<T> {
private final IChoiceRenderer<T> renderer;
public ChoiceRendererComparator(IChoiceRenderer<T> renderer) {
this.renderer = renderer;
}
#SuppressWarnings("unchecked")
public int compare(T o1, T o2) {
return ((Comparable<Object>) renderer.getDisplayValue(o1)).compareTo(renderer.getDisplayValue(o2));
}
}
Usage:
List<Entity> list = ...
IChoiceRenderer<Entity> renderer = ...
Collections.sort(list, new ChoiceRendererComparator<Entity>(renderer));
DropDownChoice<Entity> dropdown = new DropDownChoice<Entity>("dropdown", list, renderer);
The solution we use at my company is Javascript based, we set a special css class on the dropdowns we want to be sorted, and a little jQuery trick does the sort.
Facing the same problem, I moved part of the localisation data from my XMLs to the database, implemented a matching Resolver and was able to use the localized Strings for sorting.
The table design and hibernate configuration was kind of tricky and is described here: Hibernate #ElementCollection - Better solution needed.
The ResourceLoader is along these lines:
public class DataBaseStringResourceLoader extends ComponentStringResourceLoader {
private static final transient Logger logger = Logger
.getLogger(DataBaseStringResourceLoader.class);
#Inject
private ISomeDAO someDao;
#Inject
private IOtherDao otherDao;
#Inject
private IThisDAO thisDao;
#Inject
private IThatDAO thatDao;
#Override
public String loadStringResource(Class<?> clazz, String key, Locale locale,
String style, String variation) {
String resource = loadFromDB(key, new Locale(locale.getLanguage()));
if (resource == null) {
resource = super.loadStringResource(clazz, key, locale, style, variation);
}
return resource;
}
private String loadFromDB(String key, Locale locale) {
String resource = null;
if (locale.getLanguage() != Locale.GERMAN.getLanguage()
&& locale.getLanguage() != Locale.ENGLISH.getLanguage()) {
locale = Locale.ENGLISH;
}
if (key.startsWith("some") || key.startsWith("other")
|| key.startsWith("this") || key.startsWith("that")) {
Integer id = Integer.valueOf(key.substring(key.indexOf(".") + 1));
ILocalizedObject master;
if (key.startsWith("some")) {
master = someDao.findById(id);
} else if (key.startsWith("other")) {
master = otherDao.findById(id);
} else if (key.startsWith("this") ){
master = thisDao.findById(id);
} else {
master = thatDao.findById(id);
}
if (master != null && master.getNames().get(locale) != null) {
resource = master.getNames().get(locale).getName();
} else if (master == null) {
logger.debug("For key " + key + " there is no master.");
}
}
return resource;
}
[...]
}

Resources