You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mahout.apache.org by ro...@apache.org on 2010/02/13 21:54:31 UTC

svn commit: r909912 [5/10] - in /lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste: common/ eval/ hadoop/ hadoop/cooccurence/ hadoop/item/ hadoop/pseudo/ hadoop/slopeone/ impl/common/ impl/common/jdbc/ impl/eval/ impl/model/ impl/model/...

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/PlusAnonymousUserDataModel.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/PlusAnonymousUserDataModel.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/PlusAnonymousUserDataModel.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/PlusAnonymousUserDataModel.java Sat Feb 13 20:54:05 2010
@@ -17,6 +17,8 @@
 
 package org.apache.mahout.cf.taste.impl.model;
 
+import java.util.Collection;
+
 import org.apache.mahout.cf.taste.common.Refreshable;
 import org.apache.mahout.cf.taste.common.TasteException;
 import org.apache.mahout.cf.taste.impl.common.FastIDSet;
@@ -24,33 +26,40 @@
 import org.apache.mahout.cf.taste.model.DataModel;
 import org.apache.mahout.cf.taste.model.PreferenceArray;
 
-import java.util.Collection;
-
 /**
- * <p>This {@link DataModel} decorator class is useful in a situation where you wish to recommend
- * to a user that doesn't really exist yet in your actual {@link DataModel}. For example maybe you
- * wish to recommend DVDs to a user who has browsed a few titles on your DVD store site, but, the
- * user is not yet registered.</p>
- *
- * <p>This enables you to temporarily add a temporary user to an existing {@link DataModel} in a way
- * that recommenders can then produce recommendations anyway. To do so, wrap your real implementation
- * in this class:</p>
- *
- * <p><pre>
+ * <p>
+ * This {@link DataModel} decorator class is useful in a situation where you wish to recommend to a user that
+ * doesn't really exist yet in your actual {@link DataModel}. For example maybe you wish to recommend DVDs to
+ * a user who has browsed a few titles on your DVD store site, but, the user is not yet registered.
+ * </p>
+ * 
+ * <p>
+ * This enables you to temporarily add a temporary user to an existing {@link DataModel} in a way that
+ * recommenders can then produce recommendations anyway. To do so, wrap your real implementation in this
+ * class:
+ * </p>
+ * 
+ * <p>
+ * 
+ * <pre>
  * DataModel realModel = ...;
  * DataModel plusModel = new PlusAnonymousUserDataModel(realModel);
  * ...
  * ItemSimilarity similarity = new LogLikelihoodSimilarity(realModel); // not plusModel
- * </pre></p>
- *
- * <p>But, continue to use <code>realModel</code> as input to other components.
- * To recommend, first construct and
- * set the temporary user information on the model and then simply call the recommender.
- * The <code>synchronized</code> block exists to remind you that this is of course not
- * thread-safe. Only one set of temp data can be inserted into the model and used at one
- * time.</p>
- *
- * <p><pre>
+ * </pre>
+ * 
+ * </p>
+ * 
+ * <p>
+ * But, continue to use <code>realModel</code> as input to other components. To recommend, first construct and
+ * set the temporary user information on the model and then simply call the recommender. The
+ * <code>synchronized</code> block exists to remind you that this is of course not thread-safe. Only one set
+ * of temp data can be inserted into the model and used at one time.
+ * </p>
+ * 
+ * <p>
+ * 
+ * <pre>
  * Recommender recommender = ...;
  * ...
  * synchronized(...) {
@@ -58,21 +67,23 @@
  *   plusModel.setTempPrefs(tempPrefs);
  *   recommender.recommend(PlusAnonymousUserDataModel.TEMP_USER_ID, 10);
  * }
- * </pre></p>
+ * </pre>
+ * 
+ * </p>
  */
 public final class PlusAnonymousUserDataModel implements DataModel {
-
+  
   public static final long TEMP_USER_ID = Long.MIN_VALUE;
-
+  
   private final DataModel delegate;
   private PreferenceArray tempPrefs;
   private final FastIDSet prefItemIDs;
-
+  
   public PlusAnonymousUserDataModel(DataModel delegate) {
     this.delegate = delegate;
     this.prefItemIDs = new FastIDSet();
   }
-
+  
   public void setTempPrefs(PreferenceArray prefs) {
     this.tempPrefs = prefs;
     this.prefItemIDs.clear();
@@ -80,36 +91,37 @@
       this.prefItemIDs.add(prefs.getItemID(i));
     }
   }
-
+  
   @Override
   public LongPrimitiveIterator getUserIDs() throws TasteException {
-    return new PlusAnonymousUserLongPrimitiveIterator(delegate.getUserIDs(), TEMP_USER_ID);
+    return new PlusAnonymousUserLongPrimitiveIterator(delegate.getUserIDs(),
+        PlusAnonymousUserDataModel.TEMP_USER_ID);
   }
-
+  
   @Override
   public PreferenceArray getPreferencesFromUser(long userID) throws TasteException {
-    if (userID == TEMP_USER_ID) {
+    if (userID == PlusAnonymousUserDataModel.TEMP_USER_ID) {
       return tempPrefs;
     } else {
       return delegate.getPreferencesFromUser(userID);
     }
   }
-
+  
   @Override
   public FastIDSet getItemIDsFromUser(long userID) throws TasteException {
-    if (userID == TEMP_USER_ID) {
+    if (userID == PlusAnonymousUserDataModel.TEMP_USER_ID) {
       return prefItemIDs;
     } else {
       return delegate.getItemIDsFromUser(userID);
     }
   }
-
+  
   @Override
   public LongPrimitiveIterator getItemIDs() throws TasteException {
     return delegate.getItemIDs();
     // Yeah ignoring items that only the plus-one user knows about... can't really happen
   }
-
+  
   @Override
   public PreferenceArray getPreferencesForItem(long itemID) throws TasteException {
     PreferenceArray delegatePrefs = delegate.getPreferencesForItem(itemID);
@@ -131,10 +143,10 @@
     }
     return delegatePrefs;
   }
-
+  
   @Override
   public Float getPreferenceValue(long userID, long itemID) throws TasteException {
-    if (userID == TEMP_USER_ID) {
+    if (userID == PlusAnonymousUserDataModel.TEMP_USER_ID) {
       for (int i = 0; i < tempPrefs.length(); i++) {
         if (tempPrefs.getItemID(i) == itemID) {
           return tempPrefs.getValue(i);
@@ -145,17 +157,17 @@
       return delegate.getPreferenceValue(userID, itemID);
     }
   }
-
+  
   @Override
   public int getNumItems() throws TasteException {
     return delegate.getNumItems();
   }
-
+  
   @Override
   public int getNumUsers() throws TasteException {
     return delegate.getNumUsers() + 1;
   }
-
+  
   @Override
   public int getNumUsersWithPreferenceFor(long... itemIDs) throws TasteException {
     boolean hasAll = true;
@@ -174,29 +186,28 @@
     }
     return delegate.getNumUsersWithPreferenceFor(itemIDs) + (hasAll ? 1 : 0);
   }
-
+  
   @Override
   public void setPreference(long userID, long itemID, float value) throws TasteException {
-    if (userID == TEMP_USER_ID) {
+    if (userID == PlusAnonymousUserDataModel.TEMP_USER_ID) {
       throw new UnsupportedOperationException();
     } else {
       delegate.setPreference(userID, itemID, value);
     }
   }
-
+  
   @Override
   public void removePreference(long userID, long itemID) throws TasteException {
-    if (userID == TEMP_USER_ID) {
+    if (userID == PlusAnonymousUserDataModel.TEMP_USER_ID) {
       throw new UnsupportedOperationException();
     } else {
       delegate.removePreference(userID, itemID);
     }
   }
-
+  
   @Override
   public void refresh(Collection<Refreshable> alreadyRefreshed) {
     delegate.refresh(alreadyRefreshed);
   }
-
+  
 }
-

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/PlusAnonymousUserLongPrimitiveIterator.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/PlusAnonymousUserLongPrimitiveIterator.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/PlusAnonymousUserLongPrimitiveIterator.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/PlusAnonymousUserLongPrimitiveIterator.java Sat Feb 13 20:54:05 2010
@@ -17,21 +17,21 @@
 
 package org.apache.mahout.cf.taste.impl.model;
 
-import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
 import org.apache.mahout.cf.taste.impl.common.AbstractLongPrimitiveIterator;
+import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
 
 final class PlusAnonymousUserLongPrimitiveIterator extends AbstractLongPrimitiveIterator {
-
+  
   private final LongPrimitiveIterator delegate;
   private final long extraDatum;
   private boolean datumConsumed;
-
+  
   PlusAnonymousUserLongPrimitiveIterator(LongPrimitiveIterator delegate, long extraDatum) {
     this.delegate = delegate;
     this.extraDatum = extraDatum;
     datumConsumed = false;
   }
-
+  
   @Override
   public long nextLong() {
     if (datumConsumed) {
@@ -51,7 +51,7 @@
       }
     }
   }
-
+  
   @Override
   public long peek() {
     if (datumConsumed) {
@@ -69,22 +69,22 @@
       }
     }
   }
-
+  
   @Override
   public boolean hasNext() {
     return !datumConsumed || delegate.hasNext();
   }
-
+  
   @Override
   public void remove() {
     throw new UnsupportedOperationException();
   }
-
+  
   @Override
   public void skip(int n) {
     for (int i = 0; i < n; i++) {
       nextLong();
     }
   }
-
+  
 }

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/file/FileDataModel.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/file/FileDataModel.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/file/FileDataModel.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/file/FileDataModel.java Sat Feb 13 20:54:05 2010
@@ -17,77 +17,97 @@
 
 package org.apache.mahout.cf.taste.impl.model.file;
 
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.ReentrantLock;
+
 import org.apache.mahout.cf.taste.common.Refreshable;
 import org.apache.mahout.cf.taste.common.TasteException;
 import org.apache.mahout.cf.taste.impl.common.FastByIDMap;
 import org.apache.mahout.cf.taste.impl.common.FastIDSet;
-import org.apache.mahout.cf.taste.impl.model.GenericUserPreferenceArray;
-import org.apache.mahout.common.FileLineIterator;
 import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
 import org.apache.mahout.cf.taste.impl.model.GenericBooleanPrefDataModel;
 import org.apache.mahout.cf.taste.impl.model.GenericDataModel;
 import org.apache.mahout.cf.taste.impl.model.GenericPreference;
+import org.apache.mahout.cf.taste.impl.model.GenericUserPreferenceArray;
 import org.apache.mahout.cf.taste.model.DataModel;
 import org.apache.mahout.cf.taste.model.Preference;
 import org.apache.mahout.cf.taste.model.PreferenceArray;
+import org.apache.mahout.common.FileLineIterator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.locks.ReentrantLock;
-
 /**
- * <p>A {@link DataModel} backed by a comma-delimited file. This class typically expects a file where each line contains
- * a user ID, followed by item ID, followed by preferences value, separated by commas. You may also use tabs.</p>
- *
- * <p>The preference value is assumed to be parseable as a <code>double</code>. The user IDs and item IDs are read
- * parsed as <code>long</code>s.</p>
- *
- * <p>This class will reload data from the data file when {@link #refresh(Collection)} is called, unless the file has
- * been reloaded very recently already.</p>
- *
- * <p>This class will also look for update "delta" files in the same directory, with file names that start the same way
- * (up to the first period). These files should have the same format, and provide updated data that supersedes what is
- * in the main data file. This is a mechanism that allows an application to push updates to {@link FileDataModel}
- * without re-copying the entire data file.</p>
- *
- * <p>The line may contain a blank preference value (e.g. "123,456,"). This is interpreted to mean "delete preference",
- * and is only useful in the context of an update delta file (see above). Note that if the line is empty or begins with
- * '#' it will be ignored as a comment.</p>
- *
- * <p>It is also acceptable for the lines to contain additional fields. Fields beyond the third will be ignored.</p>
- *
- * <p>Finally, for application that have no notion of a preference value (that is, the user simply expresses a
- * preference for an item, but no degree of preference), the caller can simply omit the third token in each line
- * altogether -- for example, "123,456".</p>
- *
- * <p>Note that it's all-or-nothing -- all of the items in the file must express no preference, or the all must.
- * These cannot be mixed. Put another way there will always be the same number of delimiters on every line of the
- * file!</p>
- *
- * <p>This class is not intended for use with very large amounts of data (over, say, tens of millions of rows). For
- * that, a JDBC-backed {@link DataModel} and a database are more appropriate.</p>
- *
- * <p>It is possible and likely useful to subclass this class and customize its behavior to accommodate
+ * <p>
+ * A {@link DataModel} backed by a comma-delimited file. This class typically expects a file where each line
+ * contains a user ID, followed by item ID, followed by preferences value, separated by commas. You may also
+ * use tabs.
+ * </p>
+ * 
+ * <p>
+ * The preference value is assumed to be parseable as a <code>double</code>. The user IDs and item IDs are
+ * read parsed as <code>long</code>s.
+ * </p>
+ * 
+ * <p>
+ * This class will reload data from the data file when {@link #refresh(Collection)} is called, unless the file
+ * has been reloaded very recently already.
+ * </p>
+ * 
+ * <p>
+ * This class will also look for update "delta" files in the same directory, with file names that start the
+ * same way (up to the first period). These files should have the same format, and provide updated data that
+ * supersedes what is in the main data file. This is a mechanism that allows an application to push updates to
+ * {@link FileDataModel} without re-copying the entire data file.
+ * </p>
+ * 
+ * <p>
+ * The line may contain a blank preference value (e.g. "123,456,"). This is interpreted to mean
+ * "delete preference", and is only useful in the context of an update delta file (see above). Note that if
+ * the line is empty or begins with '#' it will be ignored as a comment.
+ * </p>
+ * 
+ * <p>
+ * It is also acceptable for the lines to contain additional fields. Fields beyond the third will be ignored.
+ * </p>
+ * 
+ * <p>
+ * Finally, for application that have no notion of a preference value (that is, the user simply expresses a
+ * preference for an item, but no degree of preference), the caller can simply omit the third token in each
+ * line altogether -- for example, "123,456".
+ * </p>
+ * 
+ * <p>
+ * Note that it's all-or-nothing -- all of the items in the file must express no preference, or the all must.
+ * These cannot be mixed. Put another way there will always be the same number of delimiters on every line of
+ * the file!
+ * </p>
+ * 
+ * <p>
+ * This class is not intended for use with very large amounts of data (over, say, tens of millions of rows).
+ * For that, a JDBC-backed {@link DataModel} and a database are more appropriate.
+ * </p>
+ * 
+ * <p>
+ * It is possible and likely useful to subclass this class and customize its behavior to accommodate
  * application-specific needs and input formats. See {@link #processLine(String, FastByIDMap)} and
  * {@link #processLineWithoutID(String, FastByIDMap)}
  */
 public class FileDataModel implements DataModel {
-
+  
   private static final Logger log = LoggerFactory.getLogger(FileDataModel.class);
-
+  
   private static final long MIN_RELOAD_INTERVAL_MS = 60 * 1000L; // 1 minute?
   private static final char COMMENT_CHAR = '#';
-
+  
   private final File dataFile;
   private long lastModified;
   private long lastUpdateFileModified;
@@ -97,19 +117,23 @@
   private DataModel delegate;
   private final ReentrantLock reloadLock;
   private final boolean transpose;
-
+  
   /**
-   * @param dataFile file containing preferences data. If file is compressed (and name ends in .gz or .zip accordingly)
-   *                 it will be decompressed as it is read)
-   * @throws FileNotFoundException if dataFile does not exist
-   * @throws IOException if file can't be read
+   * @param dataFile
+   *          file containing preferences data. If file is compressed (and name ends in .gz or .zip
+   *          accordingly) it will be decompressed as it is read)
+   * @throws FileNotFoundException
+   *           if dataFile does not exist
+   * @throws IOException
+   *           if file can't be read
    */
   public FileDataModel(File dataFile) throws IOException {
     this(dataFile, false);
   }
-
+  
   /**
-   * @param transpose transposes user IDs and item IDs -- convenient for 'flipping' the data model this way
+   * @param transpose
+   *          transposes user IDs and item IDs -- convenient for 'flipping' the data model this way
    * @see #FileDataModel(File)
    */
   public FileDataModel(File dataFile, boolean transpose) throws IOException {
@@ -119,35 +143,35 @@
     if (!dataFile.exists() || dataFile.isDirectory()) {
       throw new FileNotFoundException(dataFile.toString());
     }
-
-    log.info("Creating FileDataModel for file {}", dataFile);
-
+    
+    FileDataModel.log.info("Creating FileDataModel for file {}", dataFile);
+    
     this.dataFile = dataFile.getAbsoluteFile();
     this.lastModified = dataFile.lastModified();
     this.lastUpdateFileModified = readLastUpdateFileModified();
-
+    
     FileLineIterator iterator = new FileLineIterator(dataFile, false);
     String firstLine = iterator.peek();
-    while (firstLine.length() == 0 || firstLine.charAt(0) == COMMENT_CHAR) {
+    while ((firstLine.length() == 0) || (firstLine.charAt(0) == FileDataModel.COMMENT_CHAR)) {
       iterator.next();
       firstLine = iterator.peek();
     }
     iterator.close();
-    delimiter = determineDelimiter(firstLine, 2);
+    delimiter = FileDataModel.determineDelimiter(firstLine, 2);
     hasPrefValues = firstLine.indexOf(delimiter, firstLine.indexOf(delimiter) + 1) >= 0;
-
+    
     this.reloadLock = new ReentrantLock();
     this.transpose = transpose;
   }
-
+  
   public File getDataFile() {
     return dataFile;
   }
-
+  
   public char getDelimiter() {
     return delimiter;
   }
-
+  
   protected void reload() {
     if (!reloadLock.isLocked()) {
       reloadLock.lock();
@@ -155,82 +179,84 @@
         delegate = buildModel();
         loaded = true;
       } catch (IOException ioe) {
-        log.warn("Exception while reloading", ioe);
+        FileDataModel.log.warn("Exception while reloading", ioe);
       } finally {
         reloadLock.unlock();
       }
     }
   }
-
+  
   protected DataModel buildModel() throws IOException {
-
+    
     long newLastModified = dataFile.lastModified();
     long newLastUpdateFileModified = readLastUpdateFileModified();
-
-    boolean loadFreshData = delegate == null || newLastModified > lastModified + MIN_RELOAD_INTERVAL_MS;
-
+    
+    boolean loadFreshData = (delegate == null)
+                            || (newLastModified > lastModified + FileDataModel.MIN_RELOAD_INTERVAL_MS);
+    
     lastModified = newLastModified;
     lastUpdateFileModified = newLastUpdateFileModified;
-
+    
     if (hasPrefValues) {
       
       if (loadFreshData) {
-
+        
         FastByIDMap<Collection<Preference>> data = new FastByIDMap<Collection<Preference>>();
         FileLineIterator iterator = new FileLineIterator(dataFile, false);
         processFile(iterator, data);
-
+        
         for (File updateFile : findUpdateFiles()) {
           processFile(new FileLineIterator(updateFile, false), data);
         }
-
+        
         return new GenericDataModel(GenericDataModel.toDataMap(data, true));
-
+        
       } else {
-
+        
         FastByIDMap<PreferenceArray> rawData = ((GenericDataModel) delegate).getRawUserData();
-
+        
         for (File updateFile : findUpdateFiles()) {
           processFile(new FileLineIterator(updateFile, false), rawData);
         }
-
+        
         return new GenericDataModel(rawData);
-
+        
       }
-
+      
     } else {
-
+      
       if (loadFreshData) {
-
+        
         FastByIDMap<FastIDSet> data = new FastByIDMap<FastIDSet>();
         FileLineIterator iterator = new FileLineIterator(dataFile, false);
         processFileWithoutID(iterator, data);
-
+        
         for (File updateFile : findUpdateFiles()) {
           processFileWithoutID(new FileLineIterator(updateFile, false), data);
         }
-
+        
         return new GenericBooleanPrefDataModel(data);
-
+        
       } else {
-
+        
         FastByIDMap<FastIDSet> rawData = ((GenericBooleanPrefDataModel) delegate).getRawUserData();
-
+        
         for (File updateFile : findUpdateFiles()) {
           processFileWithoutID(new FileLineIterator(updateFile, false), rawData);
         }
-
+        
         return new GenericBooleanPrefDataModel(rawData);
-
+        
       }
-
+      
     }
   }
-
+  
   /**
-   * Finds update delta files in the same directory as the data file. This finds any file whose name starts the same way
-   * as the data file (up to first period) but isn't the data file itself. For example, if the data file is
-   * /foo/data.txt.gz, you might place update files at /foo/data.1.txt.gz, /foo/data.2.txt.gz, etc.
+   * Finds update delta files in the same directory as the data file. This finds any file whose name starts
+   * the same way as the data file (up to first period) but isn't the data file itself. For example, if the
+   * data file is /foo/data.txt.gz, you might place update files at /foo/data.1.txt.gz, /foo/data.2.txt.gz,
+   * etc.
    */
   private Iterable<File> findUpdateFiles() {
     String dataFileName = dataFile.getName();
@@ -247,7 +273,7 @@
     Collections.sort(updateFiles);
     return updateFiles;
   }
-
+  
   private long readLastUpdateFileModified() {
     long mostRecentModification = Long.MIN_VALUE;
     for (File updateFile : findUpdateFiles()) {
@@ -255,7 +281,7 @@
     }
     return mostRecentModification;
   }
-
+  
   public static char determineDelimiter(String line, int maxDelimiters) {
     char delimiter;
     if (line.indexOf(',') >= 0) {
@@ -281,10 +307,9 @@
     }
     return delimiter;
   }
-
-  protected void processFile(FileLineIterator dataOrUpdateFileIterator,
-                             FastByIDMap<?> data) {
-    log.info("Reading file info...");
+  
+  protected void processFile(FileLineIterator dataOrUpdateFileIterator, FastByIDMap<?> data) {
+    FileDataModel.log.info("Reading file info...");
     AtomicInteger count = new AtomicInteger();
     while (dataOrUpdateFileIterator.hasNext()) {
       String line = dataOrUpdateFileIterator.next();
@@ -292,41 +317,48 @@
         processLine(line, data);
         int currentCount = count.incrementAndGet();
         if (currentCount % 1000000 == 0) {
-          log.info("Processed {} lines", currentCount);
+          FileDataModel.log.info("Processed {} lines", currentCount);
         }
       }
     }
-    log.info("Read lines: {}", count.get());
+    FileDataModel.log.info("Read lines: {}", count.get());
   }
-
+  
   /**
-   * <p>Reads one line from the input file and adds the data to a {@link Map} data structure which maps user IDs to
-   * preferences. This assumes that each line of the input file corresponds to one preference. After reading a line and
-   * determining which user and item the preference pertains to, the method should look to see if the data contains a
-   * mapping for the user ID already, and if not, add an empty {@link List} of {@link Preference}s to the data.</p>
-   *
-   * <p>Note that if the line is empty or begins with '#' it will be ignored as a comment.</p>
-   *
-   * @param line      line from input data file
-   * @param data      all data read so far, as a mapping from user IDs to preferences
+   * <p>
+   * Reads one line from the input file and adds the data to a {@link Map} data structure which maps user IDs
+   * to preferences. This assumes that each line of the input file corresponds to one preference. After
+   * reading a line and determining which user and item the preference pertains to, the method should look to
+   * see if the data contains a mapping for the user ID already, and if not, add an empty {@link List} of
+   * {@link Preference}s to the data.
+   * </p>
+   * 
+   * <p>
+   * Note that if the line is empty or begins with '#' it will be ignored as a comment.
+   * </p>
+   * 
+   * @param line
+   *          line from input data file
+   * @param data
+   *          all data read so far, as a mapping from user IDs to preferences
    */
   protected void processLine(String line, FastByIDMap<?> data) {
-
-    if (line.length() == 0 || line.charAt(0) == COMMENT_CHAR) {
+    
+    if ((line.length() == 0) || (line.charAt(0) == FileDataModel.COMMENT_CHAR)) {
       return;
     }
-
-    int delimiterOne = line.indexOf((int) delimiter);
+    
+    int delimiterOne = line.indexOf(delimiter);
     if (delimiterOne < 0) {
       throw new IllegalArgumentException("Bad line: " + line);
     }
-    int delimiterTwo = line.indexOf((int) delimiter, delimiterOne + 1);
+    int delimiterTwo = line.indexOf(delimiter, delimiterOne + 1);
     if (delimiterTwo < 0) {
       throw new IllegalArgumentException("Bad line: " + line);
     }
     // Look for beginning of additional, ignored fields:
-    int delimiterThree = line.indexOf((int) delimiter, delimiterTwo + 1);    
-
+    int delimiterThree = line.indexOf(delimiter, delimiterTwo + 1);
+    
     String userIDString = line.substring(0, delimiterOne);
     String itemIDString = line.substring(delimiterOne + 1, delimiterTwo);
     String preferenceValueString;
@@ -335,20 +367,20 @@
     } else {
       preferenceValueString = line.substring(delimiterTwo + 1);
     }
-
+    
     long userID = readUserIDFromString(userIDString);
     long itemID = readItemIDFromString(itemIDString);
-
+    
     if (transpose) {
       long tmp = userID;
       userID = itemID;
       itemID = tmp;
     }
-
+    
     // This is kind of gross but need to handle two types of storage
     Object maybePrefs = data.get(userID);
     if (maybePrefs instanceof PreferenceArray) {
-
+      
       PreferenceArray prefs = (PreferenceArray) maybePrefs;
       if (preferenceValueString.length() == 0) {
         if (prefs != null) {
@@ -375,11 +407,11 @@
             }
           }
         }
-
+        
       } else {
-
+        
         float preferenceValue = Float.parseFloat(preferenceValueString);
-
+        
         boolean exists = false;
         if (prefs != null) {
           for (int i = 0; i < prefs.length(); i++) {
@@ -390,7 +422,7 @@
             }
           }
         }
-
+        
         if (!exists) {
           if (prefs == null) {
             prefs = new GenericUserPreferenceArray(1);
@@ -406,11 +438,11 @@
           prefs.setValue(0, preferenceValue);
         }
       }
-
+      
     } else {
-
+      
       Collection<Preference> prefs = (Collection<Preference>) maybePrefs;
-
+      
       if (preferenceValueString.length() == 0) {
         if (prefs != null) {
           // remove pref
@@ -424,9 +456,9 @@
           }
         }
       } else {
-
+        
         float preferenceValue = Float.parseFloat(preferenceValueString);
-
+        
         boolean exists = false;
         if (prefs != null) {
           for (Preference pref : prefs) {
@@ -437,7 +469,7 @@
             }
           }
         }
-
+        
         if (!exists) {
           if (prefs == null) {
             prefs = new ArrayList<Preference>(2);
@@ -446,13 +478,12 @@
           prefs.add(new GenericPreference(userID, itemID, preferenceValue));
         }
       }
-
+      
     }
   }
-
-  protected void processFileWithoutID(FileLineIterator dataOrUpdateFileIterator,
-                                      FastByIDMap<FastIDSet> data) {
-    log.info("Reading file info...");
+  
+  protected void processFileWithoutID(FileLineIterator dataOrUpdateFileIterator, FastByIDMap<FastIDSet> data) {
+    FileDataModel.log.info("Reading file info...");
     AtomicInteger count = new AtomicInteger();
     while (dataOrUpdateFileIterator.hasNext()) {
       String line = dataOrUpdateFileIterator.next();
@@ -460,27 +491,27 @@
         processLineWithoutID(line, data);
         int currentCount = count.incrementAndGet();
         if (currentCount % 100000 == 0) {
-          log.info("Processed {} lines", currentCount);
+          FileDataModel.log.info("Processed {} lines", currentCount);
         }
       }
     }
-    log.info("Read lines: {}", count.get());
+    FileDataModel.log.info("Read lines: {}", count.get());
   }
-
+  
   protected void processLineWithoutID(String line, FastByIDMap<FastIDSet> data) {
-
-    if (line.length() == 0 || line.charAt(0) == COMMENT_CHAR) {
+    
+    if ((line.length() == 0) || (line.charAt(0) == FileDataModel.COMMENT_CHAR)) {
       return;
     }
-
-    int delimiterOne = line.indexOf((int) delimiter);
+    
+    int delimiterOne = line.indexOf(delimiter);
     if (delimiterOne < 0) {
       throw new IllegalArgumentException("Bad line: " + line);
     }
-
+    
     long userID = readUserIDFromString(line.substring(0, delimiterOne));
     long itemID = readItemIDFromString(line.substring(delimiterOne + 1));
-
+    
     if (transpose) {
       long tmp = userID;
       userID = itemID;
@@ -493,114 +524,115 @@
     }
     itemIDs.add(itemID);
   }
-
+  
   private void checkLoaded() {
     if (!loaded) {
       reload();
     }
   }
-
+  
   /**
-   * Subclasses may wish to override this if ID values in the file are not numeric. This
-   * provides a hook by which subclasses can inject an
-   * {@link org.apache.mahout.cf.taste.model.IDMigrator} to perform translation.
+   * Subclasses may wish to override this if ID values in the file are not numeric. This provides a hook by
+   * which subclasses can inject an {@link org.apache.mahout.cf.taste.model.IDMigrator} to perform
+   * translation.
    */
   protected long readUserIDFromString(String value) {
     return Long.parseLong(value);
   }
-
+  
   /**
-   * Subclasses may wish to override this if ID values in the file are not numeric. This
-   * provides a hook by which subclasses can inject an
-   * {@link org.apache.mahout.cf.taste.model.IDMigrator} to perform translation.
+   * Subclasses may wish to override this if ID values in the file are not numeric. This provides a hook by
+   * which subclasses can inject an {@link org.apache.mahout.cf.taste.model.IDMigrator} to perform
+   * translation.
    */
   protected long readItemIDFromString(String value) {
     return Long.parseLong(value);
   }
-
+  
   @Override
   public LongPrimitiveIterator getUserIDs() throws TasteException {
     checkLoaded();
     return delegate.getUserIDs();
   }
-
+  
   @Override
   public PreferenceArray getPreferencesFromUser(long userID) throws TasteException {
     checkLoaded();
     return delegate.getPreferencesFromUser(userID);
   }
-
+  
   @Override
   public FastIDSet getItemIDsFromUser(long userID) throws TasteException {
-    checkLoaded();    
+    checkLoaded();
     return delegate.getItemIDsFromUser(userID);
   }
-
+  
   @Override
   public LongPrimitiveIterator getItemIDs() throws TasteException {
     checkLoaded();
     return delegate.getItemIDs();
   }
-
+  
   @Override
   public PreferenceArray getPreferencesForItem(long itemID) throws TasteException {
     checkLoaded();
     return delegate.getPreferencesForItem(itemID);
   }
-
+  
   @Override
   public Float getPreferenceValue(long userID, long itemID) throws TasteException {
     return delegate.getPreferenceValue(userID, itemID);
   }
-
+  
   @Override
   public int getNumItems() throws TasteException {
     checkLoaded();
     return delegate.getNumItems();
   }
-
+  
   @Override
   public int getNumUsers() throws TasteException {
     checkLoaded();
     return delegate.getNumUsers();
   }
-
+  
   @Override
   public int getNumUsersWithPreferenceFor(long... itemIDs) throws TasteException {
     checkLoaded();
     return delegate.getNumUsersWithPreferenceFor(itemIDs);
   }
-
+  
   /**
-   * Note that this method only updates the in-memory preference data that this {@link FileDataModel} maintains; it does
-   * not modify any data on disk. Therefore any updates from this method are only temporary, and lost when data is
-   * reloaded from a file. This method should also be considered relatively slow.
+   * Note that this method only updates the in-memory preference data that this {@link FileDataModel}
+   * maintains; it does not modify any data on disk. Therefore any updates from this method are only
+   * temporary, and lost when data is reloaded from a file. This method should also be considered relatively
+   * slow.
    */
   @Override
   public void setPreference(long userID, long itemID, float value) throws TasteException {
     checkLoaded();
     delegate.setPreference(userID, itemID, value);
   }
-
+  
   /** See the warning at {@link #setPreference(long, long, float)}. */
   @Override
   public void removePreference(long userID, long itemID) throws TasteException {
     checkLoaded();
     delegate.removePreference(userID, itemID);
   }
-
+  
   @Override
   public void refresh(Collection<Refreshable> alreadyRefreshed) {
-    if (dataFile.lastModified() > lastModified + MIN_RELOAD_INTERVAL_MS ||
-        readLastUpdateFileModified() > lastUpdateFileModified + MIN_RELOAD_INTERVAL_MS) {
-      log.debug("File has changed; reloading...");
+    if ((dataFile.lastModified() > lastModified + FileDataModel.MIN_RELOAD_INTERVAL_MS)
+        || (readLastUpdateFileModified() > lastUpdateFileModified + FileDataModel.MIN_RELOAD_INTERVAL_MS)) {
+      FileDataModel.log.debug("File has changed; reloading...");
       reload();
     }
   }
-
+  
   @Override
   public String toString() {
     return "FileDataModel[dataFile:" + dataFile + ']';
   }
-
+  
 }

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/AbstractBooleanPrefJDBCDataModel.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/AbstractBooleanPrefJDBCDataModel.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/AbstractBooleanPrefJDBCDataModel.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/AbstractBooleanPrefJDBCDataModel.java Sat Feb 13 20:54:05 2010
@@ -17,25 +17,26 @@
 
 package org.apache.mahout.cf.taste.impl.model.jdbc;
 
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import javax.sql.DataSource;
+
 import org.apache.mahout.cf.taste.common.TasteException;
-import org.apache.mahout.common.IOUtils;
 import org.apache.mahout.cf.taste.impl.model.BooleanPreference;
 import org.apache.mahout.cf.taste.model.Preference;
+import org.apache.mahout.common.IOUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.sql.DataSource;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
 public abstract class AbstractBooleanPrefJDBCDataModel extends AbstractJDBCDataModel {
-
+  
   private static final Logger log = LoggerFactory.getLogger(AbstractBooleanPrefJDBCDataModel.class);
-
+  
   private final String setPreferenceSQL;
-
+  
   protected AbstractBooleanPrefJDBCDataModel(DataSource dataSource,
                                              String preferenceTable,
                                              String userIDColumn,
@@ -53,57 +54,43 @@
                                              String getPrefsForItemSQL,
                                              String getNumPreferenceForItemSQL,
                                              String getNumPreferenceForItemsSQL) {
-    super(dataSource,
-        preferenceTable,
-        userIDColumn,
-        itemIDColumn,
-        preferenceColumn,
-        getPreferenceSQL,
-        getUserSQL,
-        getAllUsersSQL,
-        getNumItemsSQL,
-        getNumUsersSQL,
-        setPreferenceSQL,
-        removePreferenceSQL,
-        getUsersSQL,
-        getItemsSQL,
-        getPrefsForItemSQL,
-        getNumPreferenceForItemSQL,
-        getNumPreferenceForItemsSQL);
+    super(dataSource, preferenceTable, userIDColumn, itemIDColumn, preferenceColumn, getPreferenceSQL,
+        getUserSQL, getAllUsersSQL, getNumItemsSQL, getNumUsersSQL, setPreferenceSQL, removePreferenceSQL,
+        getUsersSQL, getItemsSQL, getPrefsForItemSQL, getNumPreferenceForItemSQL, getNumPreferenceForItemsSQL);
     this.setPreferenceSQL = setPreferenceSQL;
   }
-
+  
   @Override
   protected Preference buildPreference(ResultSet rs) throws SQLException {
     return new BooleanPreference(getLongColumn(rs, 1), getLongColumn(rs, 2));
   }
-
+  
   @Override
   public void setPreference(long userID, long itemID, float value) throws TasteException {
     if (!Float.isNaN(value)) {
       throw new IllegalArgumentException("Invalid value: " + value);
     }
-
-    log.debug("Setting preference for user {}, item {}", userID, itemID);
-
+    
+    AbstractBooleanPrefJDBCDataModel.log.debug("Setting preference for user {}, item {}", userID, itemID);
+    
     Connection conn = null;
     PreparedStatement stmt = null;
-
+    
     try {
       conn = getDataSource().getConnection();
       stmt = conn.prepareStatement(setPreferenceSQL);
       setLongParameter(stmt, 1, userID);
       setLongParameter(stmt, 2, itemID);
-
-      log.debug("Executing SQL update: {}", setPreferenceSQL);
+      
+      AbstractBooleanPrefJDBCDataModel.log.debug("Executing SQL update: {}", setPreferenceSQL);
       stmt.executeUpdate();
-
+      
     } catch (SQLException sqle) {
-      log.warn("Exception while setting preference", sqle);
+      AbstractBooleanPrefJDBCDataModel.log.warn("Exception while setting preference", sqle);
       throw new TasteException(sqle);
     } finally {
       IOUtils.quietClose(null, stmt, conn);
     }
   }
-
+  
 }
\ No newline at end of file

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/AbstractJDBCDataModel.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/AbstractJDBCDataModel.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/AbstractJDBCDataModel.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/AbstractJDBCDataModel.java Sat Feb 13 20:54:05 2010
@@ -17,13 +17,24 @@
 
 package org.apache.mahout.cf.taste.impl.model.jdbc;
 
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import javax.sql.DataSource;
+
 import org.apache.mahout.cf.taste.common.NoSuchUserException;
 import org.apache.mahout.cf.taste.common.Refreshable;
 import org.apache.mahout.cf.taste.common.TasteException;
 import org.apache.mahout.cf.taste.impl.common.Cache;
 import org.apache.mahout.cf.taste.impl.common.FastByIDMap;
 import org.apache.mahout.cf.taste.impl.common.FastIDSet;
-import org.apache.mahout.common.IOUtils;
 import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
 import org.apache.mahout.cf.taste.impl.common.Retriever;
 import org.apache.mahout.cf.taste.impl.common.jdbc.AbstractJDBCComponent;
@@ -34,42 +45,38 @@
 import org.apache.mahout.cf.taste.model.JDBCDataModel;
 import org.apache.mahout.cf.taste.model.Preference;
 import org.apache.mahout.cf.taste.model.PreferenceArray;
+import org.apache.mahout.common.IOUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.sql.DataSource;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.NoSuchElementException;
-
 /**
- * <p>An abstract superclass for JDBC-related {@link DataModel} implementations, providing most of the common
- * functionality that any such implementation would need.</p>
- *
- * <p>Performance will be a concern with any JDBC-based {@link DataModel}. There are going to be lots of simultaneous
- * reads and some writes to one table. Make sure the table is set up optimally -- for example, you'll want to establish
- * indexes.</p>
- *
- * <p>You'll also want to use connection pooling of some kind. Most J2EE containers like Tomcat provide connection
- * pooling, so make sure the {@link DataSource} it exposes is using pooling. Outside a J2EE container, you can use
- * packages like Jakarta's <a href="http://jakarta.apache.org/commons/dbcp/">DBCP</a> to create a {@link DataSource} on
- * top of your database whose {@link Connection}s are pooled.</p>
+ * <p>
+ * An abstract superclass for JDBC-related {@link DataModel} implementations, providing most of the common
+ * functionality that any such implementation would need.
+ * </p>
+ * 
+ * <p>
+ * Performance will be a concern with any JDBC-based {@link DataModel}. There are going to be lots of
+ * simultaneous reads and some writes to one table. Make sure the table is set up optimally -- for example,
+ * you'll want to establish indexes.
+ * </p>
+ * 
+ * <p>
+ * You'll also want to use connection pooling of some kind. Most J2EE containers like Tomcat provide
+ * connection pooling, so make sure the {@link DataSource} it exposes is using pooling. Outside a J2EE
+ * container, you can use packages like Jakarta's <a href="http://jakarta.apache.org/commons/dbcp/">DBCP</a>
+ * to create a {@link DataSource} on top of your database whose {@link Connection}s are pooled.
+ * </p>
  */
 public abstract class AbstractJDBCDataModel extends AbstractJDBCComponent implements JDBCDataModel {
-
+  
   private static final Logger log = LoggerFactory.getLogger(AbstractJDBCDataModel.class);
-
+  
   public static final String DEFAULT_PREFERENCE_TABLE = "taste_preferences";
   public static final String DEFAULT_USER_ID_COLUMN = "user_id";
   public static final String DEFAULT_ITEM_ID_COLUMN = "item_id";
   public static final String DEFAULT_PREFERENCE_COLUMN = "preference";
-
+  
   private final DataSource dataSource;
   private final String preferenceTable;
   private final String userIDColumn;
@@ -89,8 +96,8 @@
   private final String getNumPreferenceForItemsSQL;
   private int cachedNumUsers;
   private int cachedNumItems;
-  private final Cache<Long, Integer> itemPrefCounts;
-
+  private final Cache<Long,Integer> itemPrefCounts;
+  
   protected AbstractJDBCDataModel(DataSource dataSource,
                                   String getPreferenceSQL,
                                   String getUserSQL,
@@ -104,25 +111,13 @@
                                   String getPrefsForItemSQL,
                                   String getNumPreferenceForItemSQL,
                                   String getNumPreferenceForItemsSQL) {
-    this(dataSource,
-        DEFAULT_PREFERENCE_TABLE,
-        DEFAULT_USER_ID_COLUMN,
-        DEFAULT_ITEM_ID_COLUMN,
-        DEFAULT_PREFERENCE_COLUMN,
-        getPreferenceSQL,
-        getUserSQL,
-        getAllUsersSQL,
-        getNumItemsSQL,
-        getNumUsersSQL,
-        setPreferenceSQL,
-        removePreferenceSQL,
-        getUsersSQL,
-        getItemsSQL,
-        getPrefsForItemSQL,
-        getNumPreferenceForItemSQL,
-        getNumPreferenceForItemsSQL);
+    this(dataSource, AbstractJDBCDataModel.DEFAULT_PREFERENCE_TABLE,
+        AbstractJDBCDataModel.DEFAULT_USER_ID_COLUMN, AbstractJDBCDataModel.DEFAULT_ITEM_ID_COLUMN,
+        AbstractJDBCDataModel.DEFAULT_PREFERENCE_COLUMN, getPreferenceSQL, getUserSQL, getAllUsersSQL,
+        getNumItemsSQL, getNumUsersSQL, setPreferenceSQL, removePreferenceSQL, getUsersSQL, getItemsSQL,
+        getPrefsForItemSQL, getNumPreferenceForItemSQL, getNumPreferenceForItemsSQL);
   }
-
+  
   protected AbstractJDBCDataModel(DataSource dataSource,
                                   String preferenceTable,
                                   String userIDColumn,
@@ -140,38 +135,39 @@
                                   String getPrefsForItemSQL,
                                   String getNumPreferenceForItemSQL,
                                   String getNumPreferenceForItemsSQL) {
-
-    log.debug("Creating AbstractJDBCModel...");
-
-    checkNotNullAndLog("preferenceTable", preferenceTable);
-    checkNotNullAndLog("userIDColumn", userIDColumn);
-    checkNotNullAndLog("itemIDColumn", itemIDColumn);
-    checkNotNullAndLog("preferenceColumn", preferenceColumn);
-
-    checkNotNullAndLog("dataSource", dataSource);
-    checkNotNullAndLog("getUserSQL", getUserSQL);
-    checkNotNullAndLog("getAllUsersSQL", getAllUsersSQL);
-    checkNotNullAndLog("getPreferenceSQL", getPreferenceSQL);
-    checkNotNullAndLog("getNumItemsSQL", getNumItemsSQL);
-    checkNotNullAndLog("getNumUsersSQL", getNumUsersSQL);
-    checkNotNullAndLog("setPreferenceSQL", setPreferenceSQL);
-    checkNotNullAndLog("removePreferenceSQL", removePreferenceSQL);
-    checkNotNullAndLog("getUsersSQL", getUsersSQL);
-    checkNotNullAndLog("getItemsSQL", getItemsSQL);
-    checkNotNullAndLog("getPrefsForItemSQL", getPrefsForItemSQL);
-    checkNotNullAndLog("getNumPreferenceForItemSQL", getNumPreferenceForItemSQL);
-    checkNotNullAndLog("getNumPreferenceForItemsSQL", getNumPreferenceForItemsSQL);
-
+    
+    AbstractJDBCDataModel.log.debug("Creating AbstractJDBCModel...");
+    
+    AbstractJDBCComponent.checkNotNullAndLog("preferenceTable", preferenceTable);
+    AbstractJDBCComponent.checkNotNullAndLog("userIDColumn", userIDColumn);
+    AbstractJDBCComponent.checkNotNullAndLog("itemIDColumn", itemIDColumn);
+    AbstractJDBCComponent.checkNotNullAndLog("preferenceColumn", preferenceColumn);
+    
+    AbstractJDBCComponent.checkNotNullAndLog("dataSource", dataSource);
+    AbstractJDBCComponent.checkNotNullAndLog("getUserSQL", getUserSQL);
+    AbstractJDBCComponent.checkNotNullAndLog("getAllUsersSQL", getAllUsersSQL);
+    AbstractJDBCComponent.checkNotNullAndLog("getPreferenceSQL", getPreferenceSQL);
+    AbstractJDBCComponent.checkNotNullAndLog("getNumItemsSQL", getNumItemsSQL);
+    AbstractJDBCComponent.checkNotNullAndLog("getNumUsersSQL", getNumUsersSQL);
+    AbstractJDBCComponent.checkNotNullAndLog("setPreferenceSQL", setPreferenceSQL);
+    AbstractJDBCComponent.checkNotNullAndLog("removePreferenceSQL", removePreferenceSQL);
+    AbstractJDBCComponent.checkNotNullAndLog("getUsersSQL", getUsersSQL);
+    AbstractJDBCComponent.checkNotNullAndLog("getItemsSQL", getItemsSQL);
+    AbstractJDBCComponent.checkNotNullAndLog("getPrefsForItemSQL", getPrefsForItemSQL);
+    AbstractJDBCComponent.checkNotNullAndLog("getNumPreferenceForItemSQL", getNumPreferenceForItemSQL);
+    AbstractJDBCComponent.checkNotNullAndLog("getNumPreferenceForItemsSQL", getNumPreferenceForItemsSQL);
+    
     if (!(dataSource instanceof ConnectionPoolDataSource)) {
-      log.warn("You are not using ConnectionPoolDataSource. Make sure your DataSource pools connections " +
-          "to the database itself, or database performance will be severely reduced.");
+      AbstractJDBCDataModel.log
+          .warn("You are not using ConnectionPoolDataSource. Make sure your DataSource pools connections "
+                + "to the database itself, or database performance will be severely reduced.");
     }
-
+    
     this.preferenceTable = preferenceTable;
     this.userIDColumn = userIDColumn;
     this.itemIDColumn = itemIDColumn;
     this.preferenceColumn = preferenceColumn;
-
+    
     this.dataSource = dataSource;
     this.getPreferenceSQL = getPreferenceSQL;
     this.getUserSQL = getUserSQL;
@@ -185,105 +181,108 @@
     this.getPrefsForItemSQL = getPrefsForItemSQL;
     this.getNumPreferenceForItemSQL = getNumPreferenceForItemSQL;
     this.getNumPreferenceForItemsSQL = getNumPreferenceForItemsSQL;
-
+    
     this.cachedNumUsers = -1;
     this.cachedNumItems = -1;
-    this.itemPrefCounts = new Cache<Long, Integer>(new ItemPrefCountRetriever(getNumPreferenceForItemSQL));
-
+    this.itemPrefCounts = new Cache<Long,Integer>(new ItemPrefCountRetriever(getNumPreferenceForItemSQL));
+    
   }
-
+  
   /** @return the {@link DataSource} that this instance is using */
   @Override
   public DataSource getDataSource() {
     return dataSource;
   }
-
+  
   public String getPreferenceTable() {
     return preferenceTable;
   }
-
+  
   public String getUserIDColumn() {
     return userIDColumn;
   }
-
+  
   public String getItemIDColumn() {
     return itemIDColumn;
   }
-
+  
   public String getPreferenceColumn() {
     return preferenceColumn;
   }
-
+  
   @Override
   public LongPrimitiveIterator getUserIDs() throws TasteException {
-    log.debug("Retrieving all users...");
+    AbstractJDBCDataModel.log.debug("Retrieving all users...");
     return new ResultSetIDIterator(getUsersSQL);
   }
-
-  /** @throws NoSuchUserException if there is no such user */
+  
+  /**
+   * @throws NoSuchUserException
+   *           if there is no such user
+   */
   @Override
   public PreferenceArray getPreferencesFromUser(long id) throws TasteException {
-
-    log.debug("Retrieving user ID '{}'", id);
-
+    
+    AbstractJDBCDataModel.log.debug("Retrieving user ID '{}'", id);
+    
     Connection conn = null;
     PreparedStatement stmt = null;
     ResultSet rs = null;
-
+    
     try {
       conn = dataSource.getConnection();
       stmt = conn.prepareStatement(getUserSQL, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
       stmt.setFetchDirection(ResultSet.FETCH_FORWARD);
       stmt.setFetchSize(getFetchSize());
       setLongParameter(stmt, 1, id);
-
-      log.debug("Executing SQL query: {}", getUserSQL);
+      
+      AbstractJDBCDataModel.log.debug("Executing SQL query: {}", getUserSQL);
       rs = stmt.executeQuery();
-
+      
       List<Preference> prefs = new ArrayList<Preference>();
       while (rs.next()) {
         prefs.add(buildPreference(rs));
       }
-
+      
       if (prefs.isEmpty()) {
         throw new NoSuchUserException();
       }
-
+      
       return new GenericUserPreferenceArray(prefs);
-
+      
     } catch (SQLException sqle) {
-      log.warn("Exception while retrieving user", sqle);
+      AbstractJDBCDataModel.log.warn("Exception while retrieving user", sqle);
       throw new TasteException(sqle);
     } finally {
       IOUtils.quietClose(rs, stmt, conn);
     }
-
+    
   }
-
+  
   @Override
   public FastByIDMap<PreferenceArray> exportWithPrefs() throws TasteException {
-    log.debug("Exporting all data");
-
+    AbstractJDBCDataModel.log.debug("Exporting all data");
+    
     Connection conn = null;
     Statement stmt = null;
     ResultSet rs = null;
-
+    
     FastByIDMap<PreferenceArray> result = new FastByIDMap<PreferenceArray>();
-
+    
     try {
       conn = dataSource.getConnection();
       stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
       stmt.setFetchDirection(ResultSet.FETCH_FORWARD);
       stmt.setFetchSize(getFetchSize());
-
-      log.debug("Executing SQL query: {}", getAllUsersSQL);
+      
+      AbstractJDBCDataModel.log.debug("Executing SQL query: {}", getAllUsersSQL);
       rs = stmt.executeQuery(getAllUsersSQL);
-
+      
       Long currentUserID = null;
       List<Preference> currentPrefs = new ArrayList<Preference>();
       while (rs.next()) {
         long nextUserID = getLongColumn(rs, 1);
-        if (currentUserID != null && !currentUserID.equals(nextUserID)) {
+        if ((currentUserID != null) && !currentUserID.equals(nextUserID)) {
           if (!currentPrefs.isEmpty()) {
             result.put(currentUserID, new GenericUserPreferenceArray(currentPrefs));
             currentPrefs.clear();
@@ -296,43 +295,43 @@
       if (!currentPrefs.isEmpty()) {
         result.put(currentUserID, new GenericUserPreferenceArray(currentPrefs));
       }
-
+      
       return result;
-
+      
     } catch (SQLException sqle) {
-      log.warn("Exception while exporting all data", sqle);
+      AbstractJDBCDataModel.log.warn("Exception while exporting all data", sqle);
       throw new TasteException(sqle);
     } finally {
       IOUtils.quietClose(rs, stmt, conn);
-
+      
     }
   }
-
+  
   @Override
   public FastByIDMap<FastIDSet> exportWithIDsOnly() throws TasteException {
-    log.debug("Exporting all data");
-
+    AbstractJDBCDataModel.log.debug("Exporting all data");
+    
     Connection conn = null;
     Statement stmt = null;
     ResultSet rs = null;
-
+    
     FastByIDMap<FastIDSet> result = new FastByIDMap<FastIDSet>();
-
+    
     try {
       conn = dataSource.getConnection();
       stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
       stmt.setFetchDirection(ResultSet.FETCH_FORWARD);
       stmt.setFetchSize(getFetchSize());
-
-      log.debug("Executing SQL query: {}", getAllUsersSQL);
+      
+      AbstractJDBCDataModel.log.debug("Executing SQL query: {}", getAllUsersSQL);
       rs = stmt.executeQuery(getAllUsersSQL);
-
+      
       boolean currentUserIDSet = false;
       long currentUserID = 0L; // value isn't used
       FastIDSet currentItemIDs = new FastIDSet(2);
       while (rs.next()) {
         long nextUserID = getLongColumn(rs, 1);
-        if (currentUserIDSet && currentUserID != nextUserID) {
+        if (currentUserIDSet && (currentUserID != nextUserID)) {
           if (!currentItemIDs.isEmpty()) {
             result.put(currentUserID, currentItemIDs);
             currentItemIDs = new FastIDSet(2);
@@ -346,61 +345,64 @@
       if (!currentItemIDs.isEmpty()) {
         result.put(currentUserID, currentItemIDs);
       }
-
+      
       return result;
-
+      
     } catch (SQLException sqle) {
-      log.warn("Exception while exporting all data", sqle);
+      AbstractJDBCDataModel.log.warn("Exception while exporting all data", sqle);
       throw new TasteException(sqle);
     } finally {
       IOUtils.quietClose(rs, stmt, conn);
-
+      
     }
   }
-
-  /** @throws NoSuchUserException if there is no such user */
+  
+  /**
+   * @throws NoSuchUserException
+   *           if there is no such user
+   */
   @Override
   public FastIDSet getItemIDsFromUser(long id) throws TasteException {
-
-    log.debug("Retrieving items for user ID '{}'", id);
-
+    
+    AbstractJDBCDataModel.log.debug("Retrieving items for user ID '{}'", id);
+    
     Connection conn = null;
     PreparedStatement stmt = null;
     ResultSet rs = null;
-
+    
     try {
       conn = dataSource.getConnection();
       stmt = conn.prepareStatement(getUserSQL, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
       stmt.setFetchDirection(ResultSet.FETCH_FORWARD);
       stmt.setFetchSize(getFetchSize());
       setLongParameter(stmt, 1, id);
-
-      log.debug("Executing SQL query: {}", getUserSQL);
+      
+      AbstractJDBCDataModel.log.debug("Executing SQL query: {}", getUserSQL);
       rs = stmt.executeQuery();
-
+      
       FastIDSet result = new FastIDSet();
       while (rs.next()) {
         result.add(getLongColumn(rs, 2));
       }
-
+      
       if (result.isEmpty()) {
         throw new NoSuchUserException();
       }
-
+      
       return result;
-
+      
     } catch (SQLException sqle) {
-      log.warn("Exception while retrieving item s", sqle);
+      AbstractJDBCDataModel.log.warn("Exception while retrieving item s", sqle);
       throw new TasteException(sqle);
     } finally {
       IOUtils.quietClose(rs, stmt, conn);
     }
-
+    
   }
-
+  
   @Override
   public Float getPreferenceValue(long userID, long itemID) throws TasteException {
-    log.debug("Retrieving preferences for item ID '{}'", itemID);
+    AbstractJDBCDataModel.log.debug("Retrieving preferences for item ID '{}'", itemID);
     Connection conn = null;
     PreparedStatement stmt = null;
     ResultSet rs = null;
@@ -411,8 +413,8 @@
       stmt.setFetchSize(1);
       setLongParameter(stmt, 1, userID);
       setLongParameter(stmt, 2, itemID);
-
-      log.debug("Executing SQL query: {}", getPreferenceSQL);
+      
+      AbstractJDBCDataModel.log.debug("Executing SQL query: {}", getPreferenceSQL);
       rs = stmt.executeQuery();
       if (rs.next()) {
         return rs.getFloat(1);
@@ -420,38 +422,39 @@
         return null;
       }
     } catch (SQLException sqle) {
-      log.warn("Exception while retrieving prefs for item", sqle);
+      AbstractJDBCDataModel.log.warn("Exception while retrieving prefs for item", sqle);
       throw new TasteException(sqle);
     } finally {
       IOUtils.quietClose(rs, stmt, conn);
     }
   }
-
+  
   @Override
   public LongPrimitiveIterator getItemIDs() throws TasteException {
-    log.debug("Retrieving all items...");
+    AbstractJDBCDataModel.log.debug("Retrieving all items...");
     return new ResultSetIDIterator(getItemsSQL);
   }
-
+  
   @Override
   public PreferenceArray getPreferencesForItem(long itemID) throws TasteException {
     List<Preference> list = doGetPreferencesForItem(itemID);
     return new GenericItemPreferenceArray(list);
   }
-
+  
   protected List<Preference> doGetPreferencesForItem(long itemID) throws TasteException {
-    log.debug("Retrieving preferences for item ID '{}'", itemID);
+    AbstractJDBCDataModel.log.debug("Retrieving preferences for item ID '{}'", itemID);
     Connection conn = null;
     PreparedStatement stmt = null;
     ResultSet rs = null;
     try {
       conn = dataSource.getConnection();
-      stmt = conn.prepareStatement(getPrefsForItemSQL, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+      stmt = conn.prepareStatement(getPrefsForItemSQL, ResultSet.TYPE_FORWARD_ONLY,
+        ResultSet.CONCUR_READ_ONLY);
       stmt.setFetchDirection(ResultSet.FETCH_FORWARD);
       stmt.setFetchSize(getFetchSize());
       setLongParameter(stmt, 1, itemID);
-
-      log.debug("Executing SQL query: {}", getPrefsForItemSQL);
+      
+      AbstractJDBCDataModel.log.debug("Executing SQL query: {}", getPrefsForItemSQL);
       rs = stmt.executeQuery();
       List<Preference> prefs = new ArrayList<Preference>();
       while (rs.next()) {
@@ -459,13 +462,13 @@
       }
       return prefs;
     } catch (SQLException sqle) {
-      log.warn("Exception while retrieving prefs for item", sqle);
+      AbstractJDBCDataModel.log.warn("Exception while retrieving prefs for item", sqle);
       throw new TasteException(sqle);
     } finally {
       IOUtils.quietClose(rs, stmt, conn);
     }
   }
-
+  
   @Override
   public int getNumItems() throws TasteException {
     if (cachedNumItems < 0) {
@@ -473,7 +476,7 @@
     }
     return cachedNumItems;
   }
-
+  
   @Override
   public int getNumUsers() throws TasteException {
     if (cachedNumUsers < 0) {
@@ -481,24 +484,22 @@
     }
     return cachedNumUsers;
   }
-
+  
   @Override
   public int getNumUsersWithPreferenceFor(long... itemIDs) throws TasteException {
     if (itemIDs == null) {
       throw new IllegalArgumentException("itemIDs is null");
     }
     int length = itemIDs.length;
-    if (length == 0 || length > 2) {
+    if ((length == 0) || (length > 2)) {
       throw new IllegalArgumentException("Illegal number of item IDs: " + length);
     }
-    return length == 1 ?
-        itemPrefCounts.get(itemIDs[0]) :
-        getNumThings("user preferring items", getNumPreferenceForItemsSQL, itemIDs);
+    return length == 1 ? itemPrefCounts.get(itemIDs[0]) : getNumThings("user preferring items",
+      getNumPreferenceForItemsSQL, itemIDs);
   }
-
-
+  
   private int getNumThings(String name, String sql, long... args) throws TasteException {
-    log.debug("Retrieving number of {} in model", name);
+    AbstractJDBCDataModel.log.debug("Retrieving number of {} in model", name);
     Connection conn = null;
     PreparedStatement stmt = null;
     ResultSet rs = null;
@@ -509,32 +510,32 @@
       stmt.setFetchSize(getFetchSize());
       if (args != null) {
         for (int i = 1; i <= args.length; i++) {
-          setLongParameter(stmt, i, args[i-1]);
+          setLongParameter(stmt, i, args[i - 1]);
         }
       }
-      log.debug("Executing SQL query: {}", sql);
+      AbstractJDBCDataModel.log.debug("Executing SQL query: {}", sql);
       rs = stmt.executeQuery();
       rs.next();
       return rs.getInt(1);
     } catch (SQLException sqle) {
-      log.warn("Exception while retrieving number of {}", name, sqle);
+      AbstractJDBCDataModel.log.warn("Exception while retrieving number of {}", name, sqle);
       throw new TasteException(sqle);
     } finally {
       IOUtils.quietClose(rs, stmt, conn);
     }
   }
-
+  
   @Override
   public void setPreference(long userID, long itemID, float value) throws TasteException {
     if (Float.isNaN(value)) {
       throw new IllegalArgumentException("Invalid value: " + value);
     }
-
-    log.debug("Setting preference for user {}, item {}", userID, itemID);    
-
+    
+    AbstractJDBCDataModel.log.debug("Setting preference for user {}, item {}", userID, itemID);
+    
     Connection conn = null;
     PreparedStatement stmt = null;
-
+    
     try {
       conn = dataSource.getConnection();
       stmt = conn.prepareStatement(setPreferenceSQL);
@@ -542,95 +543,97 @@
       setLongParameter(stmt, 2, itemID);
       stmt.setDouble(3, value);
       stmt.setDouble(4, value);
-
-      log.debug("Executing SQL update: {}", setPreferenceSQL);
+      
+      AbstractJDBCDataModel.log.debug("Executing SQL update: {}", setPreferenceSQL);
       stmt.executeUpdate();
-
+      
     } catch (SQLException sqle) {
-      log.warn("Exception while setting preference", sqle);
+      AbstractJDBCDataModel.log.warn("Exception while setting preference", sqle);
       throw new TasteException(sqle);
     } finally {
       IOUtils.quietClose(null, stmt, conn);
     }
   }
-
+  
   @Override
   public void removePreference(long userID, long itemID) throws TasteException {
-
-    log.debug("Removing preference for user '{}', item '{}'", userID, itemID);
-
+    
+    AbstractJDBCDataModel.log.debug("Removing preference for user '{}', item '{}'", userID, itemID);
+    
     Connection conn = null;
     PreparedStatement stmt = null;
-
+    
     try {
       conn = dataSource.getConnection();
       stmt = conn.prepareStatement(removePreferenceSQL);
       setLongParameter(stmt, 1, userID);
       setLongParameter(stmt, 2, itemID);
-
-      log.debug("Executing SQL update: {}", removePreferenceSQL);
+      
+      AbstractJDBCDataModel.log.debug("Executing SQL update: {}", removePreferenceSQL);
       stmt.executeUpdate();
-
+      
     } catch (SQLException sqle) {
-      log.warn("Exception while removing preference", sqle);
+      AbstractJDBCDataModel.log.warn("Exception while removing preference", sqle);
       throw new TasteException(sqle);
     } finally {
       IOUtils.quietClose(null, stmt, conn);
     }
   }
-
+  
   @Override
   public void refresh(Collection<Refreshable> alreadyRefreshed) {
     cachedNumUsers = -1;
     cachedNumItems = -1;
     itemPrefCounts.clear();
   }
-
+  
   // Some overrideable methods to customize the class behavior:
-
+  
   protected Preference buildPreference(ResultSet rs) throws SQLException {
     return new GenericPreference(getLongColumn(rs, 1), getLongColumn(rs, 2), rs.getFloat(3));
   }
-
+  
   /**
-   * Subclasses may wish to override this if ID values in the file are not numeric. This
-   * provides a hook by which subclasses can inject an
-   * {@link org.apache.mahout.cf.taste.model.IDMigrator} to perform translation.
+   * Subclasses may wish to override this if ID values in the file are not numeric. This provides a hook by
+   * which subclasses can inject an {@link org.apache.mahout.cf.taste.model.IDMigrator} to perform
+   * translation.
    */
   protected long getLongColumn(ResultSet rs, int position) throws SQLException {
     return rs.getLong(position);
   }
-
+  
   /**
-   * Subclasses may wish to override this if ID values in the file are not numeric. This
-   * provides a hook by which subclasses can inject an
-   * {@link org.apache.mahout.cf.taste.model.IDMigrator} to perform translation.
+   * Subclasses may wish to override this if ID values in the file are not numeric. This provides a hook by
+   * which subclasses can inject an {@link org.apache.mahout.cf.taste.model.IDMigrator} to perform
+   * translation.
    */
   protected void setLongParameter(PreparedStatement stmt, int position, long value) throws SQLException {
     stmt.setLong(position, value);
   }
-
+  
   /**
-   * <p>An {@link java.util.Iterator} which returns items from a {@link ResultSet}.
-   * This is a useful way to iterate over all user data since it does not require all data to be
-   * read into memory at once. It does however require that the DB connection be held open. Note that this class will
-   * only release database resources after {@link #hasNext()} has been called and has returned <code>false</code>;
-   * callers should make sure to "drain" the entire set of data to avoid tying up database resources.</p>
+   * <p>
+   * An {@link java.util.Iterator} which returns items from a {@link ResultSet}. This is a useful way to
+   * iterate over all user data since it does not require all data to be read into memory at once. It does
+   * however require that the DB connection be held open. Note that this class will only release database
+   * resources after {@link #hasNext()} has been called and has returned <code>false</code>; callers should
+   * make sure to "drain" the entire set of data to avoid tying up database resources.
+   * </p>
    */
   private final class ResultSetIDIterator implements LongPrimitiveIterator {
-
+    
     private final Connection connection;
     private final Statement statement;
     private final ResultSet resultSet;
     private boolean closed;
-
+    
     private ResultSetIDIterator(String sql) throws TasteException {
       try {
         connection = dataSource.getConnection();
         statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
         statement.setFetchDirection(ResultSet.FETCH_FORWARD);
         statement.setFetchSize(getFetchSize());
-        log.debug("Executing SQL query: {}", sql);
+        AbstractJDBCDataModel.log.debug("Executing SQL query: {}", sql);
         resultSet = statement.executeQuery(sql);
         boolean anyResults = resultSet.next();
         if (!anyResults) {
@@ -641,7 +644,7 @@
         throw new TasteException(sqle);
       }
     }
-
+    
     @Override
     public boolean hasNext() {
       boolean nextExists = false;
@@ -653,38 +656,39 @@
             nextExists = true;
           }
         } catch (SQLException sqle) {
-          log.warn("Unexpected exception while accessing ResultSet; continuing...", sqle);
+          AbstractJDBCDataModel.log.warn("Unexpected exception while accessing ResultSet; continuing...",
+            sqle);
           close();
         }
       }
       return nextExists;
     }
-
+    
     @Override
     public Long next() {
       return nextLong();
     }
-
+    
     @Override
     public long nextLong() {
-
+      
       if (!hasNext()) {
         throw new NoSuchElementException();
       }
-
+      
       try {
         long ID = getLongColumn(resultSet, 1);
         resultSet.next();
         return ID;
       } catch (SQLException sqle) {
         // No good way to handle this since we can't throw an exception
-        log.warn("Exception while iterating", sqle);
+        AbstractJDBCDataModel.log.warn("Exception while iterating", sqle);
         close();
         throw new NoSuchElementException("Can't retrieve more due to exception: " + sqle);
       }
-
+      
     }
-
+    
     @Override
     public long peek() {
       if (!hasNext()) {
@@ -694,13 +698,13 @@
         return getLongColumn(resultSet, 1);
       } catch (SQLException sqle) {
         // No good way to handle this since we can't throw an exception
-        log.warn("Exception while iterating", sqle);
+        AbstractJDBCDataModel.log.warn("Exception while iterating", sqle);
         close();
         throw new NoSuchElementException("Can't retrieve more due to exception: " + sqle);
       }
-
+      
     }
-
+    
     /**
      * @throws UnsupportedOperationException
      */
@@ -708,26 +712,26 @@
     public void remove() {
       throw new UnsupportedOperationException();
     }
-
+    
     private void close() {
       if (!closed) {
         closed = true;
         IOUtils.quietClose(resultSet, statement, connection);
       }
     }
-
+    
     @Override
     public void skip(int n) {
       if (n >= 1) {
         try {
           advanceResultSet(resultSet, n);
         } catch (SQLException sqle) {
-          log.warn("Exception while iterating over items", sqle);
+          AbstractJDBCDataModel.log.warn("Exception while iterating over items", sqle);
           close();
         }
       }
     }
-
+    
     @Override
     protected void finalize() throws Throwable {
       try {
@@ -736,16 +740,16 @@
         super.finalize();
       }
     }
-
+    
   }
-
-  private class ItemPrefCountRetriever implements Retriever<Long, Integer> {
+  
+  private class ItemPrefCountRetriever implements Retriever<Long,Integer> {
     private final String getNumPreferenceForItemSQL;
-
+    
     private ItemPrefCountRetriever(String getNumPreferenceForItemSQL) {
       this.getNumPreferenceForItemSQL = getNumPreferenceForItemSQL;
     }
-
+    
     @Override
     public Integer get(Long key) throws TasteException {
       return getNumThings("user preferring item", getNumPreferenceForItemSQL, key);

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/ConnectionPoolDataSource.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/ConnectionPoolDataSource.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/ConnectionPoolDataSource.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/ConnectionPoolDataSource.java Sat Feb 13 20:54:05 2010
@@ -17,23 +17,28 @@
 
 package org.apache.mahout.cf.taste.impl.model.jdbc;
 
-import org.apache.commons.dbcp.ConnectionFactory;
-import org.apache.commons.dbcp.PoolableConnectionFactory;
-import org.apache.commons.dbcp.PoolingDataSource;
-import org.apache.commons.pool.impl.GenericObjectPool;
-import org.apache.commons.pool.PoolableObjectFactory;
-
-import javax.sql.DataSource;
 import java.io.PrintWriter;
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 
-/** <p>A wrapper {@link DataSource} which pools connections.</p> */
-public final class ConnectionPoolDataSource implements DataSource {
+import javax.sql.DataSource;
 
-  private final DataSource delegate;
+import org.apache.commons.dbcp.ConnectionFactory;
+import org.apache.commons.dbcp.PoolableConnectionFactory;
+import org.apache.commons.dbcp.PoolingDataSource;
+import org.apache.commons.pool.PoolableObjectFactory;
+import org.apache.commons.pool.impl.GenericObjectPool;
 
+/**
+ * <p>
+ * A wrapper {@link DataSource} which pools connections.
+ * </p>
+ */
+public final class ConnectionPoolDataSource implements DataSource {
+  
+  private final DataSource delegate;
+  
   public ConnectionPoolDataSource(DataSource underlyingDataSource) {
     if (underlyingDataSource == null) {
       throw new IllegalArgumentException("underlyingDataSource is null");
@@ -44,60 +49,60 @@
     objectPool.setTestOnReturn(false);
     objectPool.setTestWhileIdle(true);
     objectPool.setTimeBetweenEvictionRunsMillis(60 * 1000L);
-    PoolableObjectFactory factory =
-            new PoolableConnectionFactory(connectionFactory, objectPool, null, "SELECT 1", false, false);
+    PoolableObjectFactory factory = new PoolableConnectionFactory(connectionFactory, objectPool, null,
+        "SELECT 1", false, false);
     objectPool.setFactory(factory);
     delegate = new PoolingDataSource(objectPool);
   }
-
+  
   @Override
   public Connection getConnection() throws SQLException {
     return delegate.getConnection();
   }
-
+  
   @Override
   public Connection getConnection(String username, String password) throws SQLException {
     return delegate.getConnection(username, password);
   }
-
+  
   @Override
   public PrintWriter getLogWriter() throws SQLException {
     return delegate.getLogWriter();
   }
-
+  
   @Override
   public void setLogWriter(PrintWriter printWriter) throws SQLException {
     delegate.setLogWriter(printWriter);
   }
-
+  
   @Override
   public void setLoginTimeout(int timeout) throws SQLException {
     delegate.setLoginTimeout(timeout);
   }
-
+  
   @Override
   public int getLoginTimeout() throws SQLException {
     return delegate.getLoginTimeout();
   }
-
+  
   @Override
   public <T> T unwrap(Class<T> iface) throws SQLException {
     return delegate.unwrap(iface);
   }
-
+  
   @Override
   public boolean isWrapperFor(Class<?> iface) throws SQLException {
     return delegate.isWrapperFor(iface);
   }
-
+  
   private static class ConfiguringConnectionFactory implements ConnectionFactory {
-
+    
     private final DataSource underlyingDataSource;
-
+    
     ConfiguringConnectionFactory(DataSource underlyingDataSource) {
       this.underlyingDataSource = underlyingDataSource;
     }
-
+    
     @Override
     public Connection createConnection() throws SQLException {
       Connection connection = underlyingDataSource.getConnection();
@@ -106,5 +111,5 @@
       return connection;
     }
   }
-
+  
 }

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/GenericJDBCDataModel.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/GenericJDBCDataModel.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/GenericJDBCDataModel.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/GenericJDBCDataModel.java Sat Feb 13 20:54:05 2010
@@ -17,9 +17,6 @@
 
 package org.apache.mahout.cf.taste.impl.model.jdbc;
 
-import org.apache.mahout.cf.taste.common.TasteException;
-import org.apache.mahout.common.IOUtils;
-
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -27,16 +24,22 @@
 import java.io.InputStream;
 import java.util.Properties;
 
+import org.apache.mahout.cf.taste.common.TasteException;
+import org.apache.mahout.cf.taste.impl.common.jdbc.AbstractJDBCComponent;
+import org.apache.mahout.common.IOUtils;
+
 /**
- * <p>A generic {@link org.apache.mahout.cf.taste.model.DataModel} designed for use with other JDBC data sources; one
- * just specifies all necessary SQL queries to the constructor here. Optionally, the queries can be specified from a
- * {@link Properties} object, {@link File}, or {@link InputStream}. This class is most appropriate when other existing
- * implementations of {@link AbstractJDBCDataModel} are not suitable. If you are using this class to support a major
- * database, consider contributing a specialized implementation of {@link AbstractJDBCDataModel} to the project for this
- * database.</p>
+ * <p>
+ * A generic {@link org.apache.mahout.cf.taste.model.DataModel} designed for use with other JDBC data sources;
+ * one just specifies all necessary SQL queries to the constructor here. Optionally, the queries can be
+ * specified from a {@link Properties} object, {@link File}, or {@link InputStream}. This class is most
+ * appropriate when other existing implementations of {@link AbstractJDBCDataModel} are not suitable. If you
+ * are using this class to support a major database, consider contributing a specialized implementation of
+ * {@link AbstractJDBCDataModel} to the project for this database.
+ * </p>
  */
 public final class GenericJDBCDataModel extends AbstractJDBCDataModel {
-
+  
   public static final String DATA_SOURCE_KEY = "dataSource";
   public static final String GET_PREFERENCE_SQL_KEY = "getPreferenceSQL";
   public static final String GET_USER_SQL_KEY = "getUserSQL";
@@ -50,62 +53,76 @@
   public static final String GET_PREFS_FOR_ITEM_SQL_KEY = "getPrefsForItemSQL";
   public static final String GET_NUM_PREFERENCE_FOR_ITEM_KEY = "getNumPreferenceForItemSQL";
   public static final String GET_NUM_PREFERENCE_FOR_ITEMS_KEY = "getNumPreferenceForItemsSQL";
-
+  
   /**
-   * <p>Specifies all SQL queries in a {@link Properties} object. See the <code>*_KEY</code> constants in this class
-   * (e.g. {@link #GET_USER_SQL_KEY}) for a list of all keys which must map to a value in this object.</p>
-   *
-   * @param props {@link Properties} object containing values
-   * @throws TasteException if anything goes wrong during initialization
+   * <p>
+   * Specifies all SQL queries in a {@link Properties} object. See the <code>*_KEY</code> constants in this
+   * class (e.g. {@link #GET_USER_SQL_KEY}) for a list of all keys which must map to a value in this object.
+   * </p>
+   * 
+   * @param props
+   *          {@link Properties} object containing values
+   * @throws TasteException
+   *           if anything goes wrong during initialization
    */
   public GenericJDBCDataModel(Properties props) throws TasteException {
-    super(lookupDataSource(props.getProperty(DATA_SOURCE_KEY)),
-        props.getProperty(GET_PREFERENCE_SQL_KEY),
-        props.getProperty(GET_USER_SQL_KEY),
-        props.getProperty(GET_ALL_USERS_SQL_KEY),        
-        props.getProperty(GET_NUM_USERS_SQL_KEY),
-        props.getProperty(GET_NUM_ITEMS_SQL_KEY),
-        props.getProperty(SET_PREFERENCE_SQL_KEY),
-        props.getProperty(REMOVE_PREFERENCE_SQL_KEY),
-        props.getProperty(GET_USERS_SQL_KEY),
-        props.getProperty(GET_ITEMS_SQL_KEY),
-        props.getProperty(GET_PREFS_FOR_ITEM_SQL_KEY),
-        props.getProperty(GET_NUM_PREFERENCE_FOR_ITEM_KEY),
-        props.getProperty(GET_NUM_PREFERENCE_FOR_ITEMS_KEY));
+    super(AbstractJDBCComponent.lookupDataSource(props.getProperty(GenericJDBCDataModel.DATA_SOURCE_KEY)),
+        props.getProperty(GenericJDBCDataModel.GET_PREFERENCE_SQL_KEY), props
+            .getProperty(GenericJDBCDataModel.GET_USER_SQL_KEY), props
+            .getProperty(GenericJDBCDataModel.GET_ALL_USERS_SQL_KEY), props
+            .getProperty(GenericJDBCDataModel.GET_NUM_USERS_SQL_KEY), props
+            .getProperty(GenericJDBCDataModel.GET_NUM_ITEMS_SQL_KEY), props
+            .getProperty(GenericJDBCDataModel.SET_PREFERENCE_SQL_KEY), props
+            .getProperty(GenericJDBCDataModel.REMOVE_PREFERENCE_SQL_KEY), props
+            .getProperty(GenericJDBCDataModel.GET_USERS_SQL_KEY), props
+            .getProperty(GenericJDBCDataModel.GET_ITEMS_SQL_KEY), props
+            .getProperty(GenericJDBCDataModel.GET_PREFS_FOR_ITEM_SQL_KEY), props
+            .getProperty(GenericJDBCDataModel.GET_NUM_PREFERENCE_FOR_ITEM_KEY), props
+            .getProperty(GenericJDBCDataModel.GET_NUM_PREFERENCE_FOR_ITEMS_KEY));
   }
-
+  
   /**
-   * <p>See {@link #GenericJDBCDataModel(java.util.Properties)}. This constructor reads values from a file instead, as
-   * if with {@link Properties#load(InputStream)}. So, the file should be in standard Java properties file format --
-   * containing <code>key=value</code> pairs, one per line.</p>
-   *
-   * @param propertiesFile properties file
-   * @throws TasteException if anything goes wrong during initialization
+   * <p>
+   * See {@link #GenericJDBCDataModel(java.util.Properties)}. This constructor reads values from a file
+   * instead, as if with {@link Properties#load(InputStream)}. So, the file should be in standard Java
+   * properties file format -- containing <code>key=value</code> pairs, one per line.
+   * </p>
+   * 
+   * @param propertiesFile
+   *          properties file
+   * @throws TasteException
+   *           if anything goes wrong during initialization
    */
   public GenericJDBCDataModel(File propertiesFile) throws TasteException {
-    this(getPropertiesFromFile(propertiesFile));
+    this(GenericJDBCDataModel.getPropertiesFromFile(propertiesFile));
   }
-
+  
   /**
-   * <p>See {@link #GenericJDBCDataModel(Properties)}. This constructor reads values from a resource available in the
-   * classpath, as if with {@link Class#getResourceAsStream(String)} and {@link Properties#load(InputStream)}. This is
-   * useful if your configuration file is, for example, packaged in a JAR file that is in the classpath.</p>
-   *
-   * @param resourcePath path to resource in classpath (e.g. "/com/foo/TasteSQLQueries.properties")
-   * @throws TasteException if anything goes wrong during initialization
+   * <p>
+   * See {@link #GenericJDBCDataModel(Properties)}. This constructor reads values from a resource available in
+   * the classpath, as if with {@link Class#getResourceAsStream(String)} and
+   * {@link Properties#load(InputStream)}. This is useful if your configuration file is, for example, packaged
+   * in a JAR file that is in the classpath.
+   * </p>
+   * 
+   * @param resourcePath
+   *          path to resource in classpath (e.g. "/com/foo/TasteSQLQueries.properties")
+   * @throws TasteException
+   *           if anything goes wrong during initialization
    */
   public GenericJDBCDataModel(String resourcePath) throws TasteException {
-    this(getPropertiesFromStream(GenericJDBCDataModel.class.getResourceAsStream(resourcePath)));
+    this(GenericJDBCDataModel.getPropertiesFromStream(GenericJDBCDataModel.class
+        .getResourceAsStream(resourcePath)));
   }
-
+  
   private static Properties getPropertiesFromFile(File file) throws TasteException {
     try {
-      return getPropertiesFromStream(new FileInputStream(file));
+      return GenericJDBCDataModel.getPropertiesFromStream(new FileInputStream(file));
     } catch (FileNotFoundException fnfe) {
       throw new TasteException(fnfe);
     }
   }
-
+  
   private static Properties getPropertiesFromStream(InputStream is) throws TasteException {
     try {
       try {
@@ -119,5 +136,5 @@
       throw new TasteException(ioe);
     }
   }
-
+  
 }