/*
 * LensKit, an open source recommender systems toolkit.
 * Copyright 2010-2014 LensKit Contributors.  See CONTRIBUTORS.md.
 * Work on LensKit has been funded by the National Science Foundation under
 * grants IIS 05-34939, 08-08692, 08-12148, and 10-17697.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 51
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
package org.grouplens.lenskit.data.dao;

import com.google.common.collect.ImmutableMap;
import it.unimi.dsi.fastutil.longs.LongSet;
import it.unimi.dsi.fastutil.longs.LongSortedSet;
import org.apache.commons.lang3.text.StrTokenizer;
import org.grouplens.lenskit.core.Shareable;
import org.lenskit.util.io.LineStream;
import org.grouplens.lenskit.util.io.CompressionMode;
import org.lenskit.util.collections.LongUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.Map;
import java.util.NoSuchElementException;

/**
 * An item name DAO backed by a map of item IDs to names.
 *
 * @since 2.2
 * @see org.grouplens.lenskit.data.dao.ItemNameDAO
 */
@Shareable
public class MapItemNameDAO implements ItemNameDAO, ItemDAO, Serializable {
    private static final Logger logger = LoggerFactory.getLogger(MapItemNameDAO.class);
    private static final long serialVersionUID = 1L;
    private final Map<Long,String> itemNameMap;
    private final LongSortedSet itemIds;

    public MapItemNameDAO(Map<Long,String> items) {
        itemNameMap = ImmutableMap.copyOf(items);
        itemIds = LongUtils.packedSet(itemNameMap.keySet());
    }

    @Nullable
    @Override
    public LongSet getItemIds() {
        return itemIds;
    }

    @Nullable
    @Override
    public String getItemName(long item) {
        return itemNameMap.get(item);
    }

    /**
     * Read an item list DAO from a file.
     * @param file A file of item IDs, one per line.
     * @return The item list DAO.
     * @throws java.io.IOException if there is an error reading the list of items.
     */
    public static MapItemNameDAO fromCSVFile(File file) throws IOException {
        LineStream stream = LineStream.openFile(file, CompressionMode.AUTO);
        try {
            ImmutableMap.Builder<Long, String> names = ImmutableMap.builder();
            StrTokenizer tok = StrTokenizer.getCSVInstance();
            for (String line : stream) {
                tok.reset(line);
                long item = Long.parseLong(tok.next());
                String title = tok.nextToken();
                if (title != null) {
                    names.put(item, title);
                }
            }
            return new MapItemNameDAO(names.build());
        } catch (NoSuchElementException ex) {
            throw new IOException(String.format("%s:%s: not enough columns",
                                                file, stream.getLineNumber()),
                                  ex);
        } catch (NumberFormatException ex) {
            throw new IOException(String.format("%s:%s: id not an integer",
                                                file, stream.getLineNumber()),
                                  ex);
        } finally {
            stream.close();
        }
    }
}

@@ -1027,16 +1027,61 @@
 a.dao;%0A%0A
+import com.google.common.base.Preconditions;%0A
 import c
@@ -1115,24 +1115,24 @@
 mutableMap;%0A
-
 import it.un
@@ -1449,16 +1449,58 @@
 gUtils;%0A
+import org.lenskit.util.io.ObjectStreams;%0A
 import o
@@ -2552,24 +2552,393 @@
 em);%0A    %7D%0A%0A
+    /**%0A     * Read an item list DAO from a file with no header rows.%0A     * @param file A file of item IDs, one per line.%0A     * @return The item list DAO.%0A     * @throws java.io.IOException if there is an error reading the list of items.%0A     */%0A    public static MapItemNameDAO fromCSVFile(File file) throws IOException %7B%0A        return fromCSVFile(file, 0);%0A    %7D%0A%0A
     /**%0A    
@@ -3020,32 +3020,93 @@
 , one per line.%0A
+     * @param skipLines The number of initial header to skip%0A
      * @return T
@@ -3260,32 +3260,47 @@
 SVFile(File file
+, int skipLines
 ) throws IOExcep
@@ -3298,32 +3298,115 @@
 s IOException %7B%0A
+        Preconditions.checkArgument(skipLines %3E= 0, %22cannot skip negative lines%22);%0A
         LineStre
@@ -3466,16 +3466,16 @@
 .AUTO);%0A
-
         
@@ -3476,24 +3476,78 @@
       try %7B%0A
+            ObjectStreams.consume(skipLines, stream);%0A
             

Add line skipping support to item-name DAO