all things jMDA
news from and stuff about jMDA - a new lightweight approach to model driven architecture based on Java technology
Welcome to jMDA
To generate software automatically has been a strong ambition since the early days of software development.
jMDA is a new approach in this area. It streamlines proven, widely known and accepted open source technologies into a most comprehensible and easy to use set of Java libraries that are extremely powerful and flexible at the same time. The main purpose of jMDA is
to leverage a comprehensible and easy to use modelling environment,
to provide convenient and complete access to modelling information and
to make available easy to use software generator facilities.
The introduction will briefly explain the main drivers behind this project, the jMDA book provides more detailed information about the most important concepts and the open source software is available here.
Sunday 10 June 2018
javafx - combobox with autocompletion for custom types
I'd like to share a solution for a javafx combobox with autocompletion for custom types. First of all I will show how to use it. Here is an example for a simple custom type that I will use for this example:
private class Data implements Comparable<Data>
{
private String string;
private Data(String string) { this.string = string; }
@Override public int compareTo(Data o) { return string.compareTo(o.string); }
@Override public String toString() { return string; }
}
Next here comes an example for using autocompletion for the above custom type with the combobox:
// create combo box (for custom type Data) as usual
ComboBox<Data> cmbBx = new ComboBox<>();
// cell factory that provides a list cell for a given Data item (see updateItem)
Callback<ListView<Data>, ListCell<Data>> cellFactory =
new Callback<ListView<Data>, ListCell<Data>>()
{
@Override public ListCell<Data> call(ListView<Data> lv)
{
return new ListCell<Data>()
{
@Override protected void updateItem(Data item, boolean empty)
{
super.updateItem(item, empty);
if (item == null || empty) { setGraphic(null); }
else { setText(item.string); }
}
};
}
};
// converter that converts a given Data item to String and vice versa
StringConverter<Data> converter =
new StringConverter<Data>()
{
@Override public String toString(Data item)
{
if (item == null) return null;
return item.string;
}
@Override public Data fromString(String string)
{
for (Data item : cmbBx.getItems())
{
if (item.string.equals(string)) return item;
}
return null;
}
};
// use the cell factory method to provide content for the button cell
cmbBx.setButtonCell(cellFactory.call(null));
// let the cell factory deliver the content of the cells
cmbBx.setCellFactory(cellFactory);
// set a condition that lets a Data item appear in the list of the auto complete suggestions or not
Predicate<Data> predicate =
data ->
{
String cmbBxEditorTextToLowerCase = cmbBx.getEditor().getText().toLowerCase();
String dataStringToLowerCase = data.string.toLowerCase();
boolean result = dataStringToLowerCase.contains(cmbBxEditorTextToLowerCase);
return result;
};
cmbBx.setConverter(converter);
// sample data
ObservableList<Data> items = FXCollections.observableArrayList();
items.add(new Data("apple1"));
items.add(new Data("apple2"));
items.add(new Data("apple3"));
items.add(new Data("ball1"));
items.add(new Data("ball2"));
items.add(new Data("ball3"));
items.add(new Data("cat1"));
items.add(new Data("cat2"));
items.add(new Data("cat3"));
cmbBx.setItems(items);
The above preparations is pretty much conventional stuff that users of combo boxes have to deal with anyway in javafx.
However there is the predicate that should be mentioned here because it allows for "filtering" items of the combobox depending on the user input in the combo box editor. For the sample data above this means, that if the editor content is "a" all items are contained in the list of suggestions and if it is "t" then only the cats are contained.
To add this behaviour to combo boxes you simply do this:
AutoCompleteComboBoxListener<Data> autoCompleteComboBoxListener =
new AutoCompleteComboBoxListener<Data>(cmbBx, predicate);
One pretty little feature of AutoCompleteComboBoxListener is that you can change the items of the combo box on the fly by calling AutoCompleteComboBoxListener.repopulate(ObservableList<T> newPopulation).
So finally here is the code for AutoCompleteComboBoxListener:
import java.util.function.Predicate;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.control.ComboBox;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
public class AutoCompleteComboBoxListener<T> implements EventHandler<KeyEvent>
{
// private final static Logger LOGGER = LogManager.getLogger(AutoCompleteComboBoxListener.class);
// constructor injection
private ComboBox<T> cmbBx;
private Predicate<T> predicate;
/** populated in constructor, holds a copy of the initial items */
private ObservableList<T> initialItems = FXCollections.observableArrayList();
public AutoCompleteComboBoxListener(final ComboBox<T> cmbBx, final Predicate<T> predicate)
{
this.cmbBx = cmbBx;
this.predicate = predicate;
initialItems.addAll(cmbBx.getItems());
// if combobox was not editable all effort in this class would be superfluous
cmbBx.setEditable(true);
cmbBx.setOnAction
(
e ->
{
cmbBx.getEditor().end();
// LOGGER.debug("editor: " + cmbBx.getEditor().getText() + ", value: " + cmbBx.getValue());
}
);
cmbBx.setOnKeyReleased(this);
}
@Override public void handle(KeyEvent keyEvent)
{
// handle events that allow for early return
if (keyEvent.getCode() == KeyCode.ENTER)
{
cmbBx.setValue(cmbBx.getSelectionModel().getSelectedItem());
// LOGGER.debug("editor: " + cmbBx.getEditor().getText() + ", value: " + cmbBx.getValue());
return;
}
if (keyEvent.getCode() == KeyCode.DOWN)
{
if (cmbBx.isShowing() == false)
{
cmbBx.show();
}
return;
}
if ( keyEvent.getCode() == KeyCode.LEFT
|| keyEvent.getCode() == KeyCode.RIGHT
|| keyEvent.getCode() == KeyCode.HOME
|| keyEvent.getCode() == KeyCode.END
|| keyEvent.getCode() == KeyCode.TAB
|| keyEvent.getCode() == KeyCode.BACK_SPACE
|| keyEvent.getCode() == KeyCode.DELETE
|| keyEvent.isControlDown()
|| keyEvent.isAltDown()
|| keyEvent.isShiftDown()
)
{
return;
}
repopulate(initialItems);
if (!cmbBx.getItems().isEmpty())
{
cmbBx.show();
}
}
public void repopulate(ObservableList<T> newPopulation)
{
initialItems = newPopulation;
boolean showing = cmbBx.isShowing();
// combobox items will be repopulated, so make sure the "old" items do not show any longer on the
// screen
cmbBx.hide();
// repopulate combobox.items with those initial items that match the predicate
ObservableList<T> list = FXCollections.observableArrayList();
cmbBx.setItems(list);
initialItems
.forEach
(
item ->
{
if (predicate.test(item))
{
list.add(item);
}
}
);
if (showing) cmbBx.show();
}
}
Cheers
Roger
Sunday 3 December 2017
jMDA UMLKit quickstart available
Wednesday 8 November 2017
jMDA still alive
- code generation
- java annotation processing and
- access to package javax.lang.model stuff
extremely convenient. As for the class diagram tool, here is a screenshot that demonstrates what it can do:
uml class diagram created from java types |
Saturday 5 October 2013
noDSL! – domain modelling with Java and software generation with jMDA
Thursday 26 September 2013
jump start annotation processing (even without annotations if you want)
define, compile and run dynamic code in RAM
Friday 20 September 2013
version 1.1.0 of jMDA arrived
Get your feet wet with jMDA quickly here.
Monday 24 June 2013
annotation processing rounds explained
jump start annotation processing within minutes using jMDA tasks
Sunday 16 June 2013
jMDA publishes jMDA book 1.0.0 together with new versions of jmda.core and jmda.sample
Sunday 5 May 2013
jMDA releases version 1.0.0 of its software modelling and generator framework
Today jMDA released a major upgrade of it's software modelling and generator framework. This article is an excerpt of a larger document describing jMDA that will be published later.
Sunday 30 December 2012
sample: jboss 7 datasource definition with derby network client
To sum it up: The configuration for my simple environment is very straight forward, especially there is no need to define a JBoss module or to specify particular Derby JDBC driver classes. All you have to do is place derbyclient.jar into JBoss deployments directory and insert a datasource definition into the respective section of the JBoss standalone.xml as follows:
<datasources>
...
<datasource jndi-name="java:/DataSourceDerbyNetwork"
pool-name="DataSourceDerbyNetwork">
<connection-url>jdbc:derby://localhost:1527/c:/data/db/derby/xxx;create=true</connection-url>
<driver>derbyclient.jar</driver>
<pool>
<min-pool-size>5</min-pool-size>
<max-pool-size>20</max-pool-size>
</pool>
<security>
<user-name>yyy</user-name>
<password>zzz</password>
</security>
<timeout>
<idle-timeout-minutes>5</idle-timeout-minutes>
</timeout>
<statement>
<track-statements>true</track-statements>
</statement>
</datasource>
...
</datasources>
Of course you have to adjust the data printed in bold according to your individual needs. Please refer to the Derby documentation for further details about the connection-url for example.
By the way: I removed the default datasource ExampleDS from standalone.xml and did not observe this causing any problems. Seems that ExampleDS, as its name says, is used for examples only.
Sunday 7 October 2012
Avoid unnecessary qualified type references in generated source code
Monday 17 September 2012
Combine jmda.core with jmda.gen and create JUnit test suites for existing JUnit tests
Saturday 8 September 2012
Create a simple Java source code generator with four lines of code using jmda.gen
Complete redesign of jmda.gen generator framework
Friday 22 June 2012
Create / update jaxb.index files
Map<File, Set<String>> indexData =
|
Saturday 16 June 2012
New jMDA based tools help to keep JAXB index files and package lists in sync
Update of jmda.core available
Sunday 3 June 2012
What has been going on with jMDA in the recent year?
I could not disagree with that and because I'm a huge UML fan I started looking around for appropriate Java to UML reverse engineering tools. It soon turned out that it was not easy to find any. Existing products often are extreme heavy weights, clumsy to use, expensive and so on. So I started playing around with an own solution. With jMDA at hand I had everything necessary to find out anything about a given jMDA model so the only thing to do was to bring that model information into an appealing graphical representation. First results looked very promising (at least in my eyes).
But soon some really nasty problems occured. The biggest among them being myself and my lacking knowledge and experience in developing software with a huge amount of obviously non mainstream graphical requirements. I started with a Java Swing approach but got frustrated about a lot of features that seem to be missing.Then I decided to try JavaFX 2.0. Again first results looked promising but missing basic features were a big disappointment.
After all I spent a lot of time in these investigations during the last year without satisfying results. However recently I became to know UML Explorer which does most of the things I was looking for very nicely in an eclipse environment. So I gave up or at least postponed my plans for an own solution. This will allow to concentrate on developing new and improving existing features for the actual jMDA products.
Saturday 2 June 2012
New blog started for jMDA
With this blog I hope to increase community interest and participation in jMDA and would be happy to receive comments and feedback. In the jMDA project I'd like to collaboratively improve and extend jMDA technology. I plan to discuss and publish new libraries that address particular application fields for jMDA.
Finally this blog wants to be a place for the community to share ideas and discuss jMDA related topics.
Some initial information about jMDA is already available here.