/*
* Created on 16.02.2005 for PIROL
*
* SVN header information:
* $Author: michaudm $
* $Rev: 1670 $
* $Date: 2009-02-25 00:33:13 +0100 (Mi, 25. Feb 2009) $
* $Id: StandardPirolPlugIn.java 1670 2009-02-24 23:33:13Z michaudm $
*/
package de.fho.jump.pirol.utilities.plugIns;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import org.openjump.core.apitools.FeatureCollectionTools;
import org.openjump.core.apitools.LayerTools;
import org.openjump.core.apitools.SelectionTools;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jump.feature.Feature;
import com.vividsolutions.jump.workbench.WorkbenchContext;
import com.vividsolutions.jump.workbench.model.Layer;
import com.vividsolutions.jump.workbench.plugin.AbstractPlugIn;
import com.vividsolutions.jump.workbench.plugin.EnableCheckFactory;
import com.vividsolutions.jump.workbench.plugin.MultiEnableCheck;
import com.vividsolutions.jump.workbench.plugin.PlugInContext;
import com.vividsolutions.jump.workbench.ui.ErrorHandler;
import com.vividsolutions.jump.workbench.ui.task.TaskMonitorDialog;
import de.fho.jump.pirol.utilities.debugOutput.PersonalLogger;
import de.fho.jump.pirol.utilities.i18n.PirolPlugInMessages;
import de.fho.jump.pirol.utilities.settings.PirolPlugInSettings;
/**
* Overrides most of the abstract methods of the AbstractPlugIn to implement
* a default behavior, that fits the needs for a plugIn in the PIROL context.
* Also implements the ErrorHandler interface and offers methods to post error
* messages to the GUI.
*
* @author Ole Rahn, Stefan Ostermann
* <br>
* <br>FH Osnabrück - University of Applied Sciences Osnabrück,
* <br>Project: PIROL (2005),
* <br>Subproject: Daten- und Wissensmanagement
*
* @version $Rev: 1670 $
*
*/
public abstract class StandardPirolPlugIn extends AbstractPlugIn implements ErrorHandler {
/**
* buffer for messages of errors that occured during execution - needed to implement the ErrorHandler interface
*/
protected StringBuffer messages = new StringBuffer();
/**
* Are errors to be shown in the statusbar (bringUpMessages = false, DEFAULT) or in an
* output window (bringUpMessages = true)?
*/
protected boolean bringUpMessages = false;
protected static EnableCheckFactory checkFactory = null;
/**
* see description for method getIconString() for more information
*/
protected ImageIcon icon = null;
protected boolean useToolIconSize = false;
protected static GeometryFactory geometryFactory = new GeometryFactory();
/**
* logger reference for use with the StandardPirolPlugIn. Since loggers are personalized, this member has to be
* initialized in derived classes by the programmer, before it can be used. For downward compatibility no abstract
* method or constructur parameter was introduced to do this.
* @since rev.1.12
*/
protected PersonalLogger logger = null;
/**
* Please, use this constructor in the deriving class!
*@param logger the logger that will controll console outputs
*@since rev.1.17
*/
public StandardPirolPlugIn(PersonalLogger logger) {
super();
this.logger = logger;
}
public String getShortClassName(){
int pointPos = this.getClass().getName().lastIndexOf(".");
if (pointPos > -1) {
return this.getClass().getName().substring(this.getClass().getName().lastIndexOf(".") + 1);
}
this.logger.printWarning("class name is very short: " + this.getClass().getName());
return this.getClass().getName();
}
public static MultiEnableCheck createEnableCheck(final WorkbenchContext workbenchContext, boolean needFence) {
if (StandardPirolPlugIn.checkFactory == null){
StandardPirolPlugIn.checkFactory = new EnableCheckFactory(workbenchContext);
}
MultiEnableCheck multiEnableCheck = new MultiEnableCheck();
multiEnableCheck.add( StandardPirolPlugIn.checkFactory.createAtLeastNLayersMustExistCheck(1) );
multiEnableCheck.add( StandardPirolPlugIn.checkFactory.createAtLeastNLayersMustBeSelectedCheck(1) );
if (needFence)
multiEnableCheck.add( StandardPirolPlugIn.checkFactory.createFenceMustBeDrawnCheck() );
return multiEnableCheck;
}
/**
* Method to enable loading an icon from the surrounding jar-file if necessary.
* If the plugin doesn't need an icon, just return <code>null</code> else
* return the file name, e.g. "xyz.png" and put the picture in the same folder
* (package) as the deriving class.
* @return the filename of the icon or <code>null</code> if the plugin has no icon.
*/
public abstract String getIconString();
/**
* This method is called to execute the PlugIn.
* @return always <code>true</code> ?
* @param context the snapshot of the current workbench.
* @throws Exception
* @see com.vividsolutions.jump.workbench.plugin.AbstractPlugIn#execute(com.vividsolutions.jump.workbench.plugin.PlugInContext)
*/
public abstract boolean execute(PlugInContext context) throws Exception;
/**
* Name of the PlugIn to be shown in the menus or as a tooltip in JUMP.<br>
* Looks for a key (the PlugIn's name with no path) in the i18n resources, if none is found
* the standard jump name generation will be used.
*/
public String getName() {
try {
return PirolPlugInMessages.getString(this.getShortClassName());
} catch (RuntimeException e) {
return super.getName();
}
}
/**
* The PlugIn will be added to the <code>PIROL Tools/<b>[return value of getCategoryName()]</b></code> menu and a standard {@link com.vividsolutions.jump.workbench.plugin.EnableCheck} is applied.
*@param context PlugInContext
*@throws Exception
*@see StandardPirolPlugIn#getCategoryName()
*/
public void initialize(PlugInContext context) throws Exception {
context.getFeatureInstaller().addMainMenuItem( this, new String[]{PirolPlugInSettings.getName_PirolMenu(), getCategoryName() }, this.getName(), false, null, StandardPirolPlugIn.createEnableCheck(context.getWorkbenchContext(),false));
}
/**
* The name of the category, a PlugIn can be found in - this method should be overridden by any derived class!
*@return name of the category, a PlugIn can be found in
*/
public String getCategoryName(){
return PirolPlugInMessages.getString("unsorted");
}
/**
* Standard intialization: PlugIn is added to the <code>PIROL Tools/<b>subMenuName</b></code> (or localized menu name) menu and a standard {@link com.vividsolutions.jump.workbench.plugin.EnableCheck} is applied.
* @deprecated
*/
public void initialize(PlugInContext context, String subMenuName) throws Exception {
if (this.logger!=null)
this.logger.printDebug("subMenuName: " + subMenuName);
context.getFeatureInstaller().addMainMenuItem( this, new String[]{PirolPlugInSettings.getName_PirolMenu(), subMenuName }, this.getName(), false, null, StandardPirolPlugIn.createEnableCheck(context.getWorkbenchContext(),false));
}
/**
*@param context the current PlugIn context
*@return a TaskMonitorDialog, to show progress information to the user
*/
public static TaskMonitorDialog getMonitor(PlugInContext context){
return new TaskMonitorDialog( context.getWorkbenchFrame(), context.getWorkbenchFrame() );
}
/**
* Prints output to the stdout. Can be invoked by deriving classes.
* @param function the name of the method from within this one is called.
* E.g. "myMethod()".
* @param msg the message String.
* @see #println(Class, String, String)
* @deprecated use logger instead!
*/
protected void println( String function, String msg ){
if (this.logger != null){
this.logger.printDebug(msg);
} else {
println( this.getClass(), function, msg );
}
}
/**
* Writes the given message and function string to the stdout.
* The output will be formated as "classname.function: message".
* @param c the calling class
* @param function the method from within this one is called.
* @param message the text with some useful information.
* @deprecated use logger instead!
*/
public static void println( Class c, String function, String message ){
System.out.println( c.getName() + "." + function + "(): " + message );
}
/**
* Puts a warning message into the statusbar of JUMP
*@param context curr. PlugInContext
*@param msg message to be shown to the user
*/
public static void warnUser(PlugInContext context, String msg){
context.getWorkbenchFrame().warnUser(msg);
}
/**
* Get a given number of selected Layers.
* @param context the current PlugInContext
* @param num max. number of layers to return, -1 returns all selected layers
* @return a given number of selected Layers, null if no Layers are selected
*/
public static Layer[] getSelectedLayers(PlugInContext context, int num){
return LayerTools.getSelectedLayers(context, num);
}
/**
* get one Layer that is selected
* @param context the current PlugInContext
* @return one selected Layer, null if no Layers are selected
*/
public static Layer getSelectedLayer(PlugInContext context){
return LayerTools.getSelectedLayer(context);
}
/**
* To be called, when leaving the execute()-method. Puts out the error messages
* collected during execution if any and returns the given boolean value.
* Example:<pre>return finishExecution(context, true);</pre>
*@param context the current PlugInContext
*@param retVal the value to be returned by execute()
*@return retVal
*/
protected boolean finishExecution( PlugInContext context, boolean retVal ){
this.postMessagesToGui(context);
return retVal;
}
protected void postMessagesToGui(PlugInContext context){
if (messages.length()!=0 && context!=null){
context.getOutputFrame().createNewDocument();
context.getOutputFrame().addText( messages.toString() );
if (bringUpMessages)
context.getOutputFrame().surface();
messages.delete(0,messages.length());
} else if (context==null){
this.println( "postMessagesToGui(PlugInContext context)", "-> context == null!");
}
}
public void handleThrowable(Throwable t) {
if (t.getMessage()==null || t.getMessage().equals("null")){
StackTraceElement[] stre = t.getStackTrace();
for (int i=0; i<stre.length; i++){
messages.append(stre[i].toString() + "\n");
}
} else if (t.getMessage()!=null){
messages.append(t.getMessage() + "\n");
}
}
/**
* Method to load an icon from the surrounding jar-file if necessary.
* @return the icon or <code>null</code> if the getIconString() returned null (or problems occured)
*/
public Icon getIcon() {
if ( icon == null && this.getIconString() != null){
InputStream in = this.getClass().getResourceAsStream(this.getIconString());
BufferedImage img = null;
Image scaledImg = null;
try {
img = ImageIO.read(in);
scaledImg = img.getScaledInstance(this.useToolIconSize?PirolPlugInSettings.StandardToolIconWidth:PirolPlugInSettings.StandardPlugInIconWidth, this.useToolIconSize?PirolPlugInSettings.StandardToolIconHeight:PirolPlugInSettings.StandardPlugInIconHeight, img.getType());
} catch (IOException e) {
e.printStackTrace();
img = null;
icon = null;
}
if (scaledImg != null){
icon = new ImageIcon(scaledImg);
}
}
return icon;
}
/**
* Get a List of Features (from the given Layer) that reside within the fence (if there is a fence) or just the features of the layer
* (if there is currently no fence)
*@param context the plugIn context
*@param layer the layer holding the features
*@return List of features within fence if present or just within the layer
*/
public static Feature[] getFeaturesInFenceOrInLayer(PlugInContext context,Layer layer){
SelectionTools st = new SelectionTools(context);
Feature[] featureToBeUsed = null;
if (st.getFenceGeometry()==null){
featureToBeUsed = FeatureCollectionTools.FeatureCollection2FeatureArray(layer.getFeatureCollectionWrapper().getUltimateWrappee());
} else {
featureToBeUsed = SelectionTools.getFeaturesInFenceInLayer(layer, st.getFenceGeometry());
}
return featureToBeUsed;
}
/**
*@return the personal logger
*@see PersonalLogger
*/
public PersonalLogger getLogger() {
return logger;
}
/**
* Sets the personal logger - enables debug statement handling
*@param logger the new personal logger
*@see PersonalLogger
*/
public void setLogger(PersonalLogger logger) {
this.logger = logger;
}
public void setUseInToolbox(boolean toolboxUse){
this.useToolIconSize = toolboxUse;
}
}