norbert.mynemo.dataimport.fileformat.MynemoRating.java Source code

Java tutorial

Introduction

Here is the source code for norbert.mynemo.dataimport.fileformat.MynemoRating.java

Source

/*
 * Copyright 2015 Norbert
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package norbert.mynemo.dataimport.fileformat;

import static com.google.common.base.Preconditions.checkArgument;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.csv.CSVRecord;
import org.apache.commons.lang3.builder.HashCodeBuilder;

/**
 * A Mynemo rating encapsulates the user that give the rating, the rated movie and the value of the
 * rating.
 *
 * <p>
 * A list of ratings can be persisted in a tab-separated value file, where each line represents a
 * rating. The columns are:
 * <ul>
 * <li>user id
 * <li>IMDb id of the movie
 * <li>value of the rating
 * </ul>
 */
public class MynemoRating {
    /**
     * Format of the CSV entries. That defines the Mynemo rating file format.
     */
    private static final CSVFormat CSV_FORMAT = CSVFormat.MYSQL;
    /**
     * Set containing all different movie, user and rating ids built by this class.
     */
    private static final Map<String, String> ID_CACHE = new HashMap<String, String>();
    /**
     * Rating value superior to this maximum is invalid.
     */
    public static final int MAXIMUM_RATING_VALUE = 100;
    /**
     * Rating value inferior to this minimum is invalid.
     */
    public static final int MINIMUM_RATING_VALUE = 0;
    /**
     * The movie index in a rating record. That defines the Mynemo rating file format.
     */
    private static final int MOVIE_INDEX = 1;
    /**
     * The user index in a rating record. That defines the Mynemo rating file format.
     */
    private static final int USER_INDEX = 0;
    /**
     * The value index in a rating record. That defines the Mynemo rating file format.
     */
    private static final int VALUE_INDEX = 2;

    /**
     * Returns a parser able to read a Mynemo rating file.
     *
     * @param filepath file to read
     * @return a new parser
     */
    public static CSVParser createParser(String filepath) throws IOException {
        return new CSVParser(new BufferedReader(new FileReader(filepath)), CSV_FORMAT);
    }

    /**
     * Creates a printer where a rating can be printed. The given file must not exist.
     *
     * @param filepath the filepath where the printer will write the data.
     * @return a new printer
     */
    public static CSVPrinter createPrinter(String filepath) throws IOException {
        checkArgument(filepath != null, "The filepath must be not null.");
        checkArgument(!new File(filepath).exists(), "The file must not exist.");

        return new CSVPrinter(new BufferedWriter(new FileWriter(filepath)), CSV_FORMAT);
    }

    /**
     * Creates a rating from a record. The record was usually created from a parser created by the
     * {@link #createParser(String)} method.
     */
    public static MynemoRating createRating(CSVRecord record) {
        return new MynemoRating(record.get(USER_INDEX), record.get(MOVIE_INDEX), record.get(VALUE_INDEX));
    }

    /**
     * Puts the given id in the cache, and returns it, or an equal cached id.
     */
    private static String getCacheId(String id) {
        if (!ID_CACHE.containsKey(id)) {
            ID_CACHE.put(id, id);
        }
        return ID_CACHE.get(id);
    }

    /**
     * Returns <code>true</code> if the rating can be created from the given parameters. Returns
     * <code>false</code> otherwise. If one parameter is <code>null</code>, if the rating valuecannot
     * be parsed as a <code>double</code> and if the value is out of the accepted range, a rating is
     * invalid.
     */
    public static boolean isValid(String user, String movie, String value) {
        double numericValue;
        if (user == null || movie == null || value == null) {
            return false;
        }

        try {
            Long.parseLong(movie);
            numericValue = Float.parseFloat(value);
        } catch (NumberFormatException e) {
            return false;
        }

        return MINIMUM_RATING_VALUE <= numericValue && numericValue <= MAXIMUM_RATING_VALUE;
    }

    private final String movie;
    private final String user;
    private final String value;

    /**
     * Creates a rating with the given value by the given user to the given movie.
     */
    public MynemoRating(String user, String movie, String value) {
        checkArgument(isValid(user, movie, value), "Unable to create the Mynemo rating with from the" + " user '"
                + user + "' on the movie '" + movie + "' with the value '" + value + "'.");

        this.user = getCacheId(user);
        this.movie = getCacheId(movie);
        this.value = getCacheId(value);
    }

    @Override
    public boolean equals(Object o) {
        if (!(o instanceof MynemoRating)) {
            return false;
        }
        MynemoRating r = (MynemoRating) o;
        return movie.equals(r.movie) && user.equals(r.user) && value.equals(r.value);
    }

    /**
     * Returns the value as <code>float</code> data type.
     */
    public float getFloatValue() {
        return Float.parseFloat(value);
    }

    /**
     * Returns the movie id as <code>long</code> data type.
     */
    public long getLongMovie() {
        return Long.parseLong(movie);
    }

    public String getMovie() {
        return movie;
    }

    public String getUser() {
        return user;
    }

    public String getValue() {
        return value;
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(movie).append(user).append(value).toHashCode();
    }

    /**
     * Prints the internal data to the given printer. The printer is usually created by calling the
     * {@link #createPrinter(String)} method.
     */
    public void printOn(CSVPrinter printer) throws IOException {
        // the write order depends on the *_INDEX values
        printer.print(user);
        printer.print(movie);
        printer.print(value);
        // end of the record
        printer.println();
    }
}