An utility class for working with metadata models in UI. Since model operations
might take a long time, the model access should not take place in
the event dispatching thread. Also, there should be status messages in the UI
informing the user about the current state ("Classpath scanning in progress",
"Reading entity classes", etc.). Writing code that does this
is a difficult task and the code tends to be prone to errors. This class attempts to
simplify this task.
This class can be used to execute an action while ensuring that it
is executed outside the AWT thread and that all states (classpath scanning,
reading the model) are handled. The state is encapsulated by the
#Stateenumeration, which can be one of:
IDLE
before the
#start method has been called.
WAITING_READY
waiting for the model to become
MetadataModel#isReady.
This e.g corresponds to the classpath scan being in progress for a metadata model
based on Java annotations.
READING_MODEL
reading the model.
FINISHED
the action has finished executing. The result of the
action can be
#getResult.
For example, this is how the class would be used to display the entity
classes in a wizard:
// the model to read from
private MetadataModel model;
// the read helper
private MetadataModelReadHelper> readHelper;
// the result of the model action (what will be read from the model)
private List entityNames;
// ...
public void readSettings(Object settings) {
wizardDescriptor = (WizardDescriptor)settings;
// ensure the read only takes place the first time readSettings() is called
if (model == null) {
// get the model (from a wizard property or in whatever way)
model = (MetadataModel)wizardDescriptor.getProperty("model"); // NOI18N
// pass a MetadataModelAction to the read helper -- the same action
// that would be passed directly to MetadataModel.runReadActionWhenReady()
readHelper = MetadataModelReadHelper.create(model, new MetadataModelAction>() {
public List run(EntityMappingsMetadata metadata) throws Exception {
List result = new ArrayList();
for (Entity entity : metadata.getRoot().getEntity()) {
result.add(entity.getName());
}
return result;
}
});
// need to listen on the read helper for state changes
// and forward them as wizard state changes, which will cause
// the isValid() method to be called
readHelper.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
fireChange();
}
});
// everything is set up, so start the read helper
// the helper now starts executing the action in another thread
readHelper.start();
}
}
// ...
public boolean isValid() {
// test the read helper state
switch (readHelper.getState()) {
case WAITING_READY:
setErrorMessage("Scanning classpath.");
return false;
case READING_MODEL:
setErrorMessage("Searching entity classes.");
return false;
case FINISHED:
// when we got here the model action has been executed
if (entityNames == null) {
try {
entityNames = readHelper.getResult();
// pass the entity names to the wizard's visual panel
getComponent().setEntityNames(entityNames);
} catch (ExecutionException e) {
Exceptions.printStackTrace(e);
}
}
}
if (entityNames != null) {
if (entityNames.size() == 0) {
setErrorMessage("No entities");
return false;
}
}
setErrorMessage(" ");
return true;
}