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