Coverage Report - com.buckosoft.PicMan.business.ContactManager
 
Classes in this File Line Coverage Branch Coverage Complexity
ContactManager
0%
0/239
0%
0/122
6.125
 
 1  
 /******************************************************************************
 2  
  * ContactManager.java - Manage making the contact sheets.  Insure single threadedness
 3  
  * (two copies could lead to _heavens_ out of memory
 4  
  * 
 5  
  * PicMan - The BuckoSoft Picture Manager in Java
 6  
  * Copyright(c) 2005 - Dick Balaska
 7  
  * 
 8  
  */
 9  
 package com.buckosoft.PicMan.business;
 10  
 
 11  
 import java.io.File;
 12  
 import java.util.ArrayList;
 13  
 import java.util.Date;
 14  
 import java.util.HashMap;
 15  
 import java.util.Iterator;
 16  
 import java.util.LinkedList;
 17  
 import java.util.List;
 18  
 import java.util.concurrent.locks.ReentrantLock;
 19  
 
 20  
 import org.apache.commons.logging.Log;
 21  
 import org.apache.commons.logging.LogFactory;
 22  
 
 23  
 import com.buckosoft.PicMan.business.contact.ContactEngine;
 24  
 import com.buckosoft.PicMan.domain.Chain;
 25  
 import com.buckosoft.PicMan.domain.ContactParams;
 26  
 import com.buckosoft.PicMan.domain.Filter;
 27  
 import com.buckosoft.PicMan.domain.FilterMicroSet;
 28  
 import com.buckosoft.PicMan.domain.JobLogEntry;
 29  
 import com.buckosoft.PicMan.domain.MetaSet;
 30  
 import com.buckosoft.PicMan.domain.MetaSetRule;
 31  
 import com.buckosoft.PicMan.domain.Pic;
 32  
 import com.buckosoft.PicMan.domain.PosterParams;
 33  
 import com.buckosoft.PicMan.domain.Set;
 34  
 import com.buckosoft.PicMan.domain.SetSize;
 35  
 import com.buckosoft.PicMan.domain.System;
 36  
 
 37  
 /**
 38  
  * Contact Manager.  Decide when and what contact sheets to make.
 39  
  * Singleton ContactManager gets invoked  
 40  
  * @author Dick Balaska
 41  
  * @since 2005/08/06
 42  
  * @see <a href="http://cvs.buckosoft.com/Projects/PicMan/PicMan/src/main/java/com/buckosoft/PicMan/business/ContactManager.java">ContactManager.java</a>
 43  
  */
 44  0
 public class ContactManager implements SetChangedListener {
 45  
 
 46  0
         private static boolean DEBUG = false;
 47  
         private static final boolean DEBUGENTRY = false;
 48  
         private static final boolean DEBUGSPIN = false;
 49  
 
 50  0
         protected final Log logger = LogFactory.getLog(getClass());
 51  
         
 52  
         // Debugging tools (manipulate the run)
 53  
 //        private static final boolean runNone        = false;
 54  
 //        private static final boolean runOnce        = false;
 55  
         private static final boolean onePicOnly        = false;
 56  
 
 57  
         private        PicManFacade        pmf;
 58  
 
 59  0
         private        LinkedList<ContactParams>                contactList = new LinkedList<ContactParams>();
 60  0
         private        LinkedList<ContactParams>                spinList = new LinkedList<ContactParams>();
 61  
         private        String                        contactRunning;
 62  0
         private        boolean                        abortRequest = false;
 63  
         
 64  
         private        List<String>        cachedPicNames;
 65  
         private        ContactParams        cachedContactParams;
 66  
 
 67  0
         private        ReentrantLock cpLock = new ReentrantLock();
 68  
         private        ContactParams        currentContactParams;
 69  
         
 70  
         public        void setPicMan(PicManFacade pmf) {
 71  0
                 this.pmf = pmf;
 72  0
                 pmf.addSetChangedListener(this);
 73  0
         }
 74  
 
 75  
         /**
 76  
          * @return the contactRunning
 77  
          */
 78  
         public String getContactRunning() {
 79  0
                 return contactRunning;
 80  
         }
 81  
 
 82  
         public        boolean        makeContacts() throws Exception {
 83  
                 try {
 84  0
                         contactList = determineContactsToMake();
 85  0
                 } catch (Exception e) {
 86  
                         // exitRun();
 87  0
                         throw e;
 88  0
                 }
 89  0
                 boolean workDone = false;
 90  
                 if (DEBUGENTRY)
 91  
                         logger.info("process contacts: " + contactList.size());
 92  0
                 Iterator<ContactParams> it = contactList.iterator();
 93  0
                 if (it.hasNext()) {
 94  
 //                        contactMaker = new ContactMaker();
 95  
 //                        contactMaker.setPicMan(pmf);
 96  
 //                        contactMaker.setContactManager(this);
 97  0
                         workDone = true;
 98  
                 }
 99  
                 try {
 100  0
                         JobLogEntry jle = null;
 101  0
                         while (it.hasNext()) {
 102  0
                                 ContactParams cp = (ContactParams)it.next();
 103  0
                                 setContactParamsRunning(cp);
 104  0
                                 contactRunning = cp.getUuid();
 105  
                                 
 106  0
                                 if (!pmf.getDB().getSystem().isJobLogSummaryOnly() || cp.getContactNumber() == 0) {
 107  0
                                         if (DEBUG)
 108  0
                                                 logger.debug("Start log entry for " + cp.getContactNumber());
 109  0
                                         jle = new JobLogEntry();
 110  
                                         //jle.setChainId(cp.getCid());
 111  0
                                         jle.setNote(pmf.getDB().getChain(cp.getCid()).getName());
 112  0
                                         if (!pmf.getDB().getSystem().isJobLogSummaryOnly())
 113  0
                                                 jle.setName(cp.getUuid());
 114  
                                         else
 115  0
                                                 jle.setName(cp.getUid());
 116  0
                                         jle.setType(JobLogEntry.CONTACT);
 117  0
                                         pmf.addJobToLog(jle);
 118  
                                 }
 119  0
                                 ContactEngine        contactEngine = null;
 120  0
                                 String        engineName = cp.getEngineName();
 121  0
                                 if (cp instanceof PosterParams) {
 122  
                                         try {
 123  0
                                                 contactEngine = (ContactEngine)Class.forName("com.buckosoft.PicMan.business.contact.PosterEngine").newInstance();
 124  0
                                         } catch (Exception e) {
 125  0
                                                 Exception ex = new Exception("Can't instantiate Poster Engine: ", e);
 126  0
                                                 pmf.addError(ex);
 127  0
                                         }
 128  
                                         
 129  
                                 }
 130  
                                 try {
 131  0
                                         if (contactEngine == null)
 132  0
                                                 contactEngine = (ContactEngine)Class.forName("com.buckosoft.PicMan.business.contact.engine." + engineName).newInstance();
 133  0
                                 } catch (Exception e) {
 134  0
                                         Exception ex = new Exception("Can't instantiate Contact Engine: " + engineName, e);
 135  0
                                         pmf.addError(ex);
 136  0
                                 }
 137  0
                                 boolean ret = false;
 138  0
                                 if (contactEngine != null) {
 139  0
                                         contactEngine.setPicMan(pmf);
 140  0
                                         contactEngine.setContactManager(this);
 141  0
                                         ret = contactEngine.makeContact(cp);
 142  
                                 }
 143  0
                                 if (isAbort())
 144  0
                                         jle.setNote("*" + jle.getNote());
 145  0
                                 if (ret == false) {
 146  0
                                         jle.setError();
 147  0
                                         jle.setEndTime();
 148  0
                                         pmf.addJobToLog(jle);
 149  
                                 }
 150  0
                                 if (!pmf.getDB().getSystem().isJobLogSummaryOnly() 
 151  0
                                                 || cp.getContactNumber() >= pmf.getDB().getChain(cp.getCid()).getContactCount()-1
 152  
                                                 || cp instanceof PosterParams
 153  0
                                                 || isAbort()) {        // turned off by user
 154  0
                                         if (DEBUG)
 155  0
                                                 logger.debug("Finish log entry for " + cp.getContactNumber());
 156  0
                                         jle.setEndTime();
 157  0
                                         pmf.addJobToLog(jle);
 158  
                                 }
 159  0
                                 if (isAbort()) {
 160  0
                                         clearAbort();
 161  0
                                         setContactParamsRunning(null);
 162  0
                                         break;
 163  
                                 }
 164  0
                                 removeFromSpin(cp);
 165  0
                         }
 166  0
                 } catch (Exception e) {
 167  
                         //exitRun();
 168  0
                         throw e;
 169  0
                 }
 170  0
                 return(workDone);
 171  
         }
 172  
 
 173  
         
 174  
         private        void setContactParamsRunning(ContactParams cp) {
 175  0
                 cpLock.lock();
 176  
                 try {
 177  0
                         currentContactParams = cp;
 178  
                 } finally {
 179  0
                         cpLock.unlock();
 180  0
                 }
 181  0
         }
 182  
 
 183  
         public ContactParams getContactParamsRunning() {
 184  
                 ContactParams cp;
 185  0
                 cpLock.lock();
 186  
                 try {
 187  0
                         cp = currentContactParams;
 188  
                 } finally {
 189  0
                         cpLock.unlock();
 190  0
                 }
 191  0
                 return(cp);
 192  
         }
 193  
         /** Should we abort the current operation?
 194  
          * First check if the engines were turned off.
 195  
          * Then check if there is an abortRequest.  If there is, clear it and return true.
 196  
          * @return Are we aborting?
 197  
          */
 198  
         public boolean isAbort() {
 199  0
                 if (!pmf.getDB().getSystem().isEngineOn())
 200  0
                         return(true);
 201  0
                 if (!this.abortRequest)
 202  0
                         return(false);
 203  0
                 return(true);
 204  
         }
 205  
 
 206  
         private void clearAbort() {
 207  0
                 this.abortRequest = false;
 208  0
         }
 209  
 
 210  
         /** If we happen to be building contacts for the set that changed, then kill it, because it
 211  
          * has to be started over anyway.
 212  
          * @see com.buckosoft.PicMan.business.SetChangedListener#onSetChanged(com.buckosoft.PicMan.domain.SetSize)
 213  
          */
 214  
         @Override
 215  
         public void onSetChanged(SetSize ss) {
 216  0
                 cpLock.lock();
 217  
                 try {
 218  0
                         if (currentContactParams != null 
 219  0
                                         && ss.getSize() == currentContactParams.getSize() 
 220  0
                                         && ss.getSetName().equals(currentContactParams.getSetName())) {
 221  0
                                 this.abortRequest = true;
 222  0
                                 logger.info("onSetChanged: aborting build of " + ss.getSetSize());
 223  
                         }
 224  
                 } finally {
 225  0
                         cpLock.unlock();
 226  0
                 }
 227  0
         }
 228  
         
 229  
         
 230  
         /** Build a list of Contacts that need to be run
 231  
          * 
 232  
          * @return the list
 233  
          */
 234  
         public         LinkedList<ContactParams>        determineContactsToMake() {
 235  0
                 LinkedList<ContactParams> theList = new LinkedList<ContactParams>();
 236  0
                 theList.clear();
 237  0
                 List<Chain>        chains = pmf.getDB().getChains();
 238  
 //                List        sets = pmf.getSets();
 239  
 //                List        sizes = pmf.getSizes();
 240  
 //                Iterator it = sets.iterator();
 241  0
                 HashMap<String, Date>                filterAgeMap = pmf.getDB().getSetTimestamps();
 242  0
                 Iterator<Chain>        iter = chains.iterator();
 243  0
                 while (iter.hasNext()) {
 244  0
                         Chain chain = (Chain)iter.next();
 245  0
                         if (!chain.isActive())
 246  0
                                 continue;
 247  0
                         int                contactsPerSet = chain.getContactCount();
 248  0
                         HashMap<String, Date>                contactAgeMap = pmf.getDB().getContactOldestMap(chain);
 249  
 //                        Set set = (Set)it.next();
 250  
 //                        String        cSet = set.getName();
 251  
 //                        Iterator is = sizes.iterator();
 252  0
                         Iterator<SetSize> iss = chain.getSetSizes().iterator();
 253  0
                         while (iss.hasNext()) {
 254  0
                                 SetSize ss = (SetSize)iss.next();
 255  
                                 //int size = ((Integer)is.next()).intValue();
 256  
 
 257  0
                                 if (!isSpin(chain.getCid(), ss.getSetName(), ss.getSize(), -1)) {        // isSpin doesn't do the tests and goes straight to build
 258  0
                                         Date fdate = (Date)filterAgeMap.get(ss.getSetSize());
 259  0
                                         Date cdate = (Date)contactAgeMap.get(ss.getGuiSetSize());
 260  0
                                         if (DEBUG)
 261  0
                                                 logger.debug("Comparing: " + System.getUuid(ss.getSetName(), ss.getSize()) + " f:" + fdate + " c: " + cdate);
 262  0
                                         Date fdateWild = (Date)filterAgeMap.get(ss.getSetName());
 263  0
                                         if (fdateWild != null) {
 264  0
                                                 if (cdate != null) {
 265  0
                                                         if (fdateWild.after(cdate))         {        // we have a wild card match.
 266  0
                                                                 fdate = null;                        // null out fdate so we fall through and build
 267  0
                                                                 cdate = null;
 268  
                                                         }
 269  
                                                 }
 270  
                                         }
 271  0
                                         if (fdate != null) {
 272  0
                                                 if (cdate != null) {
 273  0
                                                         if (DEBUG)
 274  0
                                                                 logger.debug("class: f=" + fdate.getClass() + " c=" + cdate.getClass());
 275  0
                                                         if (fdate.before(cdate))
 276  0
                                                                 continue;
 277  
                                                 }
 278  
                                         } else {                        // no filter date, assume old
 279  0
                                                 if (cdate != null)        // if there's a contact 
 280  0
                                                         continue;        // then don't rebuild it
 281  
                                         }
 282  0
                                         if (DEBUG)
 283  0
                                                 logger.debug("Building set:  "  + ss.getSetSize());
 284  
                                 }
 285  0
                                 for (int i=0; i<contactsPerSet; i++) {
 286  0
                                         ContactParams cp = new ContactParams();
 287  0
                                         cp.setContactNumber(i);
 288  0
                                         cp.setCid(chain.getCid());
 289  0
                                         cp.setSetSize(ss);
 290  0
                                         cp.setRankMinMax(chain.getRatingMin(), chain.getRatingMax());
 291  0
                                         cp.setEngineName(chain.getEngine());
 292  
                                         if (onePicOnly) {
 293  
                                                 cp.setSize(300);
 294  
                                                 cp.setSetName("X");
 295  
                                         }
 296  0
                                         File dir = new File(chain.getContactDirectory() + File.separator + ss.getSetName());
 297  
                                         //logger.debug("try dir '" + dir.getPath() + "'");
 298  
                                         try {
 299  0
                                                 if (!dir.isDirectory())
 300  0
                                                         dir = dir.getParentFile();
 301  0
                                         } catch (Exception e) {
 302  0
                                                 dir = dir.getParentFile();
 303  0
                                         }
 304  
                                         //logger.debug("got dir '" + dir.getPath() + "'");
 305  0
                                         cp.setOutputDirectory(dir.getPath());
 306  0
                                         theList.add(cp);
 307  
                                         if (onePicOnly)
 308  
                                                 return(theList);
 309  
                                 }
 310  0
                         }
 311  0
                 }
 312  0
                 for (ContactParams cp : spinList) {
 313  0
                         if (cp instanceof PosterParams)
 314  0
                                 theList.add(cp);
 315  0
                 }
 316  0
                 return(theList);
 317  
         }
 318  
         
 319  
         public List<String> getPicNames(ContactParams cp) {
 320  0
                 if (cachedContactParams != null) {
 321  0
                         if (cp.equalsPics(cachedContactParams)) {
 322  0
                                 ArrayList<String>        al = new ArrayList<String>(cachedPicNames);
 323  0
                                 return(al);
 324  
                         }
 325  
                 }
 326  0
                 cachedPicNames = pmf.getDB().getPicNamesBySet(cp.getSetName(), cp.getSize());
 327  
 //                cachedPicNames = setupPicsList(cp, cachedPicNames);                        // XXX: Is this neccessary? It slowly prunes an already pruned list.
 328  0
                 cachedContactParams = cp;
 329  0
                 ArrayList<String>        al = new ArrayList<String>(cachedPicNames);
 330  0
                 return(al);
 331  
         }
 332  
         
 333  
         protected        List<String>        setupPicsList(ContactParams cp, List<String> picNames) {
 334  
 //                if (cp.getType() == ContactParams.TYPE_SEQUENTIAL)
 335  
 //                        return(f);
 336  0
                 ArrayList<String>        al = new ArrayList<String>(picNames);
 337  0
                 Iterator<String> iter = al.iterator();
 338  0
                 while (iter.hasNext()) {
 339  0
                         String picName = iter.next();
 340  0
                         if (isFilteredOut(cp, picName))
 341  0
                                 iter.remove();
 342  0
                 }
 343  0
                 return(al);
 344  
         }
 345  
         protected boolean isFilteredOut(ContactParams cp, String picName) {
 346  0
                 Filter f = pmf.getDB().getFilter(picName);
 347  0
                 double rating = 9;
 348  0
                 Set set = pmf.getDB().getSet(cp.getSetName());
 349  0
                 if (set.isMetaSet()) {
 350  
                         // XXX: THIS NEEDS FIXING
 351  
                         // XXX: THIS NEEDS FIXING
 352  
                         // XXX: THIS NEEDS FIXING
 353  
                         /* XXX: Still needs fixing.  There are actually two types (sigh) of MetaSet. MD is M+D/2. mlbXall is G|M|PG|R|XO|XX.  Any 7 should pass the large test.
 354  
                          * Ah.  The difference is as stated. M&D is different than G|M|PG|R|XO|XX
 355  
                          */
 356  0
                         rating = pmf.getDB().getPicRate(picName, set, cp.getSize());
 357  0
                         boolean nono = false;
 358  0
                         if (nono) {
 359  0
                                 MetaSet ms = pmf.getDB().getMetaSet(set.getSid());
 360  0
                                 List<MetaSetRule> msrList = ms.getRules();
 361  0
                                 Iterator<MetaSetRule> msrIter = msrList.iterator();
 362  0
                                 int        count = 0;
 363  0
                                 while (msrIter.hasNext()) {
 364  
                                         //MetaSetRule msr = msrIter.next();
 365  
                                         //if (msr.)
 366  0
                                         rating *= count;
 367  0
                                         int prate = f.getFilter(cp.getSetName(), cp.getSize());
 368  0
                                         rating += prate;
 369  0
                                         count++;
 370  0
                                         rating /= count;
 371  0
                                 }
 372  
                         }
 373  0
                 } else if (set.isMicroSet() || set.isNanoSet()) {
 374  0
                         Pic pic = pmf.getDB().getPic(picName);
 375  0
                         FilterMicroSet fms = pmf.getDB().getPicFromFilterMicroSet(pic.getPid(), set.getSid());
 376  0
                         if (fms != null)
 377  0
                                 rating = fms.getValue();
 378  
                         else
 379  0
                                 rating = 0;
 380  0
                 } else {
 381  0
                         rating = f.getFilter(cp.getSetName(), cp.getSize());
 382  
                 }
 383  0
                 logger.debug("isFilteredOut: " + picName + " " + rating);
 384  0
                 if (rating < cp.getRankMin()) 
 385  0
                         return(true);
 386  0
                 if (cp.getRankMax() == 9)        // passes the min test, no max. (hack to allow obsolete 10s from the database)
 387  0
                         return(false); 
 388  0
                 if (rating > cp.getRankMax())
 389  0
                         return(true);
 390  0
                 return(false);
 391  
         }
 392  
 
 393  
         
 394  
         /** Add a list to the contacts to spin (remake)
 395  
          * @param list A List of ContactParams to remake
 396  
          */
 397  
 
 398  
         public        void        addSpin(List<ContactParams> list) {
 399  0
                 Iterator<ContactParams> iter = list.iterator();
 400  0
                 while (iter.hasNext()) {
 401  0
                         ContactParams cp = iter.next();
 402  
                         if (DEBUGSPIN)
 403  
                                 logger.info("addSpin: cp cid=" + cp.getCid() + " ss= " + cp.getSetName() + "_" + cp.getSize() + " cn=" + cp.getContactNumber());
 404  0
                         if (!isOnList(spinList, cp)) {
 405  0
                                 spinList.add(cp);
 406  
                         }
 407  0
                 }
 408  0
         }
 409  
 
 410  
         private        boolean isOnList(List<ContactParams> list, ContactParams cp) {
 411  0
                 Iterator<ContactParams> iter = list.iterator();
 412  0
                 while (iter.hasNext()) {
 413  0
                         ContactParams cpl = iter.next();
 414  0
                         if (cpl.equals(cp))
 415  0
                                 return(true);
 416  0
                 }
 417  0
                 return(false);
 418  
         }
 419  
         /** Is this contact specififed on the spin list?
 420  
          * @param cid The chainId
 421  
          * @param setName The setName
 422  
          * @param size The size
 423  
          * @param contactNumber The contact sequence number
 424  
          * @return true if this is a user specified spin request (on the spin list)
 425  
          */
 426  
         private        boolean        isSpin(int cid, String setName, int size, int contactNumber) {
 427  0
                 Iterator<ContactParams> iter = spinList.iterator();
 428  0
                 ContactParams cp = new ContactParams(cid, setName, size, contactNumber);
 429  0
                 while (iter.hasNext()) {
 430  0
                         ContactParams cpl = iter.next();
 431  0
                         if (cpl.equals(cp))
 432  0
                                 return(true);
 433  0
                 }
 434  0
                 return(false);
 435  
         }
 436  
         private        void        removeFromSpin(ContactParams cp) {
 437  
                 if (DEBUGSPIN)
 438  
                         logger.info("removeFromSpin: cp cid=" + cp.getCid() + " ss= " + cp.getSetName() + "_" + cp.getSize() + " cn=" + cp.getContactNumber());
 439  0
                 Iterator<ContactParams> iter = spinList.iterator();
 440  0
                 while (iter.hasNext()) {
 441  0
                         ContactParams cpl = iter.next();
 442  0
                         if (cpl.equals(cp)) {
 443  0
                                 spinList.remove(cpl);
 444  0
                                 return;
 445  
                         }        
 446  0
                 }
 447  0
         }
 448  
 }