Skip to content
49 changes: 43 additions & 6 deletions LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,16 @@
import ch.heigvd.res.labio.interfaces.IFileVisitor;
import ch.heigvd.res.labio.quotes.QuoteClient;
import ch.heigvd.res.labio.quotes.Quote;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;

import java.io.*;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.io.FileUtils;

/**
*
* @author Olivier Liechti
* @author Olivier Liechti - Modified by Nicolas Müller on 07.03.2020
*/
public class Application implements IApplication {

Expand Down Expand Up @@ -80,17 +79,24 @@ public static void main(String[] args) {

@Override
public void fetchAndStoreQuotes(int numberOfQuotes) throws IOException {

clearOutputDirectory();
QuoteClient client = new QuoteClient();

for (int i = 0; i < numberOfQuotes; i++) {

Quote quote = client.fetchQuote();
/* There is a missing piece here!
* As you can see, this method handles the first part of the lab. It uses the web service
* client to fetch quotes. We have removed a single line from this method. It is a call to
* one method provided by this class, which is responsible for storing the content of the
* quote in a text file (and for generating the directories based on the tags).
*/

storeQuote(quote, "quote-" + (i + 1) + ".utf8");

LOG.info("Received a new joke with " + quote.getTags().size() + " tags.");

for (String tag : quote.getTags()) {
LOG.info("> " + tag);
}
Expand Down Expand Up @@ -123,7 +129,31 @@ void clearOutputDirectory() throws IOException {
* @throws IOException
*/
void storeQuote(Quote quote, String filename) throws IOException {
throw new UnsupportedOperationException("The student has not implemented this method yet.");

StringBuilder path = new StringBuilder(WORKSPACE_DIRECTORY + '/');

List<String> tags = quote.getTags();

// Generating path
for (String tag : tags) {

path.append(tag);
path.append('/');
}

File newQuote = new File(path.toString() + filename);

// Creating folders on path to quote
newQuote.getParentFile().mkdirs();


FileWriter fileWriter;

// Throws IOEXception if somthing goes wrong

fileWriter = new FileWriter(newQuote);
fileWriter.write(quote.getQuote());
fileWriter.close();
}

/**
Expand All @@ -140,6 +170,13 @@ public void visit(File file) {
* of the the IFileVisitor interface inline. You just have to add the body of the visit method, which should
* be pretty easy (we want to write the filename, including the path, to the writer passed in argument).
*/
try {

writer.write(file.getPath() + '\n'); // '\n' to match expected test results for Linux
}
catch (IOException e) {
e.printStackTrace();
}
}
});
}
Expand Down
33 changes: 30 additions & 3 deletions LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

/**
*
* @author Olivier Liechti
* @author Olivier Liechti - Modified by Nicolas Müller on 07.03.2020
*/
public class Utils {

Expand All @@ -20,7 +20,34 @@ public class Utils {
* contain any line separator, then the first element is an empty string.
*/
public static String[] getNextLine(String lines) {
throw new UnsupportedOperationException("The student has not implemented this method yet.");

String[] result = new String[2];

// Get position of first separator occurence in lines. Returns -1 if not found

int posLinuxSeparator = lines.indexOf("\n");
int posMacSeparator = lines.indexOf("\r");
int posWindowsSeparator = lines.indexOf("\r\n");

int splitPos = -1;

if (posWindowsSeparator != -1) {

splitPos = posWindowsSeparator + 2;
}
else if (posMacSeparator != -1) {

splitPos = posMacSeparator + 1;
}
else if (posLinuxSeparator != -1) {

splitPos = posLinuxSeparator + 1;
}

result[0] = splitPos != -1 ? lines.substring(0, splitPos) : "";
result[1] = splitPos != -1 ? lines.substring(splitPos) : lines;

return result;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,47 @@
import ch.heigvd.res.labio.interfaces.IFileExplorer;
import ch.heigvd.res.labio.interfaces.IFileVisitor;
import java.io.File;
import java.util.Arrays;

/**
* This implementation of the IFileExplorer interface performs a depth-first
* exploration of the file system and invokes the visitor for every encountered
* node (file and directory). When the explorer reaches a directory, it visits all
* files in the directory and then moves into the subdirectories.
*
* @author Olivier Liechti
* @author Olivier Liechti - Modified by Nicolas Müller on 07.03.2020
*/
public class DFSFileExplorer implements IFileExplorer {

@Override
public void explore(File rootDirectory, IFileVisitor vistor) {
throw new UnsupportedOperationException("The student has not implemented this method yet.");
}
public void explore(File rootDirectory, IFileVisitor visitor) {

visitor.visit(rootDirectory);

// No need to do anything more if it's not a directory
if (!rootDirectory.isDirectory()) {

return;
}

File[] files = rootDirectory.listFiles();

// No need to do anything more if directory is empty
if (files != null) {

// Test sometimes fails without sorting
Arrays.sort(files);

// Explore more if it's a directory or visit it if it's a file
for (File f : files) {

if (f.isDirectory()) {
explore(f, visitor);
}
else {
visitor.visit(f);
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package ch.heigvd.res.labio.impl.filters;

import ch.heigvd.res.labio.impl.Utils;

import java.io.FilterWriter;
import java.io.IOException;
import java.io.Writer;
Expand All @@ -13,29 +15,62 @@
*
* Hello\n\World -> 1\Hello\n2\tWorld
*
* @author Olivier Liechti
* @author Olivier Liechti - Modified by Nicolas Müller on 07.03.2020
*/
public class FileNumberingFilterWriter extends FilterWriter {

private static final Logger LOG = Logger.getLogger(FileNumberingFilterWriter.class.getName());
private boolean isFirstChar = true;
private int lineCounter = 0;
private char lastChar = '\0';

public FileNumberingFilterWriter(Writer out) {
super(out);
}

@Override
public void write(String str, int off, int len) throws IOException {
throw new UnsupportedOperationException("The student has not implemented this method yet.");

for (int i = off; i < off + len; i++) {
write(str.charAt(i));
}
}

@Override
public void write(char[] cbuf, int off, int len) throws IOException {
throw new UnsupportedOperationException("The student has not implemented this method yet.");

for (int i = off; i < off + len; i++) {
write(cbuf[i]);
}
}

@Override
public void write(int c) throws IOException {
throw new UnsupportedOperationException("The student has not implemented this method yet.");
}

// Adds tab and numbers if it's the first char
if (isFirstChar) {

out.write(Integer.toString(++lineCounter) + '\t');
isFirstChar = false;
}

// Windows has \r\n, Linux \n, Mac \r
// Function adds newline only with \n. Make sure to add a new line if \r appears without the \n.
if (lastChar == '\r' && c != '\n') {

out.write(Integer.toString(++lineCounter) + '\t');
}

// Writes current char
out.write((char)c);

// Creates new line if \n found
if (c == '\n') {

out.write(Integer.toString(++lineCounter) + '\t');
}

// Used to make it work on windows, mac and linux
lastChar = (char) c;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

/**
*
* @author Olivier Liechti
* @author Olivier Liechti - Modified by Nicolas Müller on 07.03.2020
*/
public class UpperCaseFilterWriter extends FilterWriter {

Expand All @@ -16,17 +16,25 @@ public UpperCaseFilterWriter(Writer wrappedWriter) {

@Override
public void write(String str, int off, int len) throws IOException {
throw new UnsupportedOperationException("The student has not implemented this method yet.");

out.write(str.toUpperCase(), off, len);
}

@Override
public void write(char[] cbuf, int off, int len) throws IOException {
throw new UnsupportedOperationException("The student has not implemented this method yet.");

for (int i = off; i < len + off; i++) {
cbuf[i] = Character.toUpperCase(cbuf[i]);
}

out.write(cbuf, off, len);
}

@Override
public void write(int c) throws IOException {
throw new UnsupportedOperationException("The student has not implemented this method yet.");

out.write(Character.toUpperCase(c));

}

}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package ch.heigvd.res.labio.impl.transformers;

import ch.heigvd.res.labio.impl.filters.FileNumberingFilterWriter;
import ch.heigvd.res.labio.impl.filters.UpperCaseFilterWriter;

import java.io.Writer;

/**
Expand All @@ -9,22 +12,20 @@
* generate an output file with 1) uppercase letters and 2) line numbers at the
* beginning of each line.
*
* @author Olivier Liechti
* @author Olivier Liechti - Modified by Nicolas Müller on 07.03.2020
*/
public class CompleteFileTransformer extends FileTransformer {

@Override
public Writer decorateWithFilters(Writer writer) {
if (true) {
throw new UnsupportedOperationException("The student has not implemented this method yet.");
}

/*
* If you uncomment the following line (and get rid of th 3 previous lines...), you will restore the decoration
* of the writer (connected to the file. You can see that you first decorate the writer with an UpperCaseFilterWriter, which you then
* decorate with a FileNumberingFilterWriter. The resulting writer is used by the abstract class to write the characters read from the
* input files. So, the input is first prefixed with line numbers, then transformed to uppercase, then sent to the output file.f
*/
//writer = new FileNumberingFilterWriter(new UpperCaseFilterWriter(writer));
writer = new FileNumberingFilterWriter(new UpperCaseFilterWriter(writer));
return writer;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* The subclasses have to implement the decorateWithFilters method, which instantiates
* a list of filters and decorates the output writer with them.
*
* @author Olivier Liechti
* @author Olivier Liechti - Modified by Nicolas Müller on 07.03.2020
*/
public abstract class FileTransformer implements IFileVisitor {

Expand Down Expand Up @@ -58,6 +58,14 @@ public void visit(File file) {
* writer has been decorated by the concrete subclass!). You need to write a loop to read the
* characters and write them to the writer.
*/

int value = -1; // If read fails, returns -1

// Writes values after each correct read
while (reader.ready() && (value = reader.read()) != -1) {

writer.write(value);
}

reader.close();
writer.flush();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,19 @@
* this class is passed to a file system explorer, it will simply duplicate
* the content of the input file into the output file.
*
* @author Olivier Liechti
* @author Olivier Liechti - Modified by Nicolas Müller on 07.03.2020
*/
public class NoOpFileTransformer extends FileTransformer {

@Override
public Writer decorateWithFilters(Writer writer) {
throw new UnsupportedOperationException("The student has not implemented this method yet.");
/*
* The NoOpFileTransformer does not apply any transformation of the character stream
* (no uppercase, no line number, etc.). So, we don't need to decorate the writer connected to
* the output file at all. Just uncomment the following line and get rid of the UnsupportedOperationException and
* you will be all set.
*/
//return writer;
return writer;
}

}