Skip to content

Commit

Permalink
Merge pull request #81 from thomastanck/offline-view
Browse files Browse the repository at this point in the history
View articles offline if available

Adds `offlineLink` field to `Entry`, and `BrowserPanel` views `offlineLink` if it exists.

### Summary of changes

* Add `offlineLink` to `Entry`
* Connect `offlineLink` to `BrowserPanel`
* Update `JsonAdaptedEntry` so that `offlineLink` will be saved to disk
* Adds `.html` extension to local filenames so that `WebEngine` views them properly.
  • Loading branch information
thomastanck authored Mar 19, 2019
2 parents dedc343 + 309210e commit 6dd6435
Show file tree
Hide file tree
Showing 18 changed files with 240 additions and 92 deletions.
10 changes: 9 additions & 1 deletion src/main/java/seedu/address/logic/commands/AddCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Path;
import java.util.Optional;
import java.util.logging.Logger;

Expand All @@ -29,6 +30,7 @@
import seedu.address.model.Model;
import seedu.address.model.entry.Description;
import seedu.address.model.entry.Entry;
import seedu.address.model.entry.Link;
import seedu.address.model.entry.Title;
import seedu.address.model.util.Candidate;
import seedu.address.network.Network;
Expand Down Expand Up @@ -112,11 +114,16 @@ public CommandResult execute(Model model, CommandHistory history) throws Command
}
}

Optional<Link> offlineLink = Optional.empty();

try {

// Download article content to local storage
byte[] articleContent = Network.fetchAsBytes(urlString);
model.addArticle(urlString, articleContent);
Optional<Path> articlePath = model.addArticle(urlString, articleContent);
if (articlePath.isPresent()) {
offlineLink = Optional.of(new Link(articlePath.get().toUri().toASCIIString()));
}

if (noTitleOrNoDescription) {

Expand Down Expand Up @@ -150,6 +157,7 @@ public CommandResult execute(Model model, CommandHistory history) throws Command
title.isEmpty() ? candidateTitle.get() : title, // replace title if empty
description.isEmpty() ? candidateDescription.get() : description, // replace description if empty
toAdd.getLink(),
offlineLink,
toAdd.getAddress(),
toAdd.getTags()
);
Expand Down
7 changes: 4 additions & 3 deletions src/main/java/seedu/address/model/Model.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
import java.util.function.Predicate;

import javafx.beans.property.ReadOnlyProperty;
Expand Down Expand Up @@ -101,12 +102,12 @@ public interface Model {
*/
void clearEntryBook();

/** Adds article with {@code articleContent} associated with {@code url}. */
Optional<Path> addArticle(String url, byte[] articleContent) throws IOException;

/** Displays a given entryBook without touching storage. */
void displayEntryBook(ReadOnlyEntryBook entryBook);

/** Adds article with {@code articleContent} associated with {@code url}. */
void addArticle(String url, byte[] articleContent) throws IOException;

/** Returns an unmodifiable view of the filtered entry list */
ObservableList<Entry> getFilteredEntryList();

Expand Down
5 changes: 3 additions & 2 deletions src/main/java/seedu/address/model/ModelManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.io.IOException;
import java.nio.file.Path;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.logging.Logger;

Expand Down Expand Up @@ -168,8 +169,8 @@ public Storage getStorage() {
}

@Override
public void addArticle(String url, byte[] articleContent) throws IOException {
storage.addArticle(url, articleContent);
public Optional<Path> addArticle(String url, byte[] articleContent) throws IOException {
return storage.addArticle(url, articleContent);
}

//=========== Filtered Entry List Accessors =============================================================
Expand Down
34 changes: 32 additions & 2 deletions src/main/java/seedu/address/model/entry/Entry.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;

import seedu.address.model.tag.Tag;
Expand All @@ -23,6 +24,7 @@ public class Entry {
// Data fields
private final Address address;
private final Set<Tag> tags = new HashSet<>();
private final Optional<Link> offlineLink;

/**
* Every field must be present and not null.
Expand All @@ -32,6 +34,22 @@ public Entry(Title title, Description description, Link link, Address address, S
this.title = title;
this.description = description;
this.link = link;
this.offlineLink = Optional.empty();
this.address = address;
this.tags.addAll(tags);
}

/**
* Every field must be present and not null.
*/
public Entry(Title title, Description description,
Link link, Optional<Link> offlineLink,
Address address, Set<Tag> tags) {
requireAllNonNull(title, description, link, address, tags);
this.title = title;
this.description = description;
this.link = link;
this.offlineLink = offlineLink;
this.address = address;
this.tags.addAll(tags);
}
Expand All @@ -48,6 +66,14 @@ public Link getLink() {
return link;
}

public Optional<Link> getOfflineLink() {
return offlineLink;
}

public Link getOfflineOrOriginalLink() {
return offlineLink.orElse(link);
}

public Address getAddress() {
return address;
}
Expand Down Expand Up @@ -108,8 +134,12 @@ public String toString() {
.append(" Description: ")
.append(getDescription())
.append(" Link: ")
.append(getLink())
.append(" Address: ")
.append(getLink());
offlineLink.ifPresent(link1 ->
builder.append(" Offline link: ")
.append(link1)
);
builder.append(" Address: ")
.append(getAddress())
.append(" Tags: ");
getTags().forEach(builder::append);
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/seedu/address/storage/ArticleStorage.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;

/**
* Represents a storage for articles.
Expand All @@ -19,7 +20,7 @@ public interface ArticleStorage {
* @param url cannot be null.
* @throws IOException if there was any problem writing to the file.
*/
void addArticle(String url, byte[] articleContent) throws IOException;
Optional<Path> addArticle(String url, byte[] articleContent) throws IOException;

/**
* Converts a given url to a Path where the article would be stored.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.nio.file.Path;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Optional;
import java.util.logging.Logger;

import org.apache.commons.codec.binary.Base32;
Expand All @@ -30,13 +31,15 @@ public Path getArticleDataDirectoryPath() {
}

@Override
public void addArticle(String url, byte[] articleContent) throws IOException {
public Optional<Path> addArticle(String url, byte[] articleContent) throws IOException {
Path targetPath = getArticlePath(url);

// Ensure data directory exists
FileUtil.createDirectory(directoryPath);

FileUtil.writeToFile(targetPath, articleContent);

return Optional.of(targetPath);
}

/**
Expand All @@ -52,7 +55,7 @@ private String urlToFilename(String url) throws NoSuchAlgorithmException {
byte[] truncatedHash = new byte[16];
System.arraycopy(encodedHash, 0, truncatedHash, 0, 16);
byte[] hashInBase32 = new Base32().encode(truncatedHash);
return new String(hashInBase32, StandardCharsets.UTF_8);
return new String(hashInBase32, StandardCharsets.UTF_8) + ".html";
} catch (NoSuchAlgorithmException nsae) {
logger.severe("SHA-256 hash not supported on this system. Saving links cannot be done");
throw nsae;
Expand Down
64 changes: 40 additions & 24 deletions src/main/java/seedu/address/storage/JsonAdaptedEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

Expand All @@ -24,22 +25,25 @@ class JsonAdaptedEntry {

public static final String MISSING_FIELD_MESSAGE_FORMAT = "Entry's %s field is missing!";

private final String name;
private final String phone;
private final String email;
private final String title;
private final String description;
private final String link;
private final String offlineLink;
private final String address;
private final List<JsonAdaptedTag> tagged = new ArrayList<>();

/**
* Constructs a {@code JsonAdaptedEntry} with the given entry details.
*/
@JsonCreator
public JsonAdaptedEntry(@JsonProperty("name") String name, @JsonProperty("phone") String phone,
@JsonProperty("email") String email, @JsonProperty("address") String address,
public JsonAdaptedEntry(@JsonProperty("title") String title, @JsonProperty("description") String description,
@JsonProperty("link") String link, @JsonProperty("offlineLink") String offlineLink,
@JsonProperty("address") String address,
@JsonProperty("tagged") List<JsonAdaptedTag> tagged) {
this.name = name;
this.phone = phone;
this.email = email;
this.title = title;
this.description = description;
this.link = link;
this.offlineLink = offlineLink;
this.address = address;
if (tagged != null) {
this.tagged.addAll(tagged);
Expand All @@ -50,9 +54,10 @@ public JsonAdaptedEntry(@JsonProperty("name") String name, @JsonProperty("phone"
* Converts a given {@code Entry} into this class for Jackson use.
*/
public JsonAdaptedEntry(Entry source) {
name = source.getTitle().fullTitle;
phone = source.getDescription().value;
email = source.getLink().value;
title = source.getTitle().fullTitle;
description = source.getDescription().value;
link = source.getLink().value;
offlineLink = source.getOfflineLink().isPresent() ? source.getOfflineLink().get().value : "";
address = source.getAddress().value;
tagged.addAll(source.getTags().stream()
.map(JsonAdaptedTag::new)
Expand All @@ -70,30 +75,41 @@ public Entry toModelType() throws IllegalValueException {
personTags.add(tag.toModelType());
}

if (name == null) {
if (title == null) {
throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Title.class.getSimpleName()));
}
if (!Title.isValidConstructionTitle(name)) {
throw new IllegalValueException(Title.formExceptionMessage(name));
if (!Title.isValidConstructionTitle(title)) {
throw new IllegalValueException(Title.formExceptionMessage(title));
}
final Title modelTitle = new Title(name);
final Title modelTitle = new Title(title);

if (phone == null) {
if (description == null) {
throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT,
Description.class.getSimpleName()));
}
if (!Description.isValidConstructionDescription(phone)) {
throw new IllegalValueException(Description.formExceptionMessage(phone));
if (!Description.isValidConstructionDescription(description)) {
throw new IllegalValueException(Description.formExceptionMessage(description));
}
final Description modelDescription = new Description(phone);
final Description modelDescription = new Description(description);

if (email == null) {
if (link == null) {
throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Link.class.getSimpleName()));
}
if (!Link.isValidConstructionLink(email)) {
throw new IllegalValueException(Link.formExceptionMessage(email));
if (!Link.isValidConstructionLink(link)) {
throw new IllegalValueException(Link.formExceptionMessage(link));
}
final Link modelLink = new Link(email);
final Link modelLink = new Link(link);

if (offlineLink == null) {
throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Link.class.getSimpleName()));
}
if (!offlineLink.isEmpty() && !Link.isValidConstructionLink(offlineLink)) {
throw new IllegalValueException(Link.formExceptionMessage(offlineLink));
}
final Optional<Link> modelOfflineLink =
offlineLink.isEmpty()
? Optional.empty()
: Optional.of(new Link(offlineLink));

if (address == null) {
throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName()));
Expand All @@ -104,7 +120,7 @@ public Entry toModelType() throws IllegalValueException {
final Address modelAddress = new Address(address);

final Set<Tag> modelTags = new HashSet<>(personTags);
return new Entry(modelTitle, modelDescription, modelLink, modelAddress, modelTags);
return new Entry(modelTitle, modelDescription, modelLink, modelOfflineLink, modelAddress, modelTags);
}

}
2 changes: 1 addition & 1 deletion src/main/java/seedu/address/storage/Storage.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ public interface Storage extends EntryBookStorage, UserPrefsStorage, ArticleStor
void saveAddressBook(ReadOnlyEntryBook addressBook) throws IOException;

@Override
void addArticle(String url, byte[] articleContent) throws IOException;
Optional<Path> addArticle(String url, byte[] articleContent) throws IOException;

}
4 changes: 2 additions & 2 deletions src/main/java/seedu/address/storage/StorageManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ public Path getArticleDataDirectoryPath() {
}

@Override
public void addArticle(String url, byte[] content) throws IOException {
articleStorage.addArticle(url, content);
public Optional<Path> addArticle(String url, byte[] content) throws IOException {
return articleStorage.addArticle(url, content);
}

@Override
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/seedu/address/ui/BrowserPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ private void handleFailed() {
* @param entry entry to load
*/
private void loadEntryPage(Entry entry) {
loadPage(entry.getLink().value);
loadPage(entry.getOfflineOrOriginalLink().value);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
{
"persons": [ {
"name": "Valid Title!",
"phone": "Val1d-C@mment! ~ !",
"email": "https://hans.example.com",
"title": "Valid Title!",
"description": "Val1d-C@mment! ~ !",
"link": "https://hans.example.com",
"offlineLink": "",
"address": "4th street"
}, {
"name": "Entry With Invalid Link Field",
"phone": "Oh no!",
"email": "[email protected]",
"title": "Entry With Invalid Link Field",
"description": "Oh no!",
"link": "[email protected]",
"offlineLink": "",
"address": "4th street"
} ]
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"persons": [ {
"name": "Entry with invalid link field",
"phone": "Oh no!",
"email": "[email protected]",
"title": "Entry with invalid link field",
"description": "Oh no!",
"link": "[email protected]",
"offlineLink": "",
"address": "4th street"
} ]
}
Loading

0 comments on commit 6dd6435

Please sign in to comment.