public Path prepareDataSet() throws IOException {
		// Get hadoop file system configuration.
		FileSystem fs = FileSystem.get(this.conf);

		// Check if a single file was referenced, otherwise our implementation can't handle it.
		if (!fs.exists(this.path)) throw new IOException(Coefficient.EOL + "You have to specify the complete absolute path to the test dataset!" + Coefficient.EOL +Coefficient.EOL);

		FSDataInputStream is = null;
		FSDataOutputStream os = null;
		BufferedReader br = null;
		BufferedWriter bw = null;
		Path newPathForPreparedData = new Path(inputPath + "-prepared");
		Map<Integer, Integer[]> userMap = new HashMap<Integer, Integer[]>();

		// We enclose this in a try/finally-block to ensure that the lock from the file always gets removed.
		try {
			is = fs.open(this.path);
			os = fs.create(newPathForPreparedData, true);
			br = new BufferedReader(new InputStreamReader(is, Coefficient.CHARSET), Coefficient.BUFFER_SIZE);
			bw = new BufferedWriter(new OutputStreamWriter(os, Coefficient.CHARSET), Coefficient.BUFFER_SIZE);
			String line, rating;
			String[] jokeRating;
			int i = 0;
			StringTokenizer tokenizer;

			// Read each line of the file, each line represents a single user.
			while ((line = br.readLine()) != null) {
				// Prepare the ratings array within our user map. We initialize each offset with the invalid rating 99.
				userMap.put(i, new Integer[Coefficient.MAX_RATINGS]);
				for (int j = 0; j < Coefficient.MAX_RATINGS; j++) userMap.get(i)[j] = 99;

				// Tokenize each line into little chunks splitted at the character ";".
				tokenizer = new StringTokenizer(line, ";");

				while (tokenizer.hasMoreTokens()) {
					// Split the tokenized string at "," and check if we have two offsets. We also check it the
					// extracted rating contains whitespaces, is empty ("") or null, as these are illegal values for a
					// rating.
					if ((jokeRating = tokenizer.nextToken().split(",")).length == 2 && !(StringUtils.isBlank(rating = StringUtils.trim(jokeRating[0])))) {
						// If the rating is -0 insert 0, otherwise we'll get a NumberFormatException later on.
						userMap.get(i)[Integer.valueOf(jokeRating[1]) - 1] = rating.equals("-0") ? 0 : Integer.valueOf(rating);
					}
				}

				// The iterator represents the line and each line represents a user, by incrementing the iterator we
				// increase the user count / ID.
				i++;
			}

			// Loop again over all ratings and users, we have to create a file that is usable by the hadoop M/R job. The
			// final anatomy of the prepared data file looks as follows:
			//
			// 0;1;2;...;n;
			// 0;1;2;...;n;
			//
			// Each value represents a rating, each column represents a user, and each line represents a joke. The jokes
			// (lines) are already ordered for easy M/R computation.
			for (int j = 0; j < Coefficient.MAX_RATINGS; j++) {
				for (int userID = 0; userID < userMap.size(); userID++) {
					bw.append((new StringBuilder()).append(userMap.get(userID)[j]).append(";").toString());
				}
				bw.newLine();
			}
		} finally {
			br.close();
			bw.close();
			is.close();
			os.close();
		}

		// We have to delete the prepared data file. It's not needed anymore and if another job is started the file
		// shouldn't be present in the file system.
		FileSystem.get(this.conf).deleteOnExit(newPathForPreparedData);

		return newPathForPreparedData;
	}