From 86858a87aa3f020c2b3a2afc2277531120dce692 Mon Sep 17 00:00:00 2001 From: Doriane Kaffo Date: Tue, 19 Mar 2019 16:30:33 +0100 Subject: [PATCH 1/8] FileTransformer --- .../res/labio/impl/transformers/FileTransformer.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/FileTransformer.java b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/FileTransformer.java index 18e3f14..283e7f6 100644 --- a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/FileTransformer.java +++ b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/FileTransformer.java @@ -58,7 +58,12 @@ 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 characters; + while ((characters = reader.read()) != -1) { + writer.write((char) characters); + } + reader.close(); writer.flush(); writer.close(); From a3c155f9f26edae21ec3ed887880cc2b9249a5fa Mon Sep 17 00:00:00 2001 From: Doriane Kaffo Date: Tue, 19 Mar 2019 16:35:05 +0100 Subject: [PATCH 2/8] NoOpFileTransformer passed --- .../res/labio/impl/transformers/NoOpFileTransformer.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/NoOpFileTransformer.java b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/NoOpFileTransformer.java index 5971a30..e0651e6 100644 --- a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/NoOpFileTransformer.java +++ b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/NoOpFileTransformer.java @@ -13,14 +13,13 @@ 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; } } From d9f4924a84d2ec3581bd19ad89df8e3c723b76ae Mon Sep 17 00:00:00 2001 From: Doriane Kaffo Date: Tue, 19 Mar 2019 16:38:25 +0100 Subject: [PATCH 3/8] FileNumberingFilterWriter --- .../filters/FileNumberingFilterWriter.java | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/filters/FileNumberingFilterWriter.java b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/filters/FileNumberingFilterWriter.java index 976c946..2d1495b 100644 --- a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/filters/FileNumberingFilterWriter.java +++ b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/filters/FileNumberingFilterWriter.java @@ -17,6 +17,9 @@ */ public class FileNumberingFilterWriter extends FilterWriter { + private int numberOfLine = 1; + private boolean r = false; // detection of \r before \n + private static final Logger LOG = Logger.getLogger(FileNumberingFilterWriter.class.getName()); public FileNumberingFilterWriter(Writer out) { @@ -25,17 +28,45 @@ public FileNumberingFilterWriter(Writer out) { @Override public void write(String str, int off, int len) throws IOException { - throw new UnsupportedOperationException("The student has not implemented this method yet."); + //converting the string into a char array to use offset and a length + write(str.toCharArray(), 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 = 0; i < len; ++i) { + this.write(cbuf[off + i]); + } } @Override public void write(int c) throws IOException { - throw new UnsupportedOperationException("The student has not implemented this method yet."); + // If we are at the first line, we add the tabin the number of line + if (numberOfLine == 1) { + out.write(numberOfLine + "\t"); + ++numberOfLine; + } + // If the last character was a '\r', we look if we have a '\n' + if (r == true) { + if ((char) c != '\n') { + out.write(numberOfLine + "\t"); + ++numberOfLine; + } + } + + r = false; + + if ((char) c == '\r') { + out.write('\r'); + r = true; + } else { + out.write((char) c); + if (c == '\n') { + out.write(numberOfLine + "\t"); + ++numberOfLine; + } + } } } + From 03553515fa015af8024e470f31c1358563511d54 Mon Sep 17 00:00:00 2001 From: Doriane Kaffo Date: Tue, 19 Mar 2019 16:42:40 +0100 Subject: [PATCH 4/8] CompleteFileTransformer passed --- .../transformers/CompleteFileTransformer.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/CompleteFileTransformer.java b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/CompleteFileTransformer.java index 4beca48..ef30e96 100644 --- a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/CompleteFileTransformer.java +++ b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/CompleteFileTransformer.java @@ -1,5 +1,7 @@ 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; /** @@ -8,24 +10,25 @@ * When an instance of this class is passed to a file system explorer, it will * generate an output file with 1) uppercase letters and 2) line numbers at the * beginning of each line. - * + * * @author Olivier Liechti */ public class CompleteFileTransformer extends FileTransformer { @Override public Writer decorateWithFilters(Writer writer) { - if (true) { + /* 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 + * 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)); - return writer; + + writer = new FileNumberingFilterWriter(new UpperCaseFilterWriter(writer)); + return writer; } } From 40f75274069ea14684cb65d4fe474f8ad5b20083 Mon Sep 17 00:00:00 2001 From: Doriane Kaffo Date: Tue, 19 Mar 2019 16:46:28 +0100 Subject: [PATCH 5/8] UpperCaseFilterWriter --- .../res/labio/impl/filters/UpperCaseFilterWriter.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/filters/UpperCaseFilterWriter.java b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/filters/UpperCaseFilterWriter.java index 0f41a5d..90788a2 100644 --- a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/filters/UpperCaseFilterWriter.java +++ b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/filters/UpperCaseFilterWriter.java @@ -9,24 +9,24 @@ * @author Olivier Liechti */ public class UpperCaseFilterWriter extends FilterWriter { - + public UpperCaseFilterWriter(Writer wrappedWriter) { super(wrappedWriter); } @Override public void write(String str, int off, int len) throws IOException { - throw new UnsupportedOperationException("The student has not implemented this method yet."); + super.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."); + super.write((new String(cbuf)).toUpperCase(), off, len); } @Override public void write(int c) throws IOException { - throw new UnsupportedOperationException("The student has not implemented this method yet."); + super.write(Character.toUpperCase(c)); } } From 17d12fb101e2d650e4c7da09485bec2678f1d98e Mon Sep 17 00:00:00 2001 From: Doriane Kaffo Date: Tue, 19 Mar 2019 16:48:53 +0100 Subject: [PATCH 6/8] Utils passed --- .../java/ch/heigvd/res/labio/impl/Utils.java | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/Utils.java b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/Utils.java index c8a3a5a..46e4371 100644 --- a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/Utils.java +++ b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/Utils.java @@ -12,15 +12,32 @@ public class Utils { /** * This method looks for the next new line separators (\r, \n, \r\n) to extract - * the next line in the string passed in arguments. - * + * the next line in the string passed in arguments. + * * @param lines a string that may contain 0, 1 or more lines * @return an array with 2 elements; the first element is the next line with * the line separator, the second element is the remaining text. If the argument does not * 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[] elements = new String[2]; + String[] newLineSeparators = {"\r", "\n", "\r\n"}; + int indexLine; + + if ((indexLine = lines.indexOf(newLineSeparators[2])) != -1) { + elements[0] = lines.substring(0, indexLine + newLineSeparators[2].length()); + elements[1] = lines.substring(indexLine + newLineSeparators[2].length(), lines.length()); + } else if ((indexLine = lines.indexOf(newLineSeparators[1])) != -1) { + elements[0] = lines.substring(0, indexLine + newLineSeparators[1].length()); + elements[1] = lines.substring(indexLine + newLineSeparators[1].length(), lines.length()); + } else if ((indexLine = lines.indexOf(newLineSeparators[0])) != -1) { + elements[0] = lines.substring(0, indexLine + newLineSeparators[0].length()); + elements[1] = lines.substring(indexLine + newLineSeparators[0].length(), lines.length()); + } else { + elements[0] = ""; + elements[1] = lines; + } + return elements; } } From 2f1dbd1e823810a3484506e0addbda8b1ab8032f Mon Sep 17 00:00:00 2001 From: Doriane Kaffo Date: Tue, 19 Mar 2019 16:52:59 +0100 Subject: [PATCH 7/8] DFSFileExplorer passed --- .../res/labio/impl/explorers/DFSFileExplorer.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/explorers/DFSFileExplorer.java b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/explorers/DFSFileExplorer.java index 83f8e61..0d23f05 100644 --- a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/explorers/DFSFileExplorer.java +++ b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/explorers/DFSFileExplorer.java @@ -3,6 +3,7 @@ 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 @@ -16,7 +17,16 @@ public class DFSFileExplorer implements IFileExplorer { @Override public void explore(File rootDirectory, IFileVisitor vistor) { - throw new UnsupportedOperationException("The student has not implemented this method yet."); + + if (rootDirectory != null){ + vistor.visit(rootDirectory); // visit of directory + File[] list = rootDirectory.listFiles(); + if (list != null) { // we do something if list isn't emty + Arrays.sort(list); // sort of list + for (File file : list) { + explore(file, vistor); + } + } + } } - } From a731f16b4e3eff783f9e55e4dbbfeeb0de2c9c93 Mon Sep 17 00:00:00 2001 From: Doriane Kaffo Date: Tue, 19 Mar 2019 16:57:09 +0100 Subject: [PATCH 8/8] all test passed --- .../ch/heigvd/res/labio/impl/Application.java | 62 ++++++++++++------- .../labio/impl/explorers/DFSFileExplorer.java | 2 +- 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/Application.java b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/Application.java index ad87a7d..990d23d 100644 --- a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/Application.java +++ b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/Application.java @@ -14,6 +14,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.io.FileUtils; +import java.io.*; /** * @@ -26,19 +27,19 @@ public class Application implements IApplication { * to where the Java application is invoked. */ public static String WORKSPACE_DIRECTORY = "./workspace/quotes"; - + private static final Logger LOG = Logger.getLogger(Application.class.getName()); - + public static void main(String[] args) { - + /* * I prefer to have LOG output on a single line, it's easier to read. Being able * to change the formatting of console outputs is one of the reasons why it is * better to use a Logger rather than using System.out.println */ System.setProperty("java.util.logging.SimpleFormatter.format", "%4$s: %5$s%6$s%n"); - - + + int numberOfQuotes = 0; try { numberOfQuotes = Integer.parseInt(args[0]); @@ -46,32 +47,32 @@ public static void main(String[] args) { System.err.println("The command accepts a single numeric argument (number of quotes to fetch)"); System.exit(-1); } - + Application app = new Application(); try { /* * Step 1 : clear the output directory */ app.clearOutputDirectory(); - + /* * Step 2 : use the QuotesClient to fetch quotes; store each quote in a file */ app.fetchAndStoreQuotes(numberOfQuotes); - + /* * Step 3 : use a file explorer to traverse the file system; print the name of each directory and file */ Writer writer = new StringWriter(); // we create a special writer that will send characters into a string (memory) app.printFileNames(writer); // we hand over this writer to the printFileNames method LOG.info(writer.toString()); // we dump the whole result on the console - + /* * Step 4 : process the quote files, by applying 2 transformations to their content * (convert to uppercase and add line numbers) */ app.processQuoteFiles(); - + } catch (IOException ex) { LOG.log(Level.SEVERE, "Could not fetch quotes. {0}", ex.getMessage()); ex.printStackTrace(); @@ -91,41 +92,52 @@ public void fetchAndStoreQuotes(int numberOfQuotes) throws IOException { * quote in a text file (and for generating the directories based on the tags). */ LOG.info("Received a new joke with " + quote.getTags().size() + " tags."); + storeQuote(quote, "quote-" + quote.getValue().getId() + ".utf8"); for (String tag : quote.getTags()) { LOG.info("> " + tag); } } } - + /** * This method deletes the WORKSPACE_DIRECTORY and its content. It uses the * apache commons-io library. You should call this method in the main method. - * - * @throws IOException + * + * @throws IOException */ void clearOutputDirectory() throws IOException { - FileUtils.deleteDirectory(new File(WORKSPACE_DIRECTORY)); + FileUtils.deleteDirectory(new File(WORKSPACE_DIRECTORY)); } /** * This method stores the content of a quote in the local file system. It has - * 2 responsibilities: - * + * 2 responsibilities: + * * - with quote.getTags(), it gets a list of tags and uses * it to create sub-folders (for instance, if a quote has three tags "A", "B" and * "C", it will be stored in /quotes/A/B/C/quotes-n.utf8. - * + * * - with quote.getQuote(), it has access to the text of the quote. It stores * this text in UTF-8 file. - * + * * @param quote the quote object, with tags and text * @param filename the name of the file to create and where to store the quote text - * @throws IOException + * @throws IOException */ void storeQuote(Quote quote, String filename) throws IOException { - throw new UnsupportedOperationException("The student has not implemented this method yet."); + String path = WORKSPACE_DIRECTORY; + for (String tag : quote.getTags()) { + path = path + File.separator + tag; + } + path = path + File.separator + filename; // we add the filename + //creation of file + File files = new File(path); + files.getParentFile().mkdirs(); // we create the parent repertory + BufferedWriter Writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path), "UTF-8")); + Writer.write(quote.getQuote()); + Writer.close(); } - + /** * This method uses a IFileExplorer to explore the file system and prints the name of each * encountered file and directory. @@ -140,6 +152,12 @@ 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'); + } catch (IOException e) { + e.printStackTrace(); + } } }); } @@ -147,7 +165,7 @@ public void visit(File file) { @Override public void processQuoteFiles() throws IOException { IFileExplorer explorer = new DFSFileExplorer(); - explorer.explore(new File(WORKSPACE_DIRECTORY), new CompleteFileTransformer()); + explorer.explore(new File(WORKSPACE_DIRECTORY), new CompleteFileTransformer()); } } diff --git a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/explorers/DFSFileExplorer.java b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/explorers/DFSFileExplorer.java index 0d23f05..e2a58f1 100644 --- a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/explorers/DFSFileExplorer.java +++ b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/explorers/DFSFileExplorer.java @@ -17,7 +17,7 @@ public class DFSFileExplorer implements IFileExplorer { @Override public void explore(File rootDirectory, IFileVisitor vistor) { - + if (rootDirectory != null){ vistor.visit(rootDirectory); // visit of directory File[] list = rootDirectory.listFiles();