package de.markusmo3.urm.domain;

import com.thoughtworks.paranamer.*;

import java.lang.reflect.Executable;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;

/**
 * Created by moe on 09.04.16.
 */
public abstract class DomainExecutable<T extends Executable> {

    private static final boolean useParameterNames = Boolean.parseBoolean(System.getProperty("useParameterNames", "true"));
    private static final String JAVA_IDENTIFIER_REGEX = "([a-zA-Z_$][a-zA-Z\\d_$]*)";

    private static final Paranamer PARANAMER = new AdaptiveParanamer(new DefaultParanamer(),
            new BytecodeReadingParanamer(), new NullParanamer());
    private T executable;

    public DomainExecutable(T executable) {
        this.executable = executable;
    }

    protected T getExecutable() {
        return executable;
    }

    protected String getName() {
        return executable.getName();
    }

    public String getUmlName() {
        // Have to do the old for loop way because Paranamer doesnt have a nice interface
        String[] parameterNames = PARANAMER.lookupParameterNames(executable, false);
        Parameter[] parameters = executable.getParameters();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < parameters.length; i++) {
            String paraName = ((parameterNames.length != 0 && useParameterNames) ? parameterNames[i] + " : " : "");
            sb.append(paraName + TypeUtils.getSimpleName(parameters[i].getParameterizedType()));

            if (i != parameters.length - 1) {
                sb.append(", ");
            }
        }

        return getName() + "(" + sb.toString() + ")";
    }

    public Class<?> getDeclaringClass() {
        return executable.getDeclaringClass();
    }

    public Visibility getVisibility() {
        return TypeUtils.getVisibility(executable.getModifiers());
    }

    public boolean isStatic() {
        return Modifier.isStatic(executable.getModifiers());
    }

    public boolean isAbstract() {
        return Modifier.isAbstract(executable.getModifiers());
    }

    @Override
    public String toString() {
        return getUmlName();
    }
}

@@ -172,16 +172,41 @@
 rameter;
+%0Aimport java.util.Arrays;
 %0A%0A/**%0A *
@@ -1198,24 +1198,828 @@
 rameters();%0A
+%0A        Class%3C?%3E declaringClass = executable.getDeclaringClass();%0A        if ((declaringClass.isLocalClass() %7C%7C declaringClass.isMemberClass())%0A                && !Modifier.isStatic(declaringClass.getModifiers())%0A                && (this instanceof DomainConstructor)) %7B%0A            // An inner class of any sort (local or member) that isnt static holds a reference to its%0A            // declaring/parent class. This reference is passed into the constructor as the first argument,%0A            // so in that case we have to ignore the first argument from 'parameters'%0A            parameters = Arrays.copyOfRange(parameters, 1, parameters.length);%0A            // But due to this parameter being hidden, it isnt found by Paranamer and thus the parameterNames%0A            // array mustn't be cut%0A        %7D%0A%0A
         Stri

Fix issue with inner classes and parameters The source comments should explain it good enough: An inner class of any sort (local or member) that isnt static holds a reference to its declaring/parent class. This reference is passed into the constructor as the first argument, so in that case we have to ignore the first argument from 'parameters'