/*
* Project: AMODA - Abstract Modeled Application
* Class: de.gulden.framework.amoda.generic.core.GenericApplication
* Version: snapshot-beautyj-1.1
*
* Date: 2004-09-29
*
* This is a snapshot version of the AMODA 0.2 development branch,
* it is not released as a seperate version.
* For AMODA, see http://amoda.berlios.de/.
*
* This is licensed under the GNU Lesser General Public License (LGPL)
* and comes with NO WARRANTY.
*
* Author: Jens Gulden
* Email: amoda@jensgulden.de
*/
package de.gulden.framework.amoda.generic.core;
import de.gulden.framework.amoda.generic.core.GenericApplicationEnvironmentFactory;
import de.gulden.framework.amoda.generic.metadata.*;
import de.gulden.framework.amoda.generic.option.*;
import de.gulden.framework.amoda.model.behaviour.Command;
import de.gulden.framework.amoda.model.behaviour.event.*;
import de.gulden.framework.amoda.model.core.*;
import de.gulden.framework.amoda.model.core.Application;
import de.gulden.framework.amoda.model.data.*;
import de.gulden.framework.amoda.model.document.*;
import de.gulden.framework.amoda.model.interaction.*;
import de.gulden.framework.amoda.model.option.*;
import de.gulden.framework.amoda.model.option.Option;
import de.gulden.util.*;
import java.lang.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
import org.w3c.dom.*;
import org.w3c.dom.Document;
/**
* Class GenericApplication.
*
* @author Jens Gulden
* @version snapshot-beautyj-1.1
*/
public abstract class GenericApplication extends GenericApplicationModule implements Application, Command, LogPerformer {
// ------------------------------------------------------------------------
// --- fields ---
// ------------------------------------------------------------------------
public static String DEFAULT_CONFIGURATION_RESOURCE = System.getProperty("application.config" ,"res:application.xml");
public static final int YES = 0;
public static final int NO = 2;
public static final int CANCEL = 4;
public boolean verbose;
public boolean quiet;
protected Option[] simpleAnswerOptions;
protected Queue commandQueue;
protected Stack commandUndoStack;
protected Document configuration;
protected DocumentHandler documentHandler;
protected RecentFilesList recentFilesList;
public static final String OPTIONS_DIALOG_TITLE = "Options";
protected GenericApplicationEnvironment genericApplicationEnvironment;
public UndoStack undoStack;
public Collection applicationListener = new ArrayList();
// ------------------------------------------------------------------------
// --- constructor ---
// ------------------------------------------------------------------------
public GenericApplication() {
super();
setDocumentHandler(createDocumentHandler()); // default impl.
setRecentFilesList(createRecentFilesList());
}
// ------------------------------------------------------------------------
// --- methods ---
// ------------------------------------------------------------------------
public GenericApplicationEnvironment getGenericApplicationEnvironment() {
return genericApplicationEnvironment;
}
public void setGenericApplicationEnvironment(GenericApplicationEnvironment genericApplicationEnvironment) {
if (this.genericApplicationEnvironment != genericApplicationEnvironment) {
this.genericApplicationEnvironment = genericApplicationEnvironment;
if (genericApplicationEnvironment != null) genericApplicationEnvironment.setGenericApplication(this);
}
}
public UndoStack getUndoStack() {
return undoStack;
}
public void setUndoStack(UndoStack undoStack) {
this.undoStack = undoStack;
}
public Collection getApplicationListeners() {
return applicationListener;
}
public void addApplicationListener(ApplicationListener applicationListener) {
if (! this.applicationListener.contains(applicationListener)) this.applicationListener.add(applicationListener);
}
public void removeApplicationListener(ApplicationListener applicationListener) {
this.applicationListener.remove(applicationListener);
}
public void log(String text, Object source) {
de.gulden.framework.amoda.model.interaction.LogMessage m=getGenericApplicationEnvironment().createDefaultLogMessage(text,source,Message.INFORMATION_MESSAGE,null);
m.perform();
}
public void init(ApplicationEnvironment environment) {
GenericApplicationEnvironment env=(GenericApplicationEnvironment)environment; // throws ClastCastException if invalid environment
setGenericApplicationEnvironment(env);
simpleAnswerOptions=new de.gulden.framework.amoda.model.option.Option[3];
simpleAnswerOptions[0]=env.createDefaultOption("YES",Boolean.FALSE,env.createDefaultMetadata("Yes"));
simpleAnswerOptions[1]=env.createDefaultOption("NO",Boolean.FALSE,env.createDefaultMetadata("No"));
simpleAnswerOptions[2]=env.createDefaultOption("CANCEL",Boolean.FALSE,env.createDefaultMetadata("Cancel"));
undoStack=new UndoStack();
this.initModule(this);
}
public void start() {
super.start();
// to be extended or overwritten by subclass
if (getOptions().getBoolean(GenericApplicationEnvironment.CONFIGURATION_BATCH_MODE)) {
Collection batchCommands=((GenericApplicationEnvironment)getEnvironment()).getBatchCommands();
// do batch commands before starting interaction
for (Iterator it=batchCommands.iterator();it.hasNext();) {
de.gulden.framework.amoda.model.behaviour.Command c=(de.gulden.framework.amoda.model.behaviour.Command)it.next();
c.perform();
}
}
if (getOptions().getBoolean(GenericApplicationEnvironment.CONFIGURATION_INTERACTION_MODE)) {
startInteraction();
}
}
public void message(String title, String text) {
de.gulden.framework.amoda.model.interaction.Message m=getGenericApplicationEnvironment().createDefaultMessage(title,text,Message.INFORMATION_MESSAGE,null);
m.perform();
}
public void message(String text) {
message("Message",text);
}
public void log(String text) {
log(text,this);
}
public void error(String text, Throwable throwable, boolean exitApplication) {
de.gulden.framework.amoda.model.interaction.ErrorMessage m=getGenericApplicationEnvironment().createDefaultErrorMessage(text,throwable,exitApplication,null);
m.perform();
}
public String question(String title, String text, String answers) {
de.gulden.framework.amoda.model.interaction.Question q=getGenericApplicationEnvironment().createDefaultQuestion(title,text,answers,null);
getGenericApplicationEnvironment().doQuestion(q);
return q.getAnswer();
}
public String question(String text, String answers) {
return question("",text,answers);
}
public boolean confirm(String title, String text) {
return question(title,text,"yes,no").equals("yes");
}
public boolean confirm(String text) {
return confirm("",text);
}
public void run() {
ApplicationEnvironment env=createApplicationEnvironment();
env.launch(this);
}
public void startInteraction() {
// your code here
}
public void about() {
((GenericApplicationEnvironment)getEnvironment()).doAbout();
}
public void welcome() {
// your code here
}
public void usage(boolean exitApplication) {
((GenericApplicationEnvironment)getEnvironment()).doUsage(exitApplication);
}
public void usage(String errorText) {
message("Error: "+errorText);
usage(true);
}
public void error(Throwable throwable, boolean exit) {
error("",throwable,exit);
}
public Application getApplication() {
return this;
}
public ApplicationEnvironment getEnvironment() {
return getGenericApplicationEnvironment();
}
public void error(String text, Throwable cause) {
error(text,cause,isBatchMode());
}
public void error(String text) {
error(text,null);
}
public void fatalError(String text, Throwable cause) {
error(text,cause,true);
}
public void fatalError(String text) {
fatalError(text,null);
}
public void error(Throwable cause) {
error("",cause);
}
public void fatalError(Throwable cause) {
String msg = cause.getMessage();
if (msg == null) {
msg = "-" + cause.getClass().getName() + "-";
}
fatalError(msg, cause);
}
public URL getResource(String res) {
URL url;
if (res.startsWith("/")) { // absolute URL
url=this.getClass().getResource(res);
} else {
String resBase=getOptions().getString("resource-base");
if (!resBase.endsWith("/")) resBase+="/";
url=this.getClass().getResource(resBase+res);
if (url==null) { // not yet found, try in system-resources
resBase=getOptions().getString("environment-resource-base");
if (!resBase.endsWith("/")) resBase+="/";
url=this.getClass().getResource(resBase+res);
// is still not found, url==null
}
}
return url;
}
public ImageIcon getImage(String res) {
return new ImageIcon(getResource(res));
}
public Workspace getWorkspace() {
return getGenericApplicationEnvironment().getWorkspace();
}
public ArgsParser createArgsParser() {
// your code here
return null;
}
public Workspace createWorkspace() {
return getGenericApplicationEnvironment().createDefaultWorkspace();
}
public void status(String text) {
Message m=getGenericApplicationEnvironment().createDefaultMessage(null,text,Message.STATUS_MESSAGE,null);
m.perform();
}
public DocumentHandler getDocumentHandler() {
return documentHandler;
}
public void setDocumentHandler(DocumentHandler _documentHandler) {
documentHandler = _documentHandler;
}
public RecentFilesList getRecentFilesList() {
return recentFilesList;
}
public void setRecentFilesList(RecentFilesList _recentFilesList) {
recentFilesList = _recentFilesList;
}
public boolean isVerbose() {
try {
return verbose || getOptions().getBoolean("verbose");
} catch (IllegalOptionError ioe) {
return verbose;
}
}
public void setVerbose(boolean _verbose) {
verbose = _verbose;
}
public boolean isQuiet() {
return quiet || getOptions().getBoolean("quiet");
}
public void setQuiet(boolean _quiet) {
quiet = _quiet;
}
public void exit() {
exit(0);
}
public void exit(int code) {
getGenericApplicationEnvironment().doExit(this, code);
}
public boolean isBatchMode() {
return getOptions().getBoolean("batch-mode");
}
public Value[] getInputValues() {
return getGenericApplicationEnvironment().getInputValues();
}
public void optionsDialog() {
de.gulden.framework.amoda.generic.interaction.GenericDialog d=new de.gulden.framework.amoda.generic.interaction.GenericDialog();
d.setTitle(OPTIONS_DIALOG_TITLE);
d.setParent(this);
d.setOptionsDirectly(getOptions()); // ..._Directly_ to avoid setting back-reference as parent member of options
d.perform();
if (d.getAnswer()==d.OK) {
((de.gulden.framework.amoda.generic.option.GenericOptions)getOptions()).saveGlobalProperties();
}
}
public void perform() {
// your code here
}
public void help() {
((GenericApplicationEnvironment)getEnvironment()).doHelp();
}
public Collection getAvailableFeatures() {
ArrayList features = new ArrayList();
for (Iterator it = getFeatures().iterator(); it.hasNext(); ) {
GenericFeature f = (GenericFeature)it.next();
if (!f.isSystem()) {
features.add(f);
}
}
return features;
}
public synchronized boolean isInInitializing() {
return true;
}
public synchronized boolean isInRunning() {
return true;
}
public synchronized boolean isInWaitingForCommand() {
return true;
}
public synchronized boolean isInExecutingCommand() {
return true;
}
public synchronized boolean isInDestroying() {
return true;
}
protected abstract ApplicationEnvironment createApplicationEnvironment();
protected Message createAboutMessage() {
String name=getMetadata().get("title");
if (Toolbox.empty(name)) {
name=getMetadata().get("name");
if (Toolbox.empty(name)) {
name="";
}
}
String version=getMetadata().get("version");
if (!Toolbox.empty(version)) {
version=" "+version;
} else {
version="";
}
String author=getMetadata().get("author");
if (!Toolbox.empty(author)) {
author=" by "+author;
String email=getMetadata().get("email");
if (!Toolbox.empty(email)) {
email=", "+email;
author=author+email;
}
} else {
author="";
}
String license=getMetadata().get("license-message"); // metadata description by default
if (!Toolbox.empty(license)) {
license=NL+license;
} else {
license="";
}
Message m = getGenericApplicationEnvironment().createDefaultMessage("about", name + version + author + license ,0,null);
return m;
}
protected Message createUsageMessage() {
StringBuffer sb=new StringBuffer();
String description = getMetadata().get("description").trim();
if (description.length()!=0) {
sb.append(description+NL+NL);
}
String usageLine = getUsageLine();
if (usageLine!=null) {
sb.append("Usage: "+usageLine+NL);
}
return getGenericApplicationEnvironment().createDefaultMessage("Usage",sb.toString(),0,null);
}
protected DocumentHandler createDocumentHandler() {
// your code here
return null;
}
protected ClipboardHandler createClipboardHandler() {
// your code here
return null;
}
protected RecentFilesList createRecentFilesList() {
return new GenericRecentFilesList();
}
protected URL getDefaultConfigurationDocumentResource() {
URL res;
try {
res = Toolbox.getResourceURL(DEFAULT_CONFIGURATION_RESOURCE);
} catch (java.net.MalformedURLException mue) {
res = null;
}
if (res != null) {
return res;
} else {
return super.getDefaultConfigurationDocumentResource();
}
}
protected Message createHelpMessage() {
StringBuffer sb=new StringBuffer();
Collection allOptions = getOptions().getAll(de.gulden.framework.amoda.model.option.OptionEntry.class, true).values();
if (!allOptions.isEmpty()) {
sb.append("options are: "+NL);
double[] weights={ 0.0, 0.0, 1.0 };
de.gulden.util.text.TextTable table=new de.gulden.util.text.TextTable( 3, 79, weights, ' ' );
for (Iterator it=allOptions.iterator();it.hasNext();) {
de.gulden.framework.amoda.generic.option.GenericOptionEntry o=(de.gulden.framework.amoda.generic.option.GenericOptionEntry)it.next();
if (!(o.isSystem())) {
String name = "-" + o.getId();
String shortcut = o.getShortcut();
if (shortcut != null) {
name = "-" + shortcut + " or\n" + name;
}
String description=de.gulden.util.Toolbox.noNull(o.getMetadata().get("description"));
String type="<"+de.gulden.util.Toolbox.unqualify(o.getType().getName()).toLowerCase()+">";
String defaultValue=o.getValue(o.STATE_DEFAULT).getString();
if (defaultValue!=null) {
description+=" (default: "+defaultValue+")";
}
String[] row = { name, type, description };
table.addRow(row);
}
}
sb.append(table.toString());
}
Message usage = createUsageMessage();
return getGenericApplicationEnvironment().createDefaultMessage("Help", usage.getText()+NL+sb.toString(), 0, null);
}
protected String getUsageLine() {
String u = getMetadata().get("usage").trim();
if (u.length()==0) {
u = getDefaulUsageLine();
}
return u;
}
protected String getDefaulUsageLine() {
if (getOptions().getBoolean(GenericApplicationEnvironment.CONFIGURATION_PERSISTENT_OPTIONS)) {
return "[java-and-classpath] "+findTitle().toLowerCase()+" -properties [properties-file]";
} else {
ArrayList relevantFeatures = new ArrayList();
for (Iterator it = getAvailableFeatures().iterator(); it.hasNext(); ) {
Feature f = (Feature)it.next();
if (
(! (f.getId().equals("default") || f.getId().equals("exit")))
&& (! ( (f instanceof de.gulden.framework.amoda.model.core.FeatureGroup) || (f instanceof de.gulden.framework.amoda.model.interaction.InteractionMember ) ) )
) {
relevantFeatures.add(f);
}
}
return "[java-and-classpath] "+findTitle().toLowerCase()+" "+((relevantFeatures.size()>0)?"[commands] ":"")+"[options] [input]";
}
}
void initModule(GenericApplicationModule module) {
// load configuration from XML
org.w3c.dom.Element tag=module.getConfigurationDocument().getDocumentElement();
try {
de.gulden.util.xml.serializer.XMLSerializerFactory factory=getGenericApplicationEnvironment().getFactory().getXMLSerializerFactory();
de.gulden.util.xml.serializer.XMLSerializer ser=factory.createXMLSerializer();
ser.xmlDeserialize(module, tag);
if (this != module) { // also deserialize on this to get new options and features
de.gulden.framework.amoda.model.metadata.Metadata rememberMetadata = this.getMetadata();
this.setMetadata(null); // DIRTY!
ser.xmlDeserialize(this, tag); // !!! to get options etc. of module into application, EXPERIMENTAL
this.setMetadata(rememberMetadata); // DIRTY!
}
} catch (de.gulden.util.xml.XMLException e) {
fatalError("can't parse configuration XML",e);
}
// re-init options
getGenericApplicationEnvironment().initApplicationOptions(this);
// init modules itself
module.init();
// inform listeners
Toolbox.fireEvent(getApplicationListeners(), "moduleLoaded", new de.gulden.framework.amoda.model.behaviour.event.ApplicationEvent(module));
}
} // end GenericApplication
|