Skip to content
Permalink
Browse files
Adding E parameter to the Source.Builder so users of Source.newFromTe…
…xt(...).build() doesn't have to catch any IOException
  • Loading branch information
Jaroslav Tulach committed Jun 8, 2016
1 parent 01de670 commit a61f1e18356399ce6a8a2fbffa2b2a9fdc0e5301
Showing 3 changed files with 74 additions and 34 deletions.
@@ -333,14 +333,14 @@ public void fileWithReload() throws Exception {

@Test
public void normalSourceIsntInternal() throws IOException {
Source source = Source.newWithText("anything").mimeType("text/plain").build();
Source source = Source.newFromText("anything").mimeType("text/plain").build();

assertFalse("Not internal", source.isInternal());
}

@Test
public void markSourceAsInternal() throws IOException {
Source source = Source.newWithText("anything internal").mimeType("text/plain").internal().build();
Source source = Source.newFromText("anything internal").mimeType("text/plain").internal().build();

assertTrue("This source is internal", source.isInternal());
}
@@ -327,14 +327,14 @@ public void fileWithReload() throws Exception {

@Test
public void normalSourceIsntInternal() throws IOException {
Source source = Source.newWithText("anything").mimeType("text/plain").build();
Source source = Source.newFromText("anything").mimeType("text/plain").build();

assertFalse("Not internal", source.isInternal());
}

@Test
public void markSourceAsInternal() throws IOException {
Source source = Source.newWithText("anything internal").mimeType("text/plain").internal().build();
Source source = Source.newFromText("anything internal").mimeType("text/plain").internal().build();

assertTrue("This source is internal", source.isInternal());
}
@@ -167,7 +167,7 @@ public static Source find(String name) {
* @return new instance of builder
* @since 0.15
*/
public static Builder<Source> newFromFile(File file) {
public static Builder<Source,IOException> newFromFile(File file) {
return EMPTY.new Builder<>(file);
}

@@ -278,7 +278,18 @@ public static Source fromText(CharSequence chars, String name) {
return new SourceImpl(content);
}

public static Builder<Void> newWithText(String text) {
/** Builds new {@link Source source} from a provided text. One needs
* to specify a {@link Builder#mimeType(java.lang.String)}, possibly a
* {@link Builder#name(java.lang.String)} and other attributes and then
* can {@link Builder#build()} a new instance of the source. Sample usage:
*
* {@link SourceSnippets#fromAString}
*
* @param text the text to be returned by {@link Source#getCode()}
* @return new builder to configure additional properties
* @since 0.15
*/
public static Builder<Void,RuntimeException> newFromText(String text) {
return EMPTY.new Builder<>(text);
}

@@ -385,7 +396,7 @@ public static Source fromURL(URL url, String description) throws IOException {
return new SourceImpl(content);
}

public static Builder<Source> newFromURL(URL url) {
public static Builder<Source,IOException> newFromURL(URL url) {
return EMPTY.new Builder<>(url);
}

@@ -418,8 +429,7 @@ public static Source fromReader(Reader reader, String description) throws IOExce
* @return new builder to configure and {@link Builder#build() construct} {@link Source} from
* @since 0.15
*/
public static Builder<Void> newFromReader(Reader reader) {
// TBD: read only once vs. build twice
public static Builder<Void,IOException> newFromReader(Reader reader) {
return EMPTY.new Builder<>(reader);
}

@@ -986,7 +996,12 @@ final boolean equalAttributes(Source other) {
Objects.equals(getPath(), other.getPath());
}

public final class Builder<R> {
@SuppressWarnings("unchecked")
static <E extends Exception> E raise(Class<E> type, Exception ex) throws E {
throw (E)ex;
}

public final class Builder<R,E extends Exception> {
private final Object source;
private String name;
private String path;
@@ -998,21 +1013,21 @@ private Builder(Object source) {
this.source = source;
}

public Builder<R> name(String newName) {
public Builder<R,E> name(String newName) {
this.name = newName;
return this;
}

Builder<R> path(String p) {
Builder<R,E> path(String p) {
this.path = p;
return this;
}

@SuppressWarnings("unchecked")
public Builder<Source> mimeType(String newMimeType) {
public Builder<Source,E> mimeType(String newMimeType) {
Objects.nonNull(newMimeType);
this.mime = newMimeType;
return (Builder<Source>) this;
return (Builder<Source,E>) this;
}

/**
@@ -1023,39 +1038,64 @@ public Builder<Source> mimeType(String newMimeType) {
* @return the instance of this builder
* @since 0.15
*/
public Builder<R> internal() {
public Builder<R,E> internal() {
this.internal = true;
return this;
}

public Builder<R> content(String code) {
public Builder<R,E> content(String code) {
this.content = code;
return this;
}

public Builder<R> content(byte[] arr, int offset, int length, Charset encoding) {
public Builder<R,E> content(byte[] arr, int offset, int length, Charset encoding) {
this.content = new String(arr, offset, length, encoding);
return this;
}

/** Uses configuration of this builder to create new {@link Source} object.
* The return value is parametrized to ensure your code doesn't
* compile until you specify a MIME type:
* <ul>
* <li>either via file related
* methods like {@link Source#newFromFile(java.io.File)} that can
* guess the MIME type</li>
* <li>or directly via {@link #mimeType(java.lang.String)} method
* on this builder
* </ul>
* This method may throw an exception - especially when dealing with
* files (e.g. {@link Source#newFromURL(java.net.URL)},
* {@link Source#newFromFile(java.io.File)} or {@link Source#newFromReader(java.io.Reader)}
* this method may throw {@link IOException} that one needs to deal with.
* In case of other building styles (like {@link Source#newFromText(java.lang.String)}
* one doesn't need to capture any exception when calling this method.
*
* @return the source object
* @throws E exception if something went wrong while creating the source
* @since 0.15
*/
@SuppressWarnings("unchecked")
public R build() throws IOException {
public R build() throws E {
Content holder;
if (source instanceof File) {
holder = buildFile();
} else if (source instanceof Reader) {
holder = buildReader();
} else if (source instanceof URL) {
holder = buildURL();
} else {
holder = buildString();
}
String type = this.mime == null ? holder.findMimeType() : this.mime;
if (type == null) {
throw new IOException("Unknown mime type for " + source);
try {
if (source instanceof File) {
holder = buildFile();
} else if (source instanceof Reader) {
holder = buildReader();
} else if (source instanceof URL) {
holder = buildURL();
} else {
holder = buildString();
}
String type = this.mime == null ? holder.findMimeType() : this.mime;
if (type == null) {
throw new IllegalStateException("Unknown mime type for " + source);
}
SourceImpl ret = new SourceImpl(holder, type, name, internal);
return (R) ret;
} catch (IOException ex) {
throw raise(RuntimeException.class, ex);
}
SourceImpl ret = new SourceImpl(holder, type, name, internal);
return (R) ret;
}

private Content buildFile() throws IOException {
@@ -1145,9 +1185,9 @@ public static Source fromReader() throws IOException {
return source;
}

public static Source fromAString() throws Exception {
public static Source fromAString() {
// BEGIN: SourceSnippets#fromAString
Source source = Source.newWithText("function() {\n"
Source source = Source.newFromText("function() {\n"
+ " return 'Hi';\n"
+ "}\n")
.name("hi.js")

0 comments on commit a61f1e1

Please sign in to comment.