/*
 * 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 org.spine3.type;

import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Message;
import org.spine3.base.Command;
import org.spine3.base.Event;

import java.util.regex.Pattern;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

/**
 * Utility class for obtaining a type name from a {@code Message}.
 *
 * @author Alexander Yevsyukov
 */
public class TypeName extends StringTypeValue {

    private static final String PROTOBUF_PACKAGE_SEPARATOR = ".";
    private static final Pattern PROTOBUF_PACKAGE_SEPARATOR_PATTERN =
            Pattern.compile('\\' + PROTOBUF_PACKAGE_SEPARATOR);

    private TypeName(String value) {
        super(value);
    }

    private static TypeName create(String value) {
        return new TypeName(value);
    }

    /**
     * Obtains type name for the passed message.
     */
    public static TypeName of(Message message) {
        checkNotNull(message);
        final String typeName = TypeUrl.of(message)
                                       .getTypeName();
        return create(typeName);
    }

    /**
     * Obtains type name for the passed message class.
     */
    public static TypeName of(Class<? extends Message> clazz) {
        checkNotNull(clazz);
        final String typeName = TypeUrl.of(clazz)
                                       .getTypeName();
        return create(typeName);
    }

    /**
     * Obtains type name from the message of the passed command.
     */
    public static TypeName ofCommand(Command command) {
        checkNotNull(command);
        final String typeName = TypeUrl.ofCommand(command)
                                       .getTypeName();
        return create(typeName);
    }

    /**
     * Obtains type name from the message of the passed event.
     */
    public static TypeName ofEvent(Event event) {
        checkNotNull(event);
        final String typeName = TypeUrl.ofEvent(event)
                                       .getTypeName();
        return create(typeName);
    }

    /**
     * Obtains type name for the message type by its descriptor.
     */
    public static TypeName from(Descriptor descriptor) {
        checkNotNull(descriptor);
        final String typeName = TypeUrl.from(descriptor)
                                       .getTypeName();
        return create(typeName);
    }

    /**
     * Creates instance from the passed type URL.
     */
    public static TypeName from(TypeUrl typeUrl) {
        checkNotNull(typeUrl);

        return create(typeUrl.getTypeName());
    }

    /**
     * Returns the unqualified name of the Protobuf type, for example: {@code StringValue}.
     */
    public String getSimpleName() {
        final String typeName = value();
        if (typeName.contains(PROTOBUF_PACKAGE_SEPARATOR)) {
            final String[] parts = PROTOBUF_PACKAGE_SEPARATOR_PATTERN.split(typeName);
            checkState(parts.length > 0, "Invalid type name: " + typeName);
            final String result = parts[parts.length - 1];
            return result;
        } else {
            return typeName;
        }
    }
}

@@ -1882,37 +1882,37 @@
 %0A     * 
-Obtains type name for
+Creates instance from
  the pas
@@ -1915,23 +1915,24 @@
  passed 
-message
+type URL
 .%0A     *
@@ -1964,26 +1964,28 @@
 ame 
-of(Message message
+from(TypeUrl typeUrl
 ) %7B%0A
@@ -2005,23 +2005,23 @@
 NotNull(
-message
+typeUrl
 );%0A     
@@ -2027,137 +2027,237 @@
     
-final String typeName = TypeUrl.of(message)
+return create(typeUrl.getTypeName());
 %0A    
+%7D%0A%0A
     
+/**%0A
      
-       
+* Obtains type name for the passed message.%0A
      
+*/%0A
     
-          .getTypeName();%0A        return create(typeName
+public static TypeName of(Message message) %7B%0A        checkNotNull(message);%0A        return from(TypeUrl.of(message)
 );%0A 
@@ -2390,19 +2390,17 @@
 sage%3E cl
-azz
+s
 ) %7B%0A    
@@ -2418,19 +2418,17 @@
 tNull(cl
-azz
+s
 );%0A     
@@ -2434,135 +2434,35 @@
     
-final String typeName = TypeUrl.of(clazz)%0A                                       .getTypeName();%0A        return create(typeName
+return from(TypeUrl.of(cls)
 );%0A 
@@ -2647,32 +2647,20 @@
     
-final String typeName = 
+return from(
 Type
@@ -2685,94 +2685,8 @@
 and)
-%0A                                       .getTypeName();%0A        return create(typeName
 );%0A 
@@ -2861,140 +2861,42 @@
     
-final String typeName = TypeUrl.ofEvent(event)%0A                                       .getTypeName();%0A        return create(typeName
+return from(TypeUrl.ofEvent(event)
 );%0A 
@@ -3085,343 +3085,43 @@
     
-final String typeName = TypeUrl.from(descriptor)%0A                                       .getTypeName();%0A        return create(typeName);%0A    %7D%0A%0A    /**%0A     * Creates instance from the passed type URL.%0A     */%0A    public static TypeName from(TypeUrl typeUrl) %7B%0A        checkNotNull(typeUrl);%0A%0A        return create(typeUrl.getTypeName(
+return from(TypeUrl.from(descriptor
 ));%0A

Improve code layout