Skip to content

Commit

Permalink
chore: use common interface for enum and string wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
Denis Anisimov committed May 5, 2021
1 parent 59498f2 commit 5e73864
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.Focusable;
Expand All @@ -41,7 +40,8 @@ public class Anchor extends HtmlContainer implements Focusable<Anchor> {
.attributeWithDefault("href", "", false);

private static final PropertyDescriptor<String, Optional<String>> targetDescriptor = PropertyDescriptors
.optionalAttributeWithDefault("target", AnchorTarget.DEFAULT.getValue());
.optionalAttributeWithDefault("target",
AnchorTarget.DEFAULT.getValue());

private static final String ROUTER_IGNORE_ATTRIBUTE = "router-ignore";

Expand Down Expand Up @@ -106,8 +106,8 @@ public Anchor(AbstractStreamResource href, String text) {
}

/**
* Creates an anchor component with the given href and components
* as children of this component.
* Creates an anchor component with the given href and components as
* children of this component.
*
* @see #setHref(AbstractStreamResource)
* @see #add(Component...)
Expand Down Expand Up @@ -206,46 +206,46 @@ public Optional<String> getTarget() {
}

/**
* Sets the target window, tab or frame for this anchor. The target is one of these
* special values:
* Sets the target window, tab or frame for this anchor. The target may be
* the one of these special values:
* <ul>
* <li><code>AnchorTarget.DEFAULT</code>: Removes the target value. This has the same effect as setting the target to <code>AnchorTarget.SELF</code>.
* <li><code>AnchorTarget.SELF</code>: Opens the link in the current context.
* <li><code>AnchorTarget.BLANK</code>: Opens the link in a new unnamed context.
* <li><code>AnchorTarget.PARENT</code>: Opens the link in the parent context, or the
* current context if there is no parent context.
* <li><code>AnchorTarget.TOP</code>: Opens the link in the top most grandparent
* <li><code>AnchorTarget.DEFAULT</code>: Removes the target value. This has
* the same effect as setting the target to <code>AnchorTarget.SELF</code>.
* <li><code>AnchorTarget.SELF</code>: Opens the link in the current
* context.
* <li><code>AnchorTarget.BLANK</code>: Opens the link in a new unnamed
* context.
* <li><code>AnchorTarget.PARENT</code>: Opens the link in the parent
* context, or the current context if there is no parent context.
* <li><code>AnchorTarget.TOP</code>: Opens the link in the top most
* grandparent context, or the current context if there is no parent
* context.
* </ul>
*
* @param target
* the target value, not null
*/
public void setTarget(AnchorTarget target) {
public void setTarget(AnchorTargetValue target) {
Objects.requireNonNull(target, "target cannot be null.");
setTarget(target.getValue());
}

/**
* Gets the target window, tab or frame value for this anchor.
*
* @see #setTarget(AnchorTarget)
* @see #setTarget(AnchorTargetValue)
* @see #getTarget()
*
* @return an optional target, or {@link AnchorTarget#DEFAULT} if no target has been
* set
* @return the target window value , or {@link AnchorTarget#DEFAULT} if no
* target has been set
*/
public Optional<AnchorTarget> getTargetEnum() {
Optional<AnchorTarget> anchorTarget = Optional.of(AnchorTarget.DEFAULT);

Optional<String> strTarget = getTarget();
public AnchorTargetValue getTargetValue() {
Optional<String> target = getTarget();

if (strTarget.isPresent()) {
String valueToFind = strTarget.get();
anchorTarget = Stream.of(AnchorTarget.values()).filter(type-> type.getValue().equals(valueToFind))
.findFirst();
if (target.isPresent()) {
return AnchorTargetValue.forString(target.get());
}

return anchorTarget;
return AnchorTarget.DEFAULT;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@
package com.vaadin.flow.component.html;

/**
* Enum representing <code>target</code> attribute values for an <code>&lt;a&gt;</code> element.
* Enum representing <code>target</code> attribute values for an
* <code>&lt;a&gt;</code> element.
*
* @author Vaadin Ltd
* @since
*/
public enum AnchorTarget {
public enum AnchorTarget implements AnchorTargetValue {
/**
* Remove the target value. This has the same effect as <code>SELF</code>.
*/
Expand All @@ -40,25 +41,26 @@ public enum AnchorTarget {
*/
PARENT("_parent"),
/**
* Open a link in the top most grandparent
* context, or the current context if there is no parent context.
* Open a link in the top most grandparent context, or the current context
* if there is no parent context.
*/
TOP("_top");

private final String value;

/**
* @param value the text value to use by an {@code <a>} (anchor) tag.
* @param value
* the text value to use by an {@code <a>} (anchor) tag.
*/
AnchorTarget(String value) {
this.value = value;
}

/**
* @return
* value the text value to use by an {@code <a>} (anchor) tag.
* @return value the text value to use by an {@code <a>} (anchor) tag.
*/
String getValue() {
@Override
public String getValue() {
return value;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright 2000-2021 Vaadin Ltd.
*
* Licensed 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 com.vaadin.flow.component.html;

import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;

/**
* Represents <code>target</code> attribute values for an <code>&lt;a&gt;</code>
* element.
*
* @author Vaadin Ltd
* @since
*
* @see AnchorTarget
*
*/
public interface AnchorTargetValue {

/**
* Gets the string value representation.
*
* @return string value representation
*/
String getValue();

/**
* Gets an object instance wrapping the {@code value} string representation.
*
* @param value
* the string value representation, not {@code null}
* @return an object wrapping the string value
*/
public static AnchorTargetValue forString(String value) {
Optional<AnchorTarget> target = Stream.of(AnchorTarget.values()).filter(
type -> type.getValue().equals(Objects.requireNonNull(value)))
.findFirst();
if (target.isPresent()) {
return target.get();
}
return new AnchorTargetValue() {

@Override
public String getValue() {
return value;
}

@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
if (!obj.getClass().equals(getClass())) {
return false;
}
return value.equals(((AnchorTargetValue) obj).getValue());
}

@Override
public int hashCode() {
return value.hashCode();
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright 2000-2021 Vaadin Ltd.
*
* Licensed 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 com.vaadin.flow.component.html;

import org.junit.Assert;
import org.junit.Test;

public class AnchorTargetValueTest {

@Test
public void fromString_notEnum_objectHasValueAndEquals() {
AnchorTargetValue value = AnchorTargetValue.forString("foo");
Assert.assertEquals("foo", value.getValue());

AnchorTargetValue value1 = AnchorTargetValue.forString("foo");
Assert.assertEquals(value, value1);
Assert.assertEquals(value.hashCode(), value1.hashCode());
}

@Test
public void fromString_enumValue_resultIsEnum() {
AnchorTargetValue value = AnchorTargetValue
.forString(AnchorTarget.TOP.getValue());
Assert.assertEquals(AnchorTarget.TOP, value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
*/
package com.vaadin.flow.component.html;

import com.vaadin.flow.component.Text;
import java.util.Optional;

import org.junit.Assert;
import org.junit.Test;

import java.util.Optional;
import com.vaadin.flow.component.Text;

public class AnchorTest extends ComponentTest {

Expand All @@ -45,16 +46,19 @@ public void createWithComponent() {
@Test
public void createWithTarget() {
Anchor anchor = new Anchor("#", "Home");
Assert.assertEquals(anchor.getTargetEnum(), Optional.of(AnchorTarget.DEFAULT));
Assert.assertEquals(anchor.getTargetValue(), AnchorTarget.DEFAULT);
Assert.assertEquals(anchor.getTarget(), Optional.empty());

anchor.setTarget(AnchorTarget.BLANK);

Assert.assertEquals(anchor.getTargetEnum(), Optional.of(AnchorTarget.BLANK));
Assert.assertEquals(anchor.getTarget(), Optional.of(AnchorTarget.BLANK.getValue()));
Assert.assertEquals(anchor.getTargetValue(), AnchorTarget.BLANK);
Assert.assertEquals(anchor.getTarget(),
Optional.of(AnchorTarget.BLANK.getValue()));

Assert.assertEquals(anchor.getTargetEnum(), new Anchor("#", "Home", AnchorTarget.BLANK).getTargetEnum());
Assert.assertEquals(anchor.getTarget(), new Anchor("#", "Home", AnchorTarget.BLANK).getTarget());
Assert.assertEquals(anchor.getTargetValue(),
new Anchor("#", "Home", AnchorTarget.BLANK).getTargetValue());
Assert.assertEquals(anchor.getTarget(),
new Anchor("#", "Home", AnchorTarget.BLANK).getTarget());
}

@Test
Expand All @@ -63,8 +67,8 @@ public void shouldNotRemoveRouterIgnoreAttributeWhenRemoveHref() {
anchor.getElement().setAttribute("router-ignore", true);
anchor.removeHref();

Assert.assertEquals("Anchor element should have router-ignore " +
"attribute", "",
Assert.assertEquals(
"Anchor element should have router-ignore " + "attribute", "",
anchor.getElement().getAttribute("router-ignore"));
}

Expand All @@ -74,11 +78,49 @@ public void shouldNotBreakBehaviorIfSetHrefWhenHavingRouterIgnoreAttributeBefore
anchor.getElement().setAttribute("router-ignore", true);
anchor.setHref("/logout");

Assert.assertEquals("Anchor element should have router-ignore " +
"attribute", "",
Assert.assertEquals(
"Anchor element should have router-ignore " + "attribute", "",
anchor.getElement().getAttribute("router-ignore"));
}

@Test
public void setTargetValue_useEnum_targetIsSet() {
Anchor anchor = new Anchor();
anchor.setTarget(AnchorTarget.PARENT);

Assert.assertEquals(Optional.of(AnchorTarget.PARENT.getValue()),
anchor.getTarget());
Assert.assertEquals(AnchorTarget.PARENT, anchor.getTargetValue());
}

@Test
public void setTargetValue_useObject_targetIsSet() {
Anchor anchor = new Anchor();
anchor.setTarget(AnchorTargetValue.forString("foo"));

Assert.assertEquals(Optional.of("foo"), anchor.getTarget());
Assert.assertEquals("foo", anchor.getTargetValue().getValue());
}

@Test
public void getTargetValue_useEnumStringValue_targetIsReturned() {
Anchor anchor = new Anchor();
anchor.setTarget(AnchorTarget.SELF.getValue());

Assert.assertEquals(Optional.of(AnchorTarget.SELF.getValue()),
anchor.getTarget());
Assert.assertEquals(AnchorTarget.SELF, anchor.getTargetValue());
}

@Test
public void getTargetValue_useSomeStringValue_targetIsReturned() {
Anchor anchor = new Anchor();
anchor.setTarget("foo");

Assert.assertEquals(Optional.of("foo"), anchor.getTarget());
Assert.assertEquals("foo", anchor.getTargetValue().getValue());
}

// Other test methods in super class

@Override
Expand Down

0 comments on commit 5e73864

Please sign in to comment.