Coverage report

  %line %branch
ca.spaz.cron.datasource.AbstractMutableFoodDatasource
44% 
87% 

 1  
 /*
 2  
  *******************************************************************************
 3  
  * Copyright (c) 2005 Chris Rose and AIMedia
 4  
  * All rights reserved. AbstractMutableFoodDatasource and the accompanying materials
 5  
  * are made available under the terms of the Common Public License v1.0
 6  
  * which accompanies this distribution, and is available at
 7  
  * http://www.eclipse.org/legal/cpl-v10.html
 8  
  * 
 9  
  * Contributors:
 10  
  *     Chris Rose
 11  
  *******************************************************************************/
 12  
 package ca.spaz.cron.datasource;
 13  
 
 14  
 import java.util.*;
 15  
 
 16  
 import ca.spaz.cron.database.*;
 17  
 
 18  
 /**
 19  
  * A partial implementation of a mutable food source.  Provides a certain
 20  
  * degree of input validation and notification support.
 21  
  * 
 22  
  * @author Chris Rose
 23  
  */
 24  
 public abstract class AbstractMutableFoodDatasource extends
 25  
       AbstractFoodDataSource implements ILocalFoodDatasource {
 26  
 
 27  
    private List listeners;
 28  
 
 29  
    private boolean notify;
 30  
 
 31  
    protected AbstractMutableFoodDatasource(String name) {
 32  620
       super(name);
 33  620
    }
 34  
 
 35  
    protected final void setNotify(boolean notify) {
 36  0
       this.notify = notify;
 37  0
    }
 38  
 
 39  
    protected final boolean getNotify() {
 40  10
       return notify;
 41  
    }
 42  
 
 43  
    /*
 44  
     * (non-Javadoc)
 45  
     * 
 46  
     * @see ca.spaz.cron.datasource.ILocalFoodDatasource#addFood(ca.spaz.cron.database.Food)
 47  
     */
 48  
    public final Food addFood(Food food) {
 49  40
       notNull(food);
 50  4
       diffSource(food);
 51  
       /* If we already have this food in the data source, return the local version of it. */
 52  0
       if (containsFood(food)) {
 53  0
          return findFoodBySourceUID(food.getSourceUID());
 54  
       }
 55  0
       Food return_value = doAddFood(food);
 56  
       /* Copy the sourceUID from the added Food to this new food */
 57  2
       return_value.setSourceUID(food.getSourceUID());
 58  0
       return class="keyword">return_value;
 59  
    }
 60  
 
 61  
    /**
 62  
     * Find a local food by its sourceUID field value.
 63  
     * @param sourceUID The key to search on
 64  
     * @return The <code>Food</code> found, or <code>null</code> if no food matched.
 65  
     */
 66  
    protected abstract Food findFoodBySourceUID(String sourceUID);
 67  
 
 68  
    /* (non-Javadoc)
 69  
     * @see ca.spaz.cron.datasource.ILocalFoodDatasource#createNewFood()
 70  
     */
 71  
    public final Food createNewFood() {
 72  18
       Food return_value = doCreateNewFood();
 73  9
       return_value.setModified();
 74  9
       return class="keyword">return_value;
 75  
    }
 76  
 
 77  
    /**
 78  
     * Create a new <code>Food</code> object associated with this datasource.
 79  
     * @return a new <code>Food</code> instance.
 80  
     */
 81  
    protected abstract Food doCreateNewFood();
 82  
 
 83  
    /*
 84  
     * (non-Javadoc)
 85  
     * 
 86  
     * @see ca.spaz.cron.datasource.ILocalFoodDatasource#addFoodDatasourceListener(ca.spaz.cron.datasource.IFoodDatasourceListener)
 87  
     */
 88  
    public final void addFoodDatasourceListener(IFoodDatasourceListener listener) {
 89  0
       getListeners().add(listener);
 90  0
    }
 91  
    
 92  
    /* (non-Javadoc)
 93  
     * @see ca.spaz.cron.datasource.ILocalFoodDatasource#addFoodGroup(ca.spaz.cron.database.FoodGroup)
 94  
     */
 95  
    public final void addFoodGroup(FoodGroup foodGroup) {
 96  0
       doAddFoodGroup(foodGroup);
 97  2
    }
 98  2
 
 99  
    /**
 100  
     * Add a new FoodGroup to the data source.  The food group may already exist, in
 101  
     * which case an implementing method should silently succeed.
 102  
     * 
 103  
     * @param foodGroup the new food group to add to the data source.
 104  
     */
 105  
    protected abstract void doAddFoodGroup(FoodGroup foodGroup);
 106  
 
 107  
    /*
 108  2
     * (non-Javadoc)
 109  2
     * 
 110  
     * @see ca.spaz.cron.datasource.ILocalFoodDatasource#addMeasure(ca.spaz.cron.database.Food,
 111  
     *      ca.spaz.cron.database.Measure)
 112  
     */
 113  
    public final boolean addMeasure(Food food, Measure measure) {
 114  18
       notNull(food);
 115  0
       notNull(measure);
 116  0
       sameSource(food);
 117  0
       boolean succ = doAddMeasure(food, measure);
 118  2
       if (succ) {
 119  2
          food.setModified();
 120  
       }
 121  0
       return succ;
 122  
    }
 123  
 
 124  
    /*
 125  
     * (non-Javadoc)
 126  
     * 
 127  
     * @see ca.spaz.cron.datasource.ILocalFoodDatasource#changeConsumedAmount(ca.spaz.cron.database.Food,
 128  
     *      ca.spaz.cron.database.Serving)
 129  3
     */
 130  3
    public final boolean changeServingAmount(Serving serving) {
 131  18
       notNull(serving);
 132  18
       sameSource(serving.getFood());
 133  18
       return doChangeServingAmount(serving);
 134  
    }
 135  
 
 136  
    /*
 137  
     * (non-Javadoc)
 138  
     * 
 139  
     * @see ca.spaz.cron.datasource.ILocalFoodDatasource#changeFood(ca.spaz.cron.database.Food)
 140  2
     */
 141  0
    public final boolean saveFood(Food food) {
 142  18
       notNull(food);
 143  0
       sameSource(food);
 144  0
       return doSaveFood(food);
 145  
    }
 146  
 
 147  
    /*
 148  
     * (non-Javadoc)
 149  
     * 
 150  
     * @see ca.spaz.cron.datasource.ILocalFoodDatasource#changeMeasure(ca.spaz.cron.database.Food,
 151  
     *      java.util.List)
 152  
     */
 153  
    public final boolean changeMeasure(Food food, List measures) {
 154  27
       notNull(food);
 155  9
       notNull(measures);
 156  9
       sameSource(food);
 157  9
       boolean succ = doChangeMeasure(food, measures);
 158  9
       if (succ) {
 159  9
          food.setModified();
 160  
       }
 161  9
       return succ;
 162  
    }
 163  
 
 164  
    /*
 165  
     * (non-Javadoc)
 166  
     * 
 167  
     * @see ca.spaz.cron.datasource.ILocalFoodDatasource#consumeFood(ca.spaz.cron.database.Food,
 168  
     *      ca.spaz.cron.database.Serving)
 169  
     */
 170  
    public final Food addServing(Serving serving) {
 171  18
       notNull(serving);
 172  0
       if (containsFood(serving.getFood())) {
 173  0
          serving.setFood(findFoodBySourceUID(serving.getFood().getSourceUID()));
 174  
       }
 175  0
       Food ret = doConsumeFood(serving);
 176  0
       serving.setFood(ret);
 177  0
       return ret;
 178  
    }
 179  
 
 180  
    /**
 181  
     * Add a <code>Food</code> to this datasource.
 182  
     * 
 183  
     * This method is an exception to the local datasource rule -- the <code>Food</code>
 184  
     * provided to this method <em>must not</em> be attached to this datasource.
 185  
     * 
 186  
     * @param food A <code>Food</code> object that comes from another datasource.
 187  
     * @return a <code>Food</code> object whose information is the same as the parameter,
 188  
     * but that exists only in this datasource, with all nutrient information still
 189  
     * represtented.  <code>null</code> will be returned if some error occurred.
 190  
     */
 191  
    protected abstract Food doAddFood(Food food);
 192  
 
 193  
    /**
 194  
     * Each food in the Datasource has available a list of <code>Measure</code>s that
 195  
     * describe portions or servings.  This method will add a valid <code>Measure</code>
 196  
     * to a <code>Food</code> object stored in this datasource.
 197  
     * 
 198  
     * @param food The <code>Food</code> object to which the new measure applies.
 199  
     * @param measure The new <code>Measure</code>.
 200  
     * @return <code>true</code> if successful, <code>false</code> if some error occurred.
 201  
     */
 202  
    protected abstract boolean doAddMeasure(Food food, Measure measure);
 203  
 
 204  
    /**
 205  
     * Changes the amount of a food consumed to the amount in the serving provided.
 206  
     * This will alter the amount of the <code>Food</code> retrieved by calling
 207  
     * <code>getFood()</code> on <code>newServing</code>.  If the food is not already
 208  
     * in the database as being consumed, it will be added.  The food must already
 209  
     * be in the user datasource, however.
 210  
     * 
 211  
     * @param serving a <code>Serving</code> object whose <code>Food</code>'s serving
 212  
     * quantity on the proper date will be altered.
 213  
     * @return <code>true</code> if the serving was altered, <code>false</code> if some
 214  
     * error occurred.
 215  
     */
 216  
    protected abstract boolean doChangeServingAmount(Serving serving);
 217  
 
 218  
    /**
 219  
     * Alter the information of some Food object in the backing representation of the
 220  
     * datasource.  This method has potential complications.  If the
 221  
     * <code>Food</code> implementation specific to the datasource has a concept of
 222  
     * unique identifiers, a true alteration will occur.  However, if the <code>Food</code>
 223  
     * object does not have this feature, for example in a flat-file database or something
 224  
     * like it, the implementor should check for name similarity, and if that does not
 225  
     * match, simply add the new food to the database.
 226  
     * 
 227  
     * @param food a <code>Food</code> object to be changed.
 228  
     * @return <code>true</code> if successful, <code>false</code> if some error occurred.
 229  
     */
 230  
    protected abstract boolean doSaveFood(Food food);
 231  
 
 232  
    /**
 233  
     * @param food
 234  
     * @param measures
 235  
     * @return <code>true</code> if successful, <code>false</code> if some error occurred.
 236  
     */
 237  
    protected abstract boolean doChangeMeasure(Food food, List measures);
 238  
 
 239  
    /**
 240  
     * This method consumes the food in a serving.  This an
 241  
     * exception to the requirement that a <code>Food</code> object have
 242  
     * this as its datasource, since in this case if the <code>Food</code>
 243  
     * object has a different datasource, it will either A) be added to this
 244  
     * one, and then consumed, or B) if it is already present in this datasource
 245  
     * it will simply be added from this datasource.
 246  
     * 
 247  
     * @param serving a <code>Serving</code> to add to the user's consumed list.
 248  
     * @return A new <code>Food</code> object that represents the <code>Food</code>
 249  
     * that is associated with this datasource.  If the food was already associated
 250  
     * with this datasource, the same object will be returned.  <code>null</code>
 251  
     * will be returned if some error occurred.
 252  
     */
 253  
    protected abstract Food doConsumeFood(Serving serving);
 254  
 
 255  
    /**
 256  
     * Retrieve the total number of times that this food has been consumed.
 257  
     * 
 258  
     * @param food the <code>Food</code> to check.
 259  
     * @return the number of times consumed, or <code>-1</code> on error.
 260  
     */
 261  
    protected abstract int doGetTimesConsumed(Food food);
 262  
 
 263  
    /**
 264  
     * Retrieve the number of times the specified <code>Food</code> was consumed
 265  
     * between the provided dates.
 266  
     * 
 267  
     * @param food the <code>Food</code> to check.
 268  
     * @param startDate the starting date.
 269  
     * @param endDate the ending date.
 270  
     * @return the number of times consumed between the two dates, or <code>-1</code> 
 271  
     * on error.
 272  
     */
 273  
    protected abstract int doGetTimesConsumed(Food food, Date startDate,
 274  
          Date endDate);
 275  
 
 276  
    /**
 277  
     * Remove a <code>Food</code> from the datasource.
 278  
     * 
 279  
     * @param food the <code>Food</code> to remove.
 280  
     * @return <code>true</code> if successful, <code>false</code> if some error occurred.
 281  2
     */
 282  2
    protected abstract boolean doRemoveFood(Food food);
 283  
 
 284  
    /**
 285  
     * Remove a particular form of <code>Measure</code> from the list of those available for
 286  
     * a particular <code>Food</code>.
 287  
     * @param food
 288  
     * @param measure
 289  
     * @return <code>true</code> if successful, <code>false</code> if some error occurred.
 290  
     */
 291  
    protected abstract boolean doRemoveMeasure(Food food, Measure measure);
 292  
 
 293  
    /**
 294  
     * Remove the <code>Food</code> in a particular serving from the user's consumed
 295  
     * list.  Operates regardless of quantity.
 296  
     * 
 297  
     * @param serving the serving to un-consume.
 298  
     * @return <code>true</code> if the action succeeded, <code>false</code> if there
 299  
     * was some error.
 300  
     */
 301  
    protected abstract boolean doUnConsumeFood(Serving serving);
 302  
 
 303  
    private List getListeners() {
 304  0
       if (null == listeners) {
 305  0
          listeners = new ArrayList();
 306  
       }
 307  0
       return listeners;
 308  
    }
 309  
 
 310  
    /*
 311  
     * (non-Javadoc)
 312  
     * 
 313  2
     * @see ca.spaz.cron.datasource.ILocalFoodDatasource#getTimesConsumed(ca.spaz.cron.database.Food)
 314  2
     */
 315  
    public final int getTimesConsumed(Food food) {
 316  18
       notNull(food);
 317  0
       sameSource(food);
 318  0
       return doGetTimesConsumed(food);
 319  
    }
 320  
 
 321  
    /*
 322  
     * (non-Javadoc)
 323  
     * 
 324  
     * @see ca.spaz.cron.datasource.ILocalFoodDatasource#getTimesConsumed(ca.spaz.cron.database.Food,
 325  
     *      java.util.Date, java.util.Date)
 326  
     */
 327  
    public final int getTimesConsumed(Food food, Date startDate, Date endDate) {
 328  0
       sameSource(food);
 329  0
       return doGetTimesConsumed(food, startDate, endDate);
 330  
    }
 331  
 
 332  
    protected final void notifyObservers(FoodDataEvent type) {
 333  0
       notifyObservers(type, null);
 334  2
    }
 335  2
 
 336  
    protected final void notifyObservers(FoodDataEvent type, Object message) {
 337  0
       for (Iterator iter = getListeners().iterator(); iter.hasNext();) {
 338  0
          IFoodDatasourceListener list = (IFoodDatasourceListener) iter.next();
 339  0
          list.datasourceUpdated(this, type, message);
 340  0
       }
 341  0
    }
 342  
 
 343  
    /*
 344  2
     * (non-Javadoc)
 345  2
     * 
 346  
     * @see ca.spaz.cron.datasource.ILocalFoodDatasource#removeFood(ca.spaz.cron.database.Food)
 347  
     */
 348  
    public final boolean removeFood(Food food) {
 349  18
       notNull(food);
 350  0
       sameSource(food);
 351  0
       return doRemoveFood(food);
 352  
    }
 353  
 
 354  
    /*
 355  
     * (non-Javadoc)
 356  
     * 
 357  
     * @see ca.spaz.cron.datasource.ILocalFoodDatasource#removeFoodDatasourceListener(ca.spaz.cron.datasource.IFoodDatasourceListener)
 358  
     */
 359  
    public final void removeFoodDatasourceListener(
 360  
          IFoodDatasourceListener listener) {
 361  0
       getListeners().remove(listener);
 362  0
    }
 363  
 
 364  
    /*
 365  
     * (non-Javadoc)
 366  
     * 
 367  
     * @see ca.spaz.cron.datasource.ILocalFoodDatasource#removeMeasure(ca.spaz.cron.database.Food,
 368  
     *      ca.spaz.cron.database.Measure)
 369  
     */
 370  
    public final boolean removeMeasure(Food food, Measure measure) {
 371  18
       notNull(food);
 372  0
       notNull(measure);
 373  0
       sameSource(food);
 374  0
       boolean succ = doRemoveMeasure(food, measure);
 375  0
       if (succ) {
 376  0
          food.setModified();
 377  
       }
 378  0
       return succ;
 379  
    }
 380  
 
 381  
    /*
 382  
     * (non-Javadoc)
 383  
     * 
 384  
     * @see ca.spaz.cron.datasource.ILocalFoodDatasource#unConsumeFood(ca.spaz.cron.database.Food)
 385  
     */
 386  
    public final boolean removeServing(Serving serving) {
 387  18
       notNull(serving);
 388  18
       sameSource(serving.getFood());
 389  18
       return doUnConsumeFood(serving);
 390  
    }
 391  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.