commit 6a3ae6ac2329e51fe2457a0143c3df702e54c4f8 Author: Abhinav Sarkar Date: Wed Jun 2 01:18:32 2010 +0530 First Commit: Moving the project from google code to github diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..3a4681c --- /dev/null +++ b/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4eb0d3a --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.settings/* +target/* diff --git a/.project b/.project new file mode 100644 index 0000000..513f693 --- /dev/null +++ b/.project @@ -0,0 +1,23 @@ + + + nulllessj + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.maven.ide.eclipse.maven2Builder + + + + + + org.maven.ide.eclipse.maven2Nature + org.eclipse.jdt.core.javanature + + diff --git a/nulllessj.iml b/nulllessj.iml new file mode 100644 index 0000000..66a6ba1 --- /dev/null +++ b/nulllessj.iml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..26ba274 --- /dev/null +++ b/pom.xml @@ -0,0 +1,40 @@ + + 4.0.0 + + net.abhinavsarkar + nulllessj + 1.0-SNAPSHOT + jar + + nulllessj + http://github.com/abhin4v/nulllessj + + + UTF-8 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.1 + + 1.6 + 1.6 + + + + + + + + junit + junit + 4.4 + test + + + + diff --git a/src/main/java/net/abhinavsarkar/nulllessj/ContextualCallable.java b/src/main/java/net/abhinavsarkar/nulllessj/ContextualCallable.java new file mode 100644 index 0000000..7203a6d --- /dev/null +++ b/src/main/java/net/abhinavsarkar/nulllessj/ContextualCallable.java @@ -0,0 +1,26 @@ +package net.abhinavsarkar.nulllessj; + +import java.util.concurrent.Callable; + +/** + * A {@link Callable} class with context. + * + * @author Abhinav Sarkar + * + * @param type of the context + * @param type of the return value of the callable + */ +public abstract class ContextualCallable implements Callable { + + protected T context; + + /** + * Set the context. + * + * @param context the context + */ + public void setContext(final T context) { + this.context = context; + } + +} diff --git a/src/main/java/net/abhinavsarkar/nulllessj/ContextualRunnable.java b/src/main/java/net/abhinavsarkar/nulllessj/ContextualRunnable.java new file mode 100644 index 0000000..e115915 --- /dev/null +++ b/src/main/java/net/abhinavsarkar/nulllessj/ContextualRunnable.java @@ -0,0 +1,23 @@ +package net.abhinavsarkar.nulllessj; + +/** + * A {@link Runnable} class with context. + * + * @author Abhinav Sarkar + * + * @param type of the context + */ +public abstract class ContextualRunnable implements Runnable { + + protected T context; + + /** + * Set the context. + * + * @param context the context + */ + public void setContext(final T context) { + this.context = context; + } + +} diff --git a/src/main/java/net/abhinavsarkar/nulllessj/Just.java b/src/main/java/net/abhinavsarkar/nulllessj/Just.java new file mode 100644 index 0000000..6ac8706 --- /dev/null +++ b/src/main/java/net/abhinavsarkar/nulllessj/Just.java @@ -0,0 +1,64 @@ +package net.abhinavsarkar.nulllessj; + +public final class Just extends Maybe { + + private final T value; + + public Just(final T value) { + if (value == null) { + throw new NothingException(); + } + this.value = value; + } + + public static Just just(final T value) { + return new Just(value); + } + + @Override + public T get() { + return value; + } + + @Override + public boolean isNothing() { + return false; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + + @SuppressWarnings("unchecked") + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Just other = (Just) obj; + if (value == null) { + if (other.value != null) { + return false; + } + } else if (!value.equals(other.value)) { + return false; + } + return true; + } + + @Override + public String toString() { + return value.toString(); + } + +} diff --git a/src/main/java/net/abhinavsarkar/nulllessj/Maybe.java b/src/main/java/net/abhinavsarkar/nulllessj/Maybe.java new file mode 100644 index 0000000..a231b0c --- /dev/null +++ b/src/main/java/net/abhinavsarkar/nulllessj/Maybe.java @@ -0,0 +1,317 @@ +package net.abhinavsarkar.nulllessj; + +import static net.abhinavsarkar.nulllessj.Just.just; + +import java.util.concurrent.Callable; + +/** + * A container class for representing a value which 'maybe' present. + * This is an abstract class with two concrete subclasses: {@link Just} + * and {@link Nothing} which represent a present and non-present value + * respectively. + * + * @author Abhinav Sarkar + * + * @param Type of the object being wrapped. + */ +public abstract class Maybe { + + /** + * Returns if the class is {@link Nothing} + */ + abstract public boolean isNothing(); + + /** + * Returns if the class is {@link Just} + */ + public boolean isSomething() { + return !isNothing(); + } + + /** + * A convenience shortcut for {@link Maybe#get()} + */ + public T $() { + return get(); + } + + /** + * Returns the original wrapped value if the class is {@link Just}. + * Throws {@link NothingException} if the class is {@link Nothing}. + */ + abstract public T get(); + + /** + * Returns the original wrapped value if the class is {@link Just}. + * Returns the other parameter if the class is {@link Nothing}. + * + * @param other The value to return if the class is {@link Nothing}. + */ + public T getOrElse(final T other) { + if (isNothing()) { + return other; + } else { + return get(); + } + } + + /** + * Calls the callable provided if the class is {@link Nothing} and returns + * the result of the call wrapped in {@link Maybe}. + * If {@link NothingException} or {@link NullPointerException} is thrown + * while calling the callable, then returns an object of type + * {@link Nothing}. + * If any other exception is thrown while calling the callable, then the + * exception is caught and rethrown wrapped in a {@link RuntimeException}. + * + * @param Return type of the callable provided. + * @param callable The callable to call + * + * @throws RuntimeException See the description. + * + * @see Maybe#maybe + */ + public Maybe callIfNothing(final Callable callable) { + if (isNothing()) { + try { + return maybe(callable.call()); + } catch (NothingException e) { + return new Nothing(); + } catch (NullPointerException e) { + return new Nothing(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else { + return new Nothing(); + } + } + + /** + * Runs the runnable provided if the class is {@link Nothing}. + * If {@link NothingException} or {@link NullPointerException} is thrown + * while running the runnable, then the execution of the runnable terminates + * silently and this method returns. + * If any other exception is thrown while running the runnable, then the + * exception is caught and rethrown wrapped in a {@link RuntimeException}. + * + * @param runnable + * + * @throws RuntimeException See the description. + */ + public void runIfNothing(final Runnable runnable) { + if (isNothing()) { + try { + runnable.run(); + } catch (NothingException e) { + return; + } catch (NullPointerException e) { + return; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + /** + * Calls the callable provided if the class is {@link Just} and returns + * the result of the call wrapped in {@link Maybe}. + * The callable is provided the wrapped value as the context. + * If {@link NothingException} or {@link NullPointerException} is thrown + * while calling the callable, then returns an object of type + * {@link Nothing}. + * If any other exception is thrown while calling the callable, then the + * exception is caught and rethrown wrapped in a {@link RuntimeException}. + * + * @param Return type of the callable provided. + * @param callable The callable to call + * + * @throws RuntimeException See the description. + * + * @see Maybe#maybe + */ + public Maybe callIfSomething(final ContextualCallable callable) { + if (isSomething()) { + callable.setContext(get()); + try { + return maybe(callable.call()); + } catch (NothingException e) { + return new Nothing(); + } catch (NullPointerException e) { + return new Nothing(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else { + return new Nothing(); + } + } + + /** + * Calls the somethingCallable callable or the + * nothingCallable callable if the class is {@link Just} + * or {@link Nothing} respectively. + * Returns the result of the call wrapped in {@link Maybe}. + * The somethingCallable is provided the wrapped value as the context. + * If {@link NothingException} or {@link NullPointerException} is thrown + * while calling the callables, then returns an object of type + * {@link Nothing}. + * If any other exception is thrown while calling the callables, then the + * exception is caught and rethrown wrapped in a {@link RuntimeException}. + * + * @param Return type of the callables provided. + * @param somethingCallable The callable to call if the class in {@link Just} + * @param nothingCallable The callable to call if the class in {@link Nothing} + * + * @throws RuntimeException See the description. + * + * @see Maybe#maybe + */ + public Maybe callIfSomethingOrElse( + final ContextualCallable somethingCallable, + final Callable nothingCallable) { + if (isNothing()) { + return callIfNothing(nothingCallable); + } else { + return callIfSomething(somethingCallable); + } + } + + /** + * Runs the runnable provided if the class is {@link Just}. + * The runnable is provided the wrapped value as the context. + * If {@link NothingException} or {@link NullPointerException} is thrown + * while running the runnable, then the execution of the runnable terminates + * silently and this method returns. + * If any other exception is thrown while running the runnable, then the + * exception is caught and rethrown wrapped in a {@link RuntimeException}. + * + * @param runnable The runnable to run + * + * @throws RuntimeException See the description. + */ + public void runIfSomething(final ContextualRunnable runnable) { + if (isSomething()) { + runnable.setContext(get()); + try { + runnable.run(); + } catch (NothingException e) { + return; + } catch (NullPointerException e) { + return; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + /** + * Runs the somethingRunnable runnable or the + * nothingRunnable runnable if the class is {@link Just} or + * {@link Nothing} respectively. + * The somethingRunnable is provided the wrapped value as the context. + * If {@link NothingException} or {@link NullPointerException} is thrown + * while running the runnable, then the execution of the runnable terminates + * silently and this method returns. + * If any other exception is thrown while running the runnable, then the + * exception is caught and rethrown wrapped in a {@link RuntimeException}. + * + * @param somethingRunnable The runnable to run if the class in {@link Just} + * @param nothingRunnable The runnable to run if the class in {@link Nothing} + * + * @throws RuntimeException See the description. + */ + public void runIfSomethingOrElse( + final ContextualRunnable somethingRunnable, + final Runnable nothingRunnable) { + if (isNothing()) { + runIfNothing(nothingRunnable); + } else { + runIfSomething(somethingRunnable); + } + } + + /** + * The kind of the {@link Maybe} value. + */ + public static enum MaybeKind { + SOME, NONE; + } + + /** + * Returns the kind of the {@link Maybe} value + * @return the kind of the {@link Maybe} value + */ + public MaybeKind kind() { + return isNothing() ? MaybeKind.NONE : MaybeKind.SOME; + } + + /** + * Runs the runnable provided. + * If {@link NothingException} or {@link NullPointerException} is thrown + * while running the runnable, then the execution of the + * runnable terminates silently and this method returns. + * If any other exception is thrown while running the runnable, + * then the exception is caught and rethrown wrapped in a {@link RuntimeException}. + * + * @param runnable The runnable to run + * + * @throws RuntimeException See the description. + */ + public static void run(final Runnable runnable) { + try { + runnable.run(); + } catch (NothingException e) { + return; + } catch (NullPointerException e) { + return; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Calls the callable provided and returns the result of the call wrapped + * in {@link Maybe}. + * If {@link NothingException} or {@link NullPointerException} is thrown + * while calling the callable, then returns an object of type + * {@link Nothing}. + * If any other exception is thrown while calling the callable, then the + * exception is caught and rethrown wrapped in a {@link RuntimeException}. + * + * @param Return type of the callable provided. + * @param callable The callable to call + * + * @throws RuntimeException See the description. + * + * @see Maybe#maybe + */ + public static Maybe call(final Callable callable) { + try { + return maybe(callable.call()); + } catch (NothingException e) { + return new Nothing(); + } catch (NullPointerException e) { + return new Nothing(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Wraps an Object in {@link Maybe} and returns the wrapped Object. + * If obj is null then returns an instance of {@link Nothing}. + * Otherwise returns an instance of {@link Just} wrapped over obj. + * + * @param The type of the object to wrap + * @param obj The object to wrap. + */ + public static Maybe maybe(final V obj) { + if (obj == null) { + return new Nothing(); + } else { + return just(obj); + } + } + +} diff --git a/src/main/java/net/abhinavsarkar/nulllessj/Nothing.java b/src/main/java/net/abhinavsarkar/nulllessj/Nothing.java new file mode 100644 index 0000000..460bbc7 --- /dev/null +++ b/src/main/java/net/abhinavsarkar/nulllessj/Nothing.java @@ -0,0 +1,41 @@ +package net.abhinavsarkar.nulllessj; + +public final class Nothing extends Maybe { + + public Nothing() {} + + @Override + public T get() { + throw new NothingException(); + } + + @Override + public boolean isNothing() { + return true; + } + + @Override + public int hashCode() { + return -999999; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + return true; + } + + @Override + public String toString() { + return ""; + } + +} diff --git a/src/main/java/net/abhinavsarkar/nulllessj/NothingException.java b/src/main/java/net/abhinavsarkar/nulllessj/NothingException.java new file mode 100644 index 0000000..9e08f83 --- /dev/null +++ b/src/main/java/net/abhinavsarkar/nulllessj/NothingException.java @@ -0,0 +1,7 @@ +package net.abhinavsarkar.nulllessj; + +public class NothingException extends RuntimeException { + + private static final long serialVersionUID = 1L; + +}