You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by iv...@apache.org on 2012/01/31 07:52:59 UTC

git commit: initial Optional impl

Updated Branches:
  refs/heads/sandbox/optional [created] 676bd3863


initial Optional impl


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/676bd386
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/676bd386
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/676bd386

Branch: refs/heads/sandbox/optional
Commit: 676bd3863c5781703102b524d440d0145bb76a2a
Parents: d007c13
Author: Igor Vaynberg <ig...@gmail.com>
Authored: Mon Jan 30 22:48:57 2012 -0800
Committer: Igor Vaynberg <ig...@gmail.com>
Committed: Mon Jan 30 22:48:57 2012 -0800

----------------------------------------------------------------------
 .../wicket/ajax/markup/html/AjaxFallbackLink.java  |   17 +-
 .../org/apache/wicket/markup/html/form/Check.java  |    2 +-
 .../wicket/markup/html/form/FormComponent.java     |    5 +-
 .../org/apache/wicket/markup/html/form/Radio.java  |    3 +-
 .../apache/wicket/markup/html/tree/BaseTree.java   |    9 +-
 .../java/org/apache/wicket/MockPanelWithLink.java  |   10 +-
 .../wicket/ajax/AjaxHeaderContributionPage.java    |   13 +-
 .../wicket/ajax/AjaxHeaderContributionPage2.java   |   19 +-
 .../org/apache/wicket/ajax/DomReadyOrderPage.java  |    5 +-
 .../util/tester/apps_5/AjaxLinkClickTest.java      |    9 +-
 .../apache/wicket/util/tester/apps_6/LinkPage.java |    5 +-
 .../java/org/apache/wicket/util/lang/Optional.java |  256 +++++++++++++++
 12 files changed, 311 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/676bd386/wicket-core/src/main/java/org/apache/wicket/ajax/markup/html/AjaxFallbackLink.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/markup/html/AjaxFallbackLink.java b/wicket-core/src/main/java/org/apache/wicket/ajax/markup/html/AjaxFallbackLink.java
index fe78ecb..d1af957 100644
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/markup/html/AjaxFallbackLink.java
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/markup/html/AjaxFallbackLink.java
@@ -24,6 +24,7 @@ import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
 import org.apache.wicket.markup.ComponentTag;
 import org.apache.wicket.markup.html.link.Link;
 import org.apache.wicket.model.IModel;
+import org.apache.wicket.util.lang.Optional;
 
 /**
  * An ajax link that will degrade to a normal request if ajax is not available or javascript is
@@ -139,16 +140,22 @@ public abstract class AjaxFallbackLink<T> extends Link<T> implements IAjaxLink
 	@Override
 	public final void onClick()
 	{
-		onClick(null);
+		onClick((AjaxRequestTarget)null);
+	}
+
+	@Override
+	public void onClick(final AjaxRequestTarget target)
+	{
+		onClick(Optional.of(target));
 	}
 
 	/**
 	 * Callback for the onClick event. If ajax failed and this event was generated via a normal link
-	 * the target argument will be null
+	 * the target optional will contain a null
 	 * 
 	 * @param target
-	 *            ajax target if this linked was invoked using ajax, null otherwise
+	 *            ajax request target
 	 */
-	@Override
-	public abstract void onClick(final AjaxRequestTarget target);
+	public abstract void onClick(final Optional<AjaxRequestTarget> target);
+
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/676bd386/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Check.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Check.java b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Check.java
index 85dfb8c..3746cab 100644
--- a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Check.java
+++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Check.java
@@ -176,7 +176,7 @@ public class Check<T> extends LabeledWebMarkupContainer
 
 		if (group.hasRawInput())
 		{
-			final String raw = group.getRawInput();
+			final String raw = group.getRawInput().get(null);
 			if (!Strings.isEmpty(raw))
 			{
 				final String[] values = raw.split(FormComponent.VALUE_SEPARATOR);

http://git-wip-us.apache.org/repos/asf/wicket/blob/676bd386/wicket-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java
index ec7b2f9..96aa942 100644
--- a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java
+++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java
@@ -42,6 +42,7 @@ import org.apache.wicket.model.Model;
 import org.apache.wicket.util.convert.ConversionException;
 import org.apache.wicket.util.convert.IConverter;
 import org.apache.wicket.util.lang.Args;
+import org.apache.wicket.util.lang.Optional;
 import org.apache.wicket.util.lang.WicketObjects;
 import org.apache.wicket.util.string.StringList;
 import org.apache.wicket.util.string.StringValue;
@@ -781,9 +782,9 @@ public abstract class FormComponent<T> extends LabeledWebMarkupContainer
 	 * 
 	 * @return The raw form input that is stored for this formcomponent
 	 */
-	public final String getRawInput()
+	public final Optional<String> getRawInput()
 	{
-		return NO_RAW_INPUT.equals(rawInput) ? null : rawInput;
+		return NO_RAW_INPUT.equals(rawInput) ? Optional.<String> ofNull() : Optional.of(rawInput);
 	}
 
 	/**

http://git-wip-us.apache.org/repos/asf/wicket/blob/676bd386/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Radio.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Radio.java b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Radio.java
index e4d0cab..7ec502d 100644
--- a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Radio.java
+++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Radio.java
@@ -169,8 +169,7 @@ public class Radio<T> extends LabeledWebMarkupContainer
 		// checked attribute, first check if there was a raw input on the group.
 		if (group.hasRawInput())
 		{
-			String rawInput = group.getRawInput();
-			if (rawInput != null && rawInput.equals(value))
+			if (group.getRawInput().isValueEqualTo(value))
 			{
 				tag.put("checked", "checked");
 			}

http://git-wip-us.apache.org/repos/asf/wicket/blob/676bd386/wicket-core/src/main/java/org/apache/wicket/markup/html/tree/BaseTree.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/html/tree/BaseTree.java b/wicket-core/src/main/java/org/apache/wicket/markup/html/tree/BaseTree.java
index 4c6dd29..63f3643 100644
--- a/wicket-core/src/main/java/org/apache/wicket/markup/html/tree/BaseTree.java
+++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/tree/BaseTree.java
@@ -35,6 +35,7 @@ import org.apache.wicket.model.IModel;
 import org.apache.wicket.request.Response;
 import org.apache.wicket.request.resource.PackageResourceReference;
 import org.apache.wicket.request.resource.ResourceReference;
+import org.apache.wicket.util.lang.Optional;
 import org.apache.wicket.util.string.Strings;
 
 /**
@@ -415,13 +416,11 @@ public abstract class BaseTree extends AbstractTree
 			{
 				private static final long serialVersionUID = 1L;
 
-				/**
-				 * @see org.apache.wicket.ajax.markup.html.AjaxFallbackLink#onClick(org.apache.wicket.ajax.AjaxRequestTarget)
-				 */
 				@Override
-				public void onClick(AjaxRequestTarget target)
+				public void onClick(Optional<AjaxRequestTarget> target)
 				{
-					callback.onClick(target);
+					// FIXME OPTIONAL should not use getUnsafe()
+					callback.onClick(target.getUnsafe());
 				}
 			};
 		}

http://git-wip-us.apache.org/repos/asf/wicket/blob/676bd386/wicket-core/src/test/java/org/apache/wicket/MockPanelWithLink.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/MockPanelWithLink.java b/wicket-core/src/test/java/org/apache/wicket/MockPanelWithLink.java
index ce20aca..1a3d69a 100644
--- a/wicket-core/src/test/java/org/apache/wicket/MockPanelWithLink.java
+++ b/wicket-core/src/test/java/org/apache/wicket/MockPanelWithLink.java
@@ -21,6 +21,7 @@ import org.apache.wicket.ajax.markup.html.AjaxFallbackLink;
 import org.apache.wicket.markup.IMarkupCacheKeyProvider;
 import org.apache.wicket.markup.IMarkupResourceStreamProvider;
 import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.util.lang.Optional;
 import org.apache.wicket.util.resource.IResourceStream;
 import org.apache.wicket.util.resource.StringResourceStream;
 
@@ -46,9 +47,9 @@ public abstract class MockPanelWithLink extends Panel
 		add(new AjaxFallbackLink<Void>("link")
 		{
 			@Override
-			public void onClick(AjaxRequestTarget target)
+			public void onClick(Optional<AjaxRequestTarget> target)
 			{
-				MockPanelWithLink.this.onLinkClick(target);
+				MockPanelWithLink.this.onLinkClick(target.getUnsafe());
 			}
 		});
 	}
@@ -57,8 +58,9 @@ public abstract class MockPanelWithLink extends Panel
 	 * The callback to execute when the link is clicked.
 	 * 
 	 * @param target
-	 *            the current Ajax request target. May be {@code null} if
-	 *            {@link org.apache.wicket.util.tester.BaseWicketTester#clickLink(String, boolean false)} is used.
+	 *            the current Ajax request target. May be {@code null} if {@link
+	 *            org.apache.wicket.util.tester.BaseWicketTester#clickLink(String, boolean false)}
+	 *            is used.
 	 */
 	protected abstract void onLinkClick(AjaxRequestTarget target);
 

http://git-wip-us.apache.org/repos/asf/wicket/blob/676bd386/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxHeaderContributionPage.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxHeaderContributionPage.java b/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxHeaderContributionPage.java
index a7ccde9..ca6c6f0 100644
--- a/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxHeaderContributionPage.java
+++ b/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxHeaderContributionPage.java
@@ -19,6 +19,7 @@ package org.apache.wicket.ajax;
 import org.apache.wicket.Component;
 import org.apache.wicket.ajax.markup.html.AjaxFallbackLink;
 import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.util.lang.Optional;
 
 /**
  * @author jcompagner
@@ -43,13 +44,13 @@ public class AjaxHeaderContributionPage extends WebPage
 			private static final long serialVersionUID = 1L;
 
 			@Override
-			public void onClick(AjaxRequestTarget target)
+			public void onClick(Optional<AjaxRequestTarget> target)
 			{
-				target.prependJavaScript("prepend();");
-				target.add(test1);
-				target.add(test2);
-				target.add(test3);
-				target.appendJavaScript("append();");
+				target.get().prependJavaScript("prepend();");
+				target.get().add(test1);
+				target.get().add(test2);
+				target.get().add(test3);
+				target.get().appendJavaScript("append();");
 			}
 		});
 	}

http://git-wip-us.apache.org/repos/asf/wicket/blob/676bd386/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxHeaderContributionPage2.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxHeaderContributionPage2.java b/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxHeaderContributionPage2.java
index 44c6d4f..327b9ea 100644
--- a/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxHeaderContributionPage2.java
+++ b/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxHeaderContributionPage2.java
@@ -19,6 +19,7 @@ package org.apache.wicket.ajax;
 import org.apache.wicket.Component;
 import org.apache.wicket.ajax.markup.html.AjaxFallbackLink;
 import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.util.lang.Optional;
 
 /**
  * @author jcompagner
@@ -50,16 +51,16 @@ public class AjaxHeaderContributionPage2 extends WebPage
 			private static final long serialVersionUID = 1L;
 
 			@Override
-			public void onClick(AjaxRequestTarget target)
+			public void onClick(Optional<AjaxRequestTarget> target)
 			{
-				target.prependJavaScript("prepend();");
-				target.add(test1);
-				target.add(test2);
-				target.add(test3);
-				target.add(btest1);
-				target.add(btest2);
-				target.add(btest3);
-				target.appendJavaScript("append();");
+				target.get().prependJavaScript("prepend();");
+				target.get().add(test1);
+				target.get().add(test2);
+				target.get().add(test3);
+				target.get().add(btest1);
+				target.get().add(btest2);
+				target.get().add(btest3);
+				target.get().appendJavaScript("append();");
 			}
 		});
 	}

http://git-wip-us.apache.org/repos/asf/wicket/blob/676bd386/wicket-core/src/test/java/org/apache/wicket/ajax/DomReadyOrderPage.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/ajax/DomReadyOrderPage.java b/wicket-core/src/test/java/org/apache/wicket/ajax/DomReadyOrderPage.java
index 4cef699..782cbc5 100644
--- a/wicket-core/src/test/java/org/apache/wicket/ajax/DomReadyOrderPage.java
+++ b/wicket-core/src/test/java/org/apache/wicket/ajax/DomReadyOrderPage.java
@@ -20,6 +20,7 @@ import org.apache.wicket.ajax.markup.html.AjaxFallbackLink;
 import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
 import org.apache.wicket.markup.html.WebPage;
 import org.apache.wicket.markup.html.internal.HtmlHeaderContainer;
+import org.apache.wicket.util.lang.Optional;
 
 /**
  * @author jcompagner
@@ -60,9 +61,9 @@ public class DomReadyOrderPage extends WebPage
 		}
 
 		@Override
-		public void onClick(AjaxRequestTarget target)
+		public void onClick(Optional<AjaxRequestTarget> target)
 		{
-			target.add(this);
+			target.get().add(this);
 		}
 	}
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/676bd386/wicket-core/src/test/java/org/apache/wicket/util/tester/apps_5/AjaxLinkClickTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/util/tester/apps_5/AjaxLinkClickTest.java b/wicket-core/src/test/java/org/apache/wicket/util/tester/apps_5/AjaxLinkClickTest.java
index f8a8e25..b6d6aa5 100644
--- a/wicket-core/src/test/java/org/apache/wicket/util/tester/apps_5/AjaxLinkClickTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/util/tester/apps_5/AjaxLinkClickTest.java
@@ -21,6 +21,7 @@ import org.apache.wicket.WicketTestCase;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.AjaxFallbackLink;
 import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.util.lang.Optional;
 import org.junit.Before;
 
 
@@ -87,10 +88,10 @@ public class AjaxLinkClickTest extends WicketTestCase
 			private static final long serialVersionUID = 1L;
 
 			@Override
-			public void onClick(AjaxRequestTarget target)
+			public void onClick(Optional<AjaxRequestTarget> target)
 			{
 				linkClicked = true;
-				ajaxRequestTarget = target;
+				ajaxRequestTarget = target.getUnsafe();
 			}
 		});
 
@@ -115,10 +116,10 @@ public class AjaxLinkClickTest extends WicketTestCase
 			private static final long serialVersionUID = 1L;
 
 			@Override
-			public void onClick(AjaxRequestTarget target)
+			public void onClick(Optional<AjaxRequestTarget> target)
 			{
 				linkClicked = true;
-				ajaxRequestTarget = target;
+				ajaxRequestTarget = target.getUnsafe();
 			}
 		});
 

http://git-wip-us.apache.org/repos/asf/wicket/blob/676bd386/wicket-core/src/test/java/org/apache/wicket/util/tester/apps_6/LinkPage.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/util/tester/apps_6/LinkPage.java b/wicket-core/src/test/java/org/apache/wicket/util/tester/apps_6/LinkPage.java
index 9e6dc21..c129eaa 100644
--- a/wicket-core/src/test/java/org/apache/wicket/util/tester/apps_6/LinkPage.java
+++ b/wicket-core/src/test/java/org/apache/wicket/util/tester/apps_6/LinkPage.java
@@ -23,6 +23,7 @@ import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
 import org.apache.wicket.markup.html.WebPage;
 import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.util.lang.Optional;
 import org.apache.wicket.util.tester.WicketTester;
 
 /**
@@ -91,7 +92,7 @@ public class LinkPage extends WebPage
 			private static final long serialVersionUID = 1L;
 
 			@Override
-			public void onClick(AjaxRequestTarget target)
+			public void onClick(Optional<AjaxRequestTarget> target)
 			{
 				getRequestCycle().setResponsePage(ResultPage.class);
 			}
@@ -102,7 +103,7 @@ public class LinkPage extends WebPage
 			private static final long serialVersionUID = 1L;
 
 			@Override
-			public void onClick(AjaxRequestTarget target)
+			public void onClick(Optional<AjaxRequestTarget> target)
 			{
 				getRequestCycle().setResponsePage(new ResultPage("A special label"));
 			}

http://git-wip-us.apache.org/repos/asf/wicket/blob/676bd386/wicket-util/src/main/java/org/apache/wicket/util/lang/Optional.java
----------------------------------------------------------------------
diff --git a/wicket-util/src/main/java/org/apache/wicket/util/lang/Optional.java b/wicket-util/src/main/java/org/apache/wicket/util/lang/Optional.java
new file mode 100644
index 0000000..1c33575
--- /dev/null
+++ b/wicket-util/src/main/java/org/apache/wicket/util/lang/Optional.java
@@ -0,0 +1,256 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.wicket.util.lang;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ * Represents an optional value.
+ * <p>
+ * This class aids in making handling of possible {@code null} values (whether return values or
+ * parameter values) explicit and hopefully reduces the number of {@link NullPointerException}s that
+ * will be thrown.
+ * </p>
+ * <p>
+ * It also makes tracking down NPEs easier by not allowing {@code null} return values to be
+ * propagated as parameters to further function calls, it does it by making {@link #get()} throw an
+ * NPE if called on an {@link Optional} constructed with a {@code null} value.
+ * </p>
+ * <p>
+ * By supporting {@link Iterable} this class allows the developer to rewrite code like this: <code>
+ * if (optional.isSet()) {
+ *    optional.get().foo();
+ *    optional.get().bar();
+ *    optional.get().baz();
+ * }
+ * </code> With the following: <code>
+ * for (Value value:optional) {
+ *   value.foo();
+ *   value.bar();
+ *   value.baz();
+ * }
+ * </code> which some developers find easier to read.
+ * </p>
+ * 
+ * @author igor
+ * @param <T>
+ */
+public final class Optional<T> implements Iterable<T>, Serializable
+{
+	private static final long serialVersionUID = 1L;
+
+	private static final Optional<Void> NULL = new Optional<Void>(null);
+
+	private static final Iterator<?> EMPTY_ITERATOR = Collections.emptyList().iterator();
+
+	private final T value;
+
+	private Optional(T value)
+	{
+		this.value = value;
+	}
+
+	/**
+	 * Gets the stored value or throws {@link NullPointerException} if the value is {@code null}
+	 * 
+	 * @throws NullPointerException
+	 *             if the value is {@code null}
+	 * 
+	 * @return stored value
+	 */
+	public T get()
+	{
+		if (value == null)
+		{
+			throw new NullPointerException();
+		}
+		return value;
+	}
+
+	/**
+	 * Gets the stored value or returns {@code defaultValue} if value is {@code null}
+	 * 
+	 * @param defaultValue
+	 *            default value
+	 * 
+	 * @return stored value or {@code defaultValue}
+	 */
+	public T get(T defaultValue)
+	{
+		if (value == null)
+		{
+			return defaultValue;
+		}
+		return value;
+	}
+
+	/**
+	 * @return {@code true} iff value is not {@code null}
+	 */
+	public boolean exists()
+	{
+		return value != null;
+	}
+
+	/**
+	 * @return {code true} if the store value is {@code null}
+	 */
+	public boolean isNull()
+	{
+		return value == null;
+	}
+
+	/**
+	 * @return {code true} if the store value is not {@code null}
+	 */
+	public boolean isNotNull()
+	{
+		return value != null;
+	}
+
+	/**
+	 * @return {code true} if the store value is not {@code null}
+	 */
+	public boolean isSet()
+	{
+		return value != null;
+	}
+
+	/**
+	 * @return {code true} if the store value is {@code null}
+	 */
+	public boolean isNotSet()
+	{
+		return value == null;
+	}
+
+	@SuppressWarnings("unchecked")
+	public Iterator<T> iterator()
+	{
+		if (value == null)
+		{
+			return (Iterator<T>)EMPTY_ITERATOR;
+		}
+		else
+		{
+			return Collections.singleton(value).iterator();
+		}
+	}
+
+	/**
+	 * Factory method for creating {@link Optional} values
+	 * 
+	 * @param <Z>
+	 * @param value
+	 * @return optional that represents the specified value
+	 */
+	@SuppressWarnings("unchecked")
+	public static <Z> Optional<Z> of(Z value)
+	{
+		if (value == null)
+		{
+			return (Optional<Z>)NULL;
+		}
+		else
+		{
+			return new Optional<Z>(value);
+		}
+	}
+
+	/**
+	 * Factory method for creating an {@link Optional} value that represents a {@code null}
+	 * 
+	 * @param <T>
+	 * @return optional that represents a {@code null}
+	 */
+	@SuppressWarnings("unchecked")
+	public static <Z> Optional<Z> ofNull()
+	{
+		return (Optional<Z>)NULL;
+	}
+
+	/**
+	 * Checks if the stored value is the same as the {@code other} value
+	 * 
+	 * @param other
+	 * @return {@code true} iff stored value == other
+	 */
+	public boolean isValueSameAs(T other)
+	{
+		return value == other;
+	}
+
+	/**
+	 * A null-safe checks to see if the stored value is equal to the {@code other} value
+	 * 
+	 * @param other
+	 * @return {@code true} iff stored value equals other
+	 */
+	public boolean isValueEqualTo(T other)
+	{
+		return Objects.equal(value, other);
+	}
+
+
+	@Override
+	public int hashCode()
+	{
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((value == null) ? 0 : value.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj)
+	{
+		if (this == obj)
+		{
+			return true;
+		}
+		if (obj == null)
+		{
+			return false;
+		}
+		if (!(obj instanceof Optional))
+		{
+			return false;
+		}
+		Optional<?> other = (Optional<?>)obj;
+		return Objects.equal(value, other.value);
+	}
+
+	/**
+	 * @return either the String "null" or the String "value: " followed by the contained value's
+	 *         toString
+	 */
+	@Override
+	public String toString()
+	{
+		return "[Optional value=" + value + "]";
+	}
+
+	/**
+	 * Performs an unsafe {@link #get()}, may return {@code null}
+	 * 
+	 * @return stored {@code value} including {@code null}
+	 */
+	public T getUnsafe()
+	{
+		return value;
+	}
+}
\ No newline at end of file