/*
 * Copyright 2017, TeamDev Ltd. All rights reserved.
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package io.spine.examples.todolist.action;

import com.google.common.annotations.VisibleForTesting;
import io.spine.examples.todolist.view.View;

import java.util.Objects;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.lang.String.format;

/**
 * An {@code Action} encapsulates navigation among {@linkplain View views}.
 *
 * @author Dmytro Grankin
 */
public abstract class Action {

    private static final String SHORTCUT_FORMAT = "(%s)";
    private static final String SHORTCUT_NAME_SEPARATOR = " ";

    private final String name;
    private final String shortcut;

    protected Action(String name, String shortcut) {
        checkArgument(!isNullOrEmpty(name));
        checkArgument(!isNullOrEmpty(shortcut));
        this.name = name;
        this.shortcut = shortcut;
    }

    /**
     * Executes the action.
     *
     * @param source the source {@link View} of the action
     */
    public abstract void execute(View source);

    public abstract Action createReverseAction(String name, String shortcut);

    public String getName() {
        return name;
    }

    public String getShortcut() {
        return shortcut;
    }

    public static String getShortcutFormat() {
        return SHORTCUT_FORMAT;
    }

    @VisibleForTesting
    static String getShortcutNameSeparator() {
        return SHORTCUT_NAME_SEPARATOR;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        final Action other = (Action) o;
        return Objects.equals(shortcut, other.shortcut);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(shortcut);
    }

    @Override
    public String toString() {
        final String formattedShortcut = format(SHORTCUT_FORMAT, shortcut);
        return formattedShortcut + SHORTCUT_NAME_SEPARATOR + name;
    }
}

@@ -1432,16 +1432,77 @@
 ws%7D.%0A *%0A
+ * @param %3CS%3E the type of source %7B@link View%7D for the action%0A
  * @auth
@@ -1519,16 +1519,39 @@
 Grankin%0A
+ * @see #execute(View)%0A
  */%0Apubl
@@ -1574,16 +1574,32 @@
 s Action
+%3CS extends View%3E
  %7B%0A%0A    
@@ -2072,28 +2072,20 @@
  source 
-%7B@link V
+v
 iew
-%7D
  of the 
@@ -2132,20 +2132,17 @@
 execute(
-View
+S
  source)

Add generic parameter of the source `View` in `Action`