Coverage Report - com.buckosoft.PicMan.business.mosaic.MosaicEngine
 
Classes in this File Line Coverage Branch Coverage Complexity
MosaicEngine
0%
0/129
0%
0/26
1.781
MosaicEngine$ConfigItem
0%
0/19
N/A
1.781
 
 1  
 /******************************************************************************
 2  
  * MosaicEngine.java - Base class for the Mosaic engines
 3  
  * 
 4  
  * PicMan - The BuckoSoft Picture Manager in Java
 5  
  * Copyright(c) 2007 - Dick Balaska
 6  
  * 
 7  
  */
 8  
 package com.buckosoft.PicMan.business.mosaic;
 9  
 
 10  
 import java.awt.image.BufferedImage;
 11  
 import java.io.File;
 12  
 import java.util.Date;
 13  
 import java.util.HashMap;
 14  
 import java.util.Iterator;
 15  
 import java.util.LinkedList;
 16  
 
 17  
 import javax.imageio.ImageIO;
 18  
 import javax.imageio.ImageWriter;
 19  
 import javax.imageio.stream.ImageOutputStream;
 20  
 
 21  
 import org.apache.commons.logging.Log;
 22  
 import org.apache.commons.logging.LogFactory;
 23  
 
 24  
 import com.buckosoft.PicMan.business.PicManFacade;
 25  
 import com.buckosoft.PicMan.business.util.CopyFile;
 26  
 import com.buckosoft.PicMan.db.DatabaseFacade;
 27  
 import com.buckosoft.PicMan.domain.JobLogEntry;
 28  
 import com.buckosoft.PicMan.domain.Mosaic;
 29  
 import com.buckosoft.PicMan.domain.Pic;
 30  
 import com.buckosoft.PicMan.domain.Set;
 31  
 
 32  
 /** Base class for the mosaic engines
 33  
  * @author Dick Balaska
 34  
  * @since 2007/12/23
 35  
  * @see <a href="http://cvs.buckosoft.com/Projects/PicMan/PicMan/src/main/java/com/buckosoft/PicMan/business/mosaic/MosaicEngine.java">MosaicEngine.java</a>
 36  
  * @see com.buckosoft.PicMan.business.mosaic.engine
 37  
  */
 38  
 public class MosaicEngine {
 39  0
         protected static boolean DEBUG = false;
 40  0
         private final Log logger = LogFactory.getLog(getClass());
 41  
 
 42  
         protected        PicManFacade        pmf;
 43  
         protected        DatabaseFacade        dbf;
 44  
 
 45  
         protected        Mosaic                        mosaic;
 46  
         protected        Pic                                masterPic;
 47  
         protected        int                                mid;
 48  
         protected        BufferedImage        bi;
 49  0
         protected        int                                tileHeight = 50;
 50  0
         protected        Date                        lastMosaicUpdate = new Date(0);
 51  
         protected        Set                                mosaicSet;                // The Set to fetch our pics from
 52  
 
 53  0
         protected        JobLogEntry                jobLogEntry = null;
 54  
 
 55  
         /** A hash of all of the configured parameters */
 56  0
         protected HashMap<String, ConfigItem>        configMap = new HashMap<String, ConfigItem>();
 57  
         /** The names of the configured parameters, so we can pull them in a reasonable order for display. */
 58  0
         protected LinkedList<String>                        configList = new LinkedList<String>();
 59  
 
 60  0
         protected HashMap<String, Object>        buildParameters = new HashMap<String, Object>();
 61  
 
 62  
         /** Default constructor
 63  
          * Base class constructor.  Place your engine config attributes in your constructor. 
 64  
          */
 65  0
         public MosaicEngine() {
 66  0
                 addConfig("rateWeight", "rate multiplier when selecting pics", ConfigItem.TYPE_DOUBLE, 1.0);
 67  
                 
 68  0
         }
 69  
         /** Set the reference to the PicMan API.
 70  
          * @param pmf The PicManFacade
 71  
          */
 72  
         public        void setPicMan(PicManFacade pmf) {
 73  0
                 this.pmf = pmf;
 74  0
                 this.dbf = pmf.getDB();
 75  0
         }
 76  
 
 77  
         /** Enable logger output on this module
 78  
          * @param debugFlag true == turn on debugging.
 79  
          */
 80  
         public void setDEBUG(boolean debugFlag) {
 81  0
                 DEBUG = debugFlag;
 82  0
         }
 83  
 
 84  
         /**
 85  
          * @return the lastMosaicUpdate
 86  
          */
 87  
         public Date getLastMosaicUpdate() {
 88  0
                 return lastMosaicUpdate;
 89  
         }
 90  
 
 91  
         protected void setLastMosaicUpdate() {
 92  0
                 this.lastMosaicUpdate = new Date();
 93  0
         }
 94  
         
 95  
         /** Get the Tile Height / thumbnail height to be used to build this Mosaic.
 96  
          * This assumes an engine deals in tileHeights, which is true for now.
 97  
          * @return the tileHeight
 98  
          */
 99  
         public int getTileHeight() {
 100  0
                 return tileHeight;
 101  
         }
 102  
 
 103  
         /**
 104  
          * @param tileHeight the tileHeight to set
 105  
          */
 106  
         public void setTileHeight(int tileHeight) {
 107  0
                 this.tileHeight = tileHeight;
 108  0
         }
 109  
 
 110  
         /** Fetch the image that we built / are building.
 111  
          * @return the bufferedImage
 112  
          */
 113  
         public BufferedImage getImage() {
 114  0
                 return bi;
 115  
         }
 116  
         
 117  
         /** Get the name of the Mosaic that we are building.
 118  
          * @return The Mosaic name from the Mosaic.
 119  
          */
 120  
         public String        getName() {
 121  0
                 if (this.mosaic != null)
 122  0
                         return(this.mosaic.getName());
 123  0
                 return("No Name");
 124  
         }
 125  
 
 126  
         /** Get the name of the master pic that we are building from.
 127  
          * @return The name of the master pic.
 128  
          */
 129  
         public String        getMasterPicName() {
 130  0
                 if (this.mosaic != null)
 131  0
                         return(this.mosaic.getMasterPic());
 132  0
                 return("");
 133  
         }
 134  
         /** Get the name of the output file that will be written.
 135  
          * @return        The User specified output file. i.e. "C:\myMosaics\Mosaic1.jpg"
 136  
          */
 137  
         public String        getOutputFileName() {
 138  0
                 if (this.mosaic != null)
 139  0
                         return(this.mosaic.getOutPic());
 140  0
                 return("No Filename");
 141  
         }
 142  
 
 143  
         /** Fetch how long this Engine has been running.
 144  
          * @return Something like "1:23:45"
 145  
          */
 146  
         public String        getDurationAsString() {
 147  0
                 if (jobLogEntry == null)
 148  0
                         return("xx:xx");
 149  0
                 return(jobLogEntry.getDurationAsString());
 150  
         }
 151  
 
 152  
         /** Set the Mosaic that we are going to build.
 153  
          * @param mosaic The Mosaic parameters as specified by the User.
 154  
          */
 155  
         public        void        setMosaic(Mosaic mosaic) {
 156  0
                 this.mosaic = mosaic;
 157  0
                 this.mosaicSet = pmf.getDB().getSet(mosaic.getSid());
 158  0
                 this.masterPic = pmf.getDB().getPic(mosaic.getMasterPic());
 159  0
                 this.mid = mosaic.getMid();
 160  0
                 this.tileHeight = mosaic.getTileHeight();
 161  0
                 this.setupBuildParameters();
 162  0
                 this.bi = pmf.getPicReader().readPic(this.masterPic);
 163  0
                 setLastMosaicUpdate();
 164  0
         }
 165  
 
 166  
 
 167  
         /** Write the built image to the jpg specified in outPic
 168  
          * @param makeBackup Maintain a set of backups of the output mosaic.
 169  
          */
 170  
         public        void        outputMosaicFile(boolean makeBackup) {
 171  0
                 Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
 172  0
                 ImageWriter writer = (ImageWriter)writers.next();
 173  0
                 File file = new File(this.mosaic.getOutPic());
 174  0
                 if (DEBUG)
 175  0
                         logger.info("Writing jpg to '" + file.getPath() + "'");
 176  
                 try {
 177  0
                         ImageOutputStream oos = ImageIO.createImageOutputStream(file);
 178  0
                         writer.setOutput(oos);
 179  0
                         writer.write(bi);
 180  0
                         oos.close();
 181  0
                 } catch (Exception e) {
 182  
 //                        bi = null;
 183  0
                         pmf.addError(new Exception ("Can't write jpeg to '"+ file.getPath() + "'",e));
 184  0
                         return;
 185  0
                 }
 186  0
                 if (makeBackup)
 187  0
                         CopyFile.makeBackup(pmf, file);
 188  0
         }
 189  
 
 190  
         /** Build the Mosaic.
 191  
          * @return true if there is more work to do.
 192  
          * @throws Exception Something went wrong.
 193  
          */
 194  
         public boolean build() throws Exception {
 195  0
                 jobLogEntry = new JobLogEntry();
 196  0
                 jobLogEntry.setType(JobLogEntry.MOSAIC);
 197  0
                 jobLogEntry.setName(this.mosaic.getName());
 198  0
                 pmf.addJobToLog(jobLogEntry);
 199  0
                 this.mosaic.setStartTime(new Date());
 200  0
                 boolean ret = false;
 201  
                 try {
 202  0
                         ret = _build();
 203  0
                 } catch (Exception e) {
 204  0
                         jobLogEntry.setEndTime();
 205  0
                         throw e;
 206  0
                 }
 207  0
                 jobLogEntry.setEndTime();
 208  0
                 if (!mosaic.isBatch())
 209  0
                         pmf.getDB().storeMosaic(mosaic);
 210  0
                 outputMosaicFile(mosaic.isMakeBackup());
 211  0
                 return(ret);
 212  
         }
 213  
 
 214  
         protected boolean _build() throws Exception {
 215  0
                 throw new Exception("Should be overridden");
 216  
                 
 217  
         }
 218  
 
 219  
         /** Get the engine's build status.  This should be overridden by the actual engine.
 220  
          * @return i.e. SecondRibbon returns "Calc: pass=13 p=901"
 221  
          */
 222  
         public String getStatus() {
 223  0
                 return("Should be overridden");
 224  
         }
 225  
         
 226  
         /** Get the engine's semi-static build info.  This should be overridden by the actual engine.
 227  
          * @return i.e. SecondRibbon returns "tileRows=154 maxCol=2048 pics=5820"
 228  
          */
 229  
         public String getInfo() {
 230  0
                 return("Should be overridden");
 231  
         }
 232  
         
 233  
         /** Support for runtime MosaicEngine configuration.
 234  
          * These define the available configurable attributes for an engine.
 235  
          * @author Dick Balaska
 236  
          * @since 2009/07/17
 237  
          * @version $Revision: 1.5 $ <br> $Date: 2014/06/21 04:35:32 $
 238  
          * @see MosaicEngine
 239  
          */
 240  0
         public class ConfigItem {
 241  
                 public final static int TYPE_STRING         = 1;
 242  
                 public final static int TYPE_INT                 = 2;
 243  
                 public final static int TYPE_DOUBLE                = 3;
 244  
                 public final static int TYPE_BOOLEAN        = 4;
 245  
 
 246  
                 private String        name;
 247  
                 private String        description;
 248  
                 @SuppressWarnings("unused")
 249  
                 private int                order;                        // aborted attempt to display the config fields in order
 250  
                 private int                type;
 251  
                 private int                valueInt;
 252  
                 private double        valueDouble;
 253  
                 private String        valueString;
 254  
                 
 255  
                 /** Construct a ConfigItem with these parameters
 256  
                  * @param name The name of the item
 257  
                  * @param description A description to go in the web page
 258  
                  * @param type String/int/bool/etc.
 259  
                  * @param order The order that this item was entered, for display
 260  
                  */
 261  0
                 public ConfigItem(String name, String description, int type, int order) {
 262  0
                         this.name = name;
 263  0
                         this.description = description;
 264  0
                         this.type = type;
 265  0
                         this.order = order;
 266  0
                 }
 267  
 
 268  
                 /**
 269  
                  * @return the valueInt
 270  
                  */
 271  
                 public int getValueInt() {
 272  0
                         return valueInt;
 273  
                 }
 274  
 
 275  
                 /**
 276  
                  * @param valueInt the valueInt to set
 277  
                  */
 278  
                 public void setValueInt(int valueInt) {
 279  0
                         this.valueInt = valueInt;
 280  0
                 }
 281  
 
 282  
                 /**
 283  
                  * @return the valueDouble
 284  
                  */
 285  
                 public double getValueDouble() {
 286  0
                         return valueDouble;
 287  
                 }
 288  
 
 289  
                 /**
 290  
                  * @param valueDouble the valueDouble to set
 291  
                  */
 292  
                 public void setValueDouble(double valueDouble) {
 293  0
                         this.valueDouble = valueDouble;
 294  0
                 }
 295  
 
 296  
                 /**
 297  
                  * @return the valueString
 298  
                  */
 299  
                 public String getValueString() {
 300  0
                         return valueString;
 301  
                 }
 302  
 
 303  
                 /**
 304  
                  * @param valueString the valueString to set
 305  
                  */
 306  
                 public void setValueString(String valueString) {
 307  0
                         this.valueString = valueString;
 308  0
                 }
 309  
 
 310  
                 /** Get the name of this ConfigItem.
 311  
                  * @return the name
 312  
                  */
 313  
                 public String getName() {
 314  0
                         return name;
 315  
                 }
 316  
 
 317  
                 /**
 318  
                  * @return the description
 319  
                  */
 320  
                 public String getDescription() {
 321  0
                         return description;
 322  
                 }
 323  
 
 324  
                 /**
 325  
                  * @return the type
 326  
                  */
 327  
                 public int getType() {
 328  0
                         return type;
 329  
                 }
 330  
                 
 331  
         }
 332  
 
 333  
         protected void addConfig(String name, String description, int type, int value) {
 334  0
                 ConfigItem ci = new ConfigItem(name, description, type, configMap.size());
 335  0
                 ci.valueInt = value;
 336  0
                 configMap.put(name, ci);
 337  0
                 configList.add(name);
 338  0
         }
 339  
         protected void addConfig(String name, String description, int type, double value) {
 340  0
                 ConfigItem ci = new ConfigItem(name, description, type, configMap.size());
 341  0
                 ci.valueDouble = value;
 342  0
                 configMap.put(name, ci);
 343  0
                 configList.add(name);
 344  0
         }
 345  
 
 346  
         /** A map of the available ConfigItems for an engine.
 347  
          * @return The map of ConfigItems for this engine keyed by the item name.
 348  
          */
 349  
         public HashMap<String, ConfigItem> getConfigMap() {
 350  0
                 return(configMap);
 351  
         }
 352  
         
 353  
         private void setupBuildParameters() {
 354  0
                 HashMap<String, String> engineConfig = mosaic.getEngineConfig();
 355  0
                 for (String key : configMap.keySet()) {
 356  0
                         ConfigItem ci = configMap.get(key);
 357  0
                         String v = engineConfig.get(key);
 358  0
                         if (v != null) {
 359  0
                                 switch (ci.type) {
 360  
                                 case ConfigItem.TYPE_INT:
 361  0
                                         int i = -1;
 362  
                                         try {
 363  0
                                                 i = Integer.parseInt(v);
 364  0
                                         } catch (NumberFormatException e) {
 365  0
                                                 pmf.addError(e);
 366  0
                                                 logger.info(e);
 367  0
                                                 i = -1;
 368  0
                                         }
 369  0
                                         buildParameters.put(key, new Integer(i));
 370  0
                                         break;
 371  
                                 case ConfigItem.TYPE_DOUBLE:
 372  0
                                         double d = 0.0;
 373  
                                         try {
 374  0
                                                 if (!v.isEmpty())
 375  0
                                                         d = Double.parseDouble(v);
 376  0
                                         } catch (NumberFormatException e) {
 377  0
                                                 pmf.addError(e);
 378  0
                                                 logger.info(e);
 379  0
                                                 d = 0.0;
 380  0
                                         }
 381  0
                                         buildParameters.put(key, new Double(d));
 382  0
                                         break;
 383  
                                 default:
 384  0
                                         Exception e = new Exception("Unhandled type " + ci.type);
 385  0
                                         pmf.addError(e);
 386  0
                                         logger.info(e);
 387  0
                                         break;
 388  
                                 }
 389  
                         } else {
 390  0
                                 switch (ci.type) {
 391  
                                 case ConfigItem.TYPE_INT:
 392  0
                                         buildParameters.put(key, new Integer(ci.getValueInt()));
 393  0
                                         break;
 394  
                                 case ConfigItem.TYPE_DOUBLE:
 395  0
                                         buildParameters.put(key, new Double(ci.getValueDouble()));
 396  0
                                         break;
 397  
                                 default:
 398  0
                                         Exception e = new Exception("Unhandled default type " + ci.type);
 399  0
                                         pmf.addError(e);
 400  0
                                         logger.info(e);
 401  
                                         break;
 402  
                                 }
 403  
                         }
 404  0
                 }
 405  0
         }
 406  
 }