Package org.jemmy.dock

Source Code of org.jemmy.dock.DockGenerator$ClassArrayValueGetter

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2007-2009 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of the Common Development
* and Distribution License (the "License"). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the license at LICENSE.html or
* http://www.sun.com/cddl. See the License for the specific language governing
* permissions and limitations under the License.
*
* When distributing Covered Code, include this License Header Notice in each
* file.
*
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s): Alexandre (Shura) Iline. (shurymury@gmail.com)
*
* The Original Software is the Jemmy library. The Initial Developer of the
* Original Software is Alexandre Iline. All Rights Reserved.
*
*/
package org.jemmy.dock;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.*;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.*;
import javax.lang.model.type.*;
import javax.lang.model.util.AbstractAnnotationValueVisitor6;
import javax.lang.model.util.AbstractTypeVisitor6;
import static javax.lang.model.util.ElementFilter.methodsIn;
import javax.lang.model.util.SimpleAnnotationValueVisitor6;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import org.jemmy.control.*;
import org.jemmy.env.Environment;
import org.jemmy.interfaces.ControlInterface;
import org.jemmy.interfaces.Parent;
import org.jemmy.lookup.LookupCriteria;

/**
* Major inconvenience which a novice experiences with Jemmy usage is the fact
* that it is not clear from API what kind of operation you would be able to
* perform with what kind of controls. Similarly it is not at first clear what
* kind of lookup criteria one could use for a particular controls kind and also
* what properties a control type provides.<br/> This annotation processor
* generates another layer of API to access the same functionality which Jemmy
* provides but differently - through a set of lookup constructors, property
* getters and
* <code>as*</code> interfaces. All of that is generated from a set of
* annotations which are added to classes which extend
* <code>org.jemmy.control.Wrap</code> class.<br> Check
* <code>*.*Dock</code> classes and the corresponding
* <code>Wrap</code> extentions within JemmyAWT code.
*
* @deprecated Please use a generator from JemmySupport
* @author shura
*/
@Deprecated
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class DockGenerator extends AbstractProcessor {

    public static final String CONTROL_PLACEHOLDER = "$CONTROL$";
    public static final String PACKAGE_PLACEHOLDER = "$PACKAGE$";
    public static final String SUPERDOCK_PLACEHOLDER = "$SUPERDOCK$";
    public static final String WRAP_PLACEHOLDER = "$WRAP$";
    private static final String DOCK_PLACEHOLDER = "$DOCK$";
    private static final String body_source = "/**\n"
            + "This is a convenience class generated by information available through annotations in class $WRAP$\n"
            + "*/\n"
            + "package $PACKAGE$;\n"
            + "import " + Wrap.class.getName() + ";\n"
            + "import " + Parent.class.getName() + ";\n"
            + "import " + LookupCriteria.class.getName() + ";\n"
            + "import " + Environment.class.getName() + ";\n"
            + "public class $DOCK$ extends $SUPERDOCK$ {\n"
            + "$CONSTRUCTORS$"
            + "$WRAP_GETTER$"
            + "$INTERFACES$"
            + "$PROPERTIES$"
            + "}";
    private static final String control_constructor_source =
            "\t/**Creates dock for a previously found control*/\n"
            + "\tpublic $DOCK$(Environment env, $CONTROL$ control) {\n"
            + "\t\tsuper($WRAP_METHOD$(env, $CONTROL$.class, control));\n"
            + "\t}\n";
    private static final String wrap_constructor_source =
            "\t/**Creates dock for a wrapped control*/\n"
            + "\t$PUBLIC$ $DOCK$(Wrap<? extends $CONTROL$> wrap) {\n"
            + "\t\tsuper(wrap);\n"
            + "\t}\n";
    private static final String criteria_constructors_source =
            "\t/**Looks for an <code>index</code>'th <code>$CONTROL$</code> by a criteria"
            + " within <code>parent</code>*/\n"
            + "\tpublic $DOCK$(Parent<? super $CONTROL$> parent, int index, LookupCriteria<$CONTROL$>... criteria) {\n"
            + "\t\tthis(lookup(parent, $CONTROL$.class, index, criteria));\n"
            + "\t}\n"
            + "\t/**Looks for a <code>$CONTROL$</code> by a criteria"
            + " within <code>parent</code>*/\n"
            + "\tpublic $DOCK$(Parent<? super $CONTROL$> parent, LookupCriteria<$CONTROL$>... criteria) {\n"
            + "\t\tthis(parent, 0, criteria);\n"
            + "\t}\n";
    private static final String object_lookup_constructors_source =
            "\t/**Looks for an <code>index</code>'th <code>$CONTROL$</code> $LOOKUP_DESCRIPTION$"
            + " within <code>parent</code>*/\n"
            + "\tpublic $DOCK$(Parent<? super $CONTROL$> parent, int index$COMMA$ $DECLARED_PARAMETERS$) {\n"
            + "\t\tthis(parent, index, $USED_PARAMETERS$);\n"
            + "\t}\n"
            + "\t/**Looks for a <code>$CONTROL$</code> $LOOKUP_DESCRIPTION$"
            + " within <code>parent</code>*/\n"
            + "\tpublic $DOCK$(Parent<? super $CONTROL$> parent$COMMA$ $DECLARED_PARAMETERS$) {\n"
            + "\t\tthis(parent, $USED_PARAMETERS$);\n"
            + "\t}\n";
    private static final String default_parent_criteria_constructors_source =
            "\t/**Looks for a <code>$CONTROL$</code> by a criteria"
            + " within $DEFAULT_PARENT_DESCRIPTION$*/\n"
            + "\tpublic $DOCK$(LookupCriteria<$CONTROL$>... criteria) {\n"
            + "\t\tthis(0, criteria);\n"
            + "\t}\n"
            + "\t/**Looks for an <code>index</code>'th <code>$CONTROL$</code> by a criteria"
            + " within $DEFAULT_PARENT_DESCRIPTION$*/\n"
            + "\tpublic $DOCK$(int index, LookupCriteria<$CONTROL$>... criteria) {\n"
            + "\t\tthis($LOOKUP_METHOD$($CONTROL$.class), index, criteria);\n"
            + "\t}\n";
    private static final String default_parent_object_lookup_constructors_source =
            "\t/**Looks for a <code>$CONTROL$</code> $LOOKUP_DESCRIPTION$"
            + " within $DEFAULT_PARENT_DESCRIPTION$*/\n"
            + "\tpublic $DOCK$($DECLARED_PARAMETERS$) {\n"
            + "\t\tthis(0, $USED_PARAMETERS$);\n"
            + "\t}\n"
            + "\t/**Looks for an <code>index</code>'th <code>$CONTROL$</code> $LOOKUP_DESCRIPTION$"
            + " within $DEFAULT_PARENT_DESCRIPTION$*/\n"
            + "\tpublic $DOCK$(int index$COMMA$ $DECLARED_PARAMETERS$) {\n"
            + "\t\tthis($LOOKUP_METHOD$($CONTROL$.class), index, $USED_PARAMETERS$);\n"
            + "\t}\n";
    private static final String criteria_subclass_constructors_source =
            "\t/**Looks for an <code>index</code>'th <code>SUBCLASS</code> by a criteria"
            + " within <code>parent</code>*/\n"
            + "\tpublic <SUBCLASS extends $CONTROL$> $DOCK$(Parent<? super $CONTROL$> parent, Class<SUBCLASS> cls, int index, LookupCriteria<SUBCLASS>... criteria) {\n"
            + "\t\tthis(lookup(parent, cls, index, criteria));\n"
            + "\t}\n"
            + "\t/**Looks for a <code>SUBCLASS</code> by a criteria"
            + " within <code>parent</code>*/\n"
            + "\tpublic <SUBCLASS extends $CONTROL$> $DOCK$(Parent<? super $CONTROL$> parent, Class<SUBCLASS> cls, LookupCriteria<SUBCLASS>... criteria) {\n"
            + "\t\tthis(parent, cls, 0, criteria);\n"
            + "\t}\n";
    private static final String object_lookup_subclass_constructors_source =
            "\t/**Looks for an <code>index</code>'th <code>SUBCLASS</code> $LOOKUP_DESCRIPTION$"
            + " within <code>parent</code>*/\n"
            + "\tpublic <SUBCLASS extends $CONTROL$> $DOCK$(Parent<? super $CONTROL$> parent, Class<SUBCLASS> cls, int index$COMMA$ $DECLARED_PARAMETERS$) {\n"
            + "\t\tthis(parent, cls, index, $USED_PARAMETERS$);\n"
            + "\t}\n"
            + "\t/**Looks for a <code>SUBCLASS</code> $LOOKUP_DESCRIPTION$"
            + " within <code>parent</code>*/\n"
            + "\tpublic <SUBCLASS extends $CONTROL$> $DOCK$(Parent<? super $CONTROL$> parent, Class<SUBCLASS> cls$COMMA$ $DECLARED_PARAMETERS$) {\n"
            + "\t\tthis(parent, cls, $USED_PARAMETERS$);\n"
            + "\t}\n";
    private static final String default_parent_criteria_subclass_constructors_source =
            "\t/**Looks for a <code>SUBCLASS</code> by a criteria"
            + " within $DEFAULT_PARENT_DESCRIPTION$*/\n"
            + "\tpublic <SUBCLASS extends $CONTROL$> $DOCK$(Class<SUBCLASS> cls, LookupCriteria<SUBCLASS>... criteria) {\n"
            + "\t\tthis(cls, 0, criteria);\n"
            + "\t}\n"
            + "\t/**Looks for an <code>index</code>'th <code>SUBCLASS</code> by a criteria"
            + " within $DEFAULT_PARENT_DESCRIPTION$*/\n"
            + "\tpublic <SUBCLASS extends $CONTROL$> $DOCK$(Class<SUBCLASS> cls, int index, LookupCriteria<SUBCLASS>... criteria) {\n"
            + "\t\tthis($LOOKUP_METHOD$(cls), cls, index, criteria);\n"
            + "\t}\n";
    private static final String default_parent_object_lookup_subclass_constructors_source =
            "\t/**Looks for a <code>SUBCLASS</code> $LOOKUP_DESCRIPTION$"
            + " within $DEFAULT_PARENT_DESCRIPTION$*/\n"
            + "\tpublic <SUBCLASS extends $CONTROL$> $DOCK$(Class<SUBCLASS> cls$COMMA$ $DECLARED_PARAMETERS$) {\n"
            + "\t\tthis(cls, 0, $USED_PARAMETERS$);\n"
            + "\t}\n"
            + "\t/**Looks for an <code>index</code>'th <code>SUBCLASS</code> $LOOKUP_DESCRIPTION$"
            + " within $DEFAULT_PARENT_DESCRIPTION$*/\n"
            + "\tpublic <SUBCLASS extends $CONTROL$> $DOCK$(Class<SUBCLASS> cls, int index$COMMA$ $DECLARED_PARAMETERS$) {\n"
            + "\t\tthis($LOOKUP_METHOD$(cls), cls, index, $USED_PARAMETERS$);\n"
            + "\t}\n";
    private static final String wrap_getter_source =
            "\t/**Returns wrap*/\n"
            + "\t@Override\n"
            + "\tpublic $WRAP$<? extends $CONTROL$> wrap() {\n"
            + "\t\treturn ($WRAP$<? extends $CONTROL$>)super.wrap();\n"
            + "\t}\n";
    private static final String anon_wrap_getter_source =
            "\t/**Returns wrap*/\n"
            + "\t@Override\n"
            + "\tpublic Wrap<? extends $CONTROL$> wrap() {\n"
            + "\t\treturn (Wrap<? extends $CONTROL$>)super.wrap();\n"
            + "\t}\n";
    private static final String interface_getter_source =
            "\t/**Allows to use as <code>$INTERFACE$</code>*/\n"
            + "\tpublic $INTERFACE$ $INTERFACE_GETTER$() {\n"
            + "\t\treturn wrap().as($INTERFACE$.class);\n"
            + "\t}\n";
    private static final String typed_interface_getter_source =
            "\t/**Allows to use as <code>$INTERFACE$&lt;$INTERFACE_TYPE$&gt;</code>*/\n"
            + "\tpublic $INTERFACE$<$INTERFACE_TYPE$> $INTERFACE_GETTER$() {\n"
            + "\t\treturn wrap().as($INTERFACE$.class, $INTERFACE_TYPE$.class);\n"
            + "\t}\n";
    private static final String method_property_getter_source =
            "\t/**Returns a result of <code>$PROP_NAME$()</code> method*/\n"
            + "\tpublic $PROP_TYPE$ $GETTER_NAME$() {\n"
            + "\t\treturn getProperty(new org.jemmy.action.GetAction<$PROP_TYPE$>() {\n"
            + "\t\t\t@Override\n"
            + "\t\t\tpublic void run(Object... parameters) throws Exception {\n"
            + "\t\t\t\tsetResult(wrap().getControl().$PROP_NAME$());\n"
            + "\t\t\t}\n"
            + "\t\t});\n"
            + "\t}\n";
    private static final String field_property_getter_source =
            "\t/**Returns a value of <code>$PROP_NAME$</code> property*/\n"
            + "\tpublic $PROP_TYPE$ $GETTER_NAME$() {\n"
            + "\t\treturn getProperty(new org.jemmy.action.GetAction<$PROP_TYPE$>() {\n"
            + "\t\t\t@Override\n"
            + "\t\t\tpublic void run(Object... parameters) throws Exception {\n"
            + "\t\t\t\tsetResult(wrap().getControl().$PROP_NAME$);\n"
            + "\t\t\t}\n"
            + "\t\t});\n"
            + "\t}\n";
    private static final String declared_property_getter_source =
            "\t/**Returns $PROP_NAME$ property*/\n"
            + "\tpublic $PROP_TYPE$ $GETTER_NAME$() {\n"
            + "\t\treturn wrap().$METHOD_NAME$();\n"
            + "\t}\n";
    private static final String anon_declared_property_getter_source =
            "\t/**Returns $PROP_NAME$ property*/\n"
            + "\tpublic $PROP_TYPE$ $GETTER_NAME$() {\n"
            + "\t\treturn wrap().getProperty($PROP_TYPE$.class, \"$PROP_NAME$\");\n"
            + "\t}\n";
    private static final String shortcut_methods_source =
            "\t/**Calls <code>wrap().as($INTERFACE$.class).$INVOKE_SETTER$;</code>*/\n"
            + "\tpublic $RETURN_TYPE$ $INTERFACE_SETTER$ {\n"
            + "\t\t $RETURN_STATEMENT$wrap().as($INTERFACE$.class).$INVOKE_SETTER$;\n"
            + "\t}\n";
    private HashMap<String, String> primitiveTypesSubstitutions =
            new HashMap<String, String>();

    {
        primitiveTypesSubstitutions.put(int.class.getName(), Integer.class.getName());
        primitiveTypesSubstitutions.put(long.class.getName(), Long.class.getName());
        primitiveTypesSubstitutions.put(float.class.getName(), Float.class.getName());
        primitiveTypesSubstitutions.put(double.class.getName(), Double.class.getName());
        primitiveTypesSubstitutions.put(boolean.class.getName(), Boolean.class.getName());
    }
    Set<String> types;

    public DockGenerator() {
        types = new HashSet<String>();
        types.add(ControlType.class.getName());
    }

    @Override
    public Set<String> getSupportedAnnotationTypes() {
        return types;
    }

    private StringBuilder replace(String b, String... replacements) {
        return replace(new StringBuilder(b), replacements);
    }

    private StringBuilder replace(StringBuilder b, String... replacements) {
        assert replacements.length % 2 == 0;
        for (int j = 0; j < replacements.length / 2; j++) {
            int i;
            while ((i = b.indexOf(replacements[j * 2])) > -1) {
                b.replace(i, i + replacements[j * 2].length(), replacements[j * 2 + 1]);
            }
        }
        return b;
    }

    private String generateDockName(Element e, String controlClassName) {
        DockInfo dn = e.getAnnotation(DockInfo.class);
        if (dn != null && dn.name().length() > 0) {
            return dn.name();
        } else {
            return generateDockName(((TypeElement) e).getQualifiedName().toString(),
                    getSimpleName(controlClassName));
        }
    }

    private String generateDockName(String wrapClassName, String controlClassName) {
        if (wrapClassName.equals(Wrap.class.getName())) {
            return Dock.class.getName();
        } else {
            return getPackageName(wrapClassName) + "." + getSimpleName(controlClassName) + "Dock";
        }
    }

    private String substitutePrimitiveType(String orig) {
        if (primitiveTypesSubstitutions.containsKey(orig)) {
            return primitiveTypesSubstitutions.get(orig);
        } else {
            return orig;
        }
    }

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment re) {
        for (Element e : re.getElementsAnnotatedWith(ControlType.class)) {
            String wrapClass = ((TypeElement) e).getQualifiedName().toString();
            processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Wrapper: " + wrapClass);
            //Lets assume there is only one ControlType notification, ok?
            AnnotationMirror controlTypeAnn = findAnnotations(e, ControlType.class).get(0);
            for (String controlClassName : getElementValue(controlTypeAnn, "value").accept(new ClassArrayValueGetter(), null)) {
                String dockClassName = generateDockName(e, controlClassName);
                String dockPackage = getPackageName(dockClassName);
                String dockShortName = getSimpleName(dockClassName);
                processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Generating " + dockPackage + "." + dockShortName + " for " + controlClassName);
                //superclass
                String wrapSuperClass = ((TypeElement) e).getSuperclass().accept(new TypeNameGetter(), null);
                String superControlClassName = ((TypeElement) e).getSuperclass().
                        accept(new SuperWrapClassNamesGetter(), null);
                String superDockClassName = generateDockName(((DeclaredType) ((TypeElement) e).getSuperclass()).asElement(), superControlClassName);
                //header
                StringBuilder body = replace(body_source,
                        PACKAGE_PLACEHOLDER, dockPackage,
                        DOCK_PLACEHOLDER, dockShortName,
                        SUPERDOCK_PLACEHOLDER, superDockClassName,
                        WRAP_PLACEHOLDER, wrapClass);
                TypeMirror mirror = e.asType();
                String defaultWrapperMethod = null;
                String defaultParentMethod = null;
                String defaultParentDescription = null;
                boolean anonymous = false;
                while (!mirror.accept(new TypeNameGetter(), null).equals(Wrap.class.getName())) {
                    Element typeEl = ((DeclaredType) mirror).asElement();
                    if (!anonymous) {
                        DockInfo di = e.getAnnotation(DockInfo.class);
                        if (di != null) {
                            anonymous = di.anonymous();
                        }
                    }
                    for (Element el : typeEl.getEnclosedElements()) {

                        if (defaultParentMethod == null) {
                            DefaultParent defaultParentAnn = el.getAnnotation(DefaultParent.class);
                            if (defaultParentAnn != null) {
                                defaultParentMethod = ((TypeElement) ((DeclaredType) mirror).asElement()).getQualifiedName() + "." + el.getSimpleName();
                                defaultParentDescription = defaultParentAnn.value();
                            }
                        }
                        if (defaultWrapperMethod == null) {
                            DefaultWrapper defaultWrapperAnn = el.getAnnotation(DefaultWrapper.class);
                            if (defaultWrapperAnn != null) {
                                defaultWrapperMethod = ((TypeElement) ((DeclaredType) mirror).asElement()).getQualifiedName() + "." + el.getSimpleName();
                            }
                        }
                        if (defaultParentMethod != null && defaultWrapperMethod != null) {
                            break;
                        }
                    }
                    mirror = (DeclaredType) ((TypeElement) ((DeclaredType) mirror).asElement()).getSuperclass();
                }
                //constructors
                StringBuilder constructors = new StringBuilder();
                if (defaultWrapperMethod != null) {
                    constructors.append(replace(control_constructor_source,
                            DOCK_PLACEHOLDER, dockShortName,
                            CONTROL_PLACEHOLDER, controlClassName,
                            "$WRAP_METHOD$", defaultWrapperMethod));
                }
                constructors.append(replace(wrap_constructor_source,
                        DOCK_PLACEHOLDER, dockShortName,
                        CONTROL_PLACEHOLDER, controlClassName,
                        "$PUBLIC$", anonymous ? "protected" : "public"));
                constructors.append(replace(criteria_constructors_source, DOCK_PLACEHOLDER, dockShortName, CONTROL_PLACEHOLDER, controlClassName));
                boolean needsSubtypeLookups = (e.getAnnotation(DockInfo.class) != null) && e.getAnnotation(DockInfo.class).generateSubtypeLookups();
                if (needsSubtypeLookups) {
                    constructors.append(replace(criteria_subclass_constructors_source, DOCK_PLACEHOLDER, dockShortName, CONTROL_PLACEHOLDER, controlClassName));
                }
                if (defaultParentMethod != null) {
                    constructors.append(replace(default_parent_criteria_constructors_source,
                            DOCK_PLACEHOLDER, dockShortName,
                            CONTROL_PLACEHOLDER, controlClassName,
                            "$LOOKUP_METHOD$", defaultParentMethod,
                            "$DEFAULT_PARENT_DESCRIPTION$", defaultParentDescription));
                    if (needsSubtypeLookups) {
                        constructors.append(replace(default_parent_criteria_subclass_constructors_source,
                                DOCK_PLACEHOLDER, dockShortName,
                                CONTROL_PLACEHOLDER, controlClassName,
                                "$LOOKUP_METHOD$", defaultParentMethod,
                                "$DEFAULT_PARENT_DESCRIPTION$", defaultParentDescription));
                    }
                }
                //object lookup constructors
                ObjectLookupTable olt = new ObjectLookupTable((TypeElement) e);
                for (int i = 0; i < olt.names.size(); i++) {
                    String mn = olt.methodNames.get(i);
                    StringBuilder declaredParameters = new StringBuilder();
                    StringBuilder usedParameters =
                            new StringBuilder(mn + "($LOOKUP_SUBTYPE$");
//                    StringBuilder usedParameters =
//                            new StringBuilder(mn + "(" + controlClassName + ".class");
                    for (int j = 0; j < olt.types.get(i).size(); j++) {
                        usedParameters.append(", ");
                        if (j > 0) {
                            declaredParameters.append(", ");
                        }
                        usedParameters.append(olt.names.get(i).get(j));
                        declaredParameters.append(olt.types.get(i).get(j)).
                                append(" ").append(olt.names.get(i).get(j));
                    }
                    usedParameters.append(")");
                    String comma = (olt.types.get(i).size() > 0) ? "," : "";
                    constructors.append(replace(object_lookup_constructors_source,
                            DOCK_PLACEHOLDER, dockShortName,
                            CONTROL_PLACEHOLDER, controlClassName,
                            "$DECLARED_PARAMETERS$", declaredParameters.toString(),
                            "$USED_PARAMETERS$", usedParameters.toString(),
                            "$LOOKUP_SUBTYPE$", controlClassName + ".class",
                            "$LOOKUP_DESCRIPTION$", olt.comments.get(i),
                            "$COMMA$", comma));
                    if (needsSubtypeLookups) {
                        constructors.append(replace(object_lookup_subclass_constructors_source,
                                DOCK_PLACEHOLDER, dockShortName,
                                CONTROL_PLACEHOLDER, controlClassName,
                                "$DECLARED_PARAMETERS$", declaredParameters.toString(),
                                "$USED_PARAMETERS$", usedParameters.toString(),
                                "$LOOKUP_SUBTYPE$", "cls",
                                "$LOOKUP_DESCRIPTION$", olt.comments.get(i),
                                "$COMMA$", comma));
                    }
                    if (defaultParentMethod != null) {
                        constructors.append(replace(default_parent_object_lookup_constructors_source,
                                DOCK_PLACEHOLDER, dockShortName,
                                CONTROL_PLACEHOLDER, controlClassName,
                                "$LOOKUP_METHOD$", defaultParentMethod,
                                "$DEFAULT_PARENT_DESCRIPTION$", defaultParentDescription,
                                "$DECLARED_PARAMETERS$", declaredParameters.toString(),
                                "$USED_PARAMETERS$", usedParameters.toString(),
                                "$LOOKUP_SUBTYPE$", controlClassName + ".class",
                                "$LOOKUP_DESCRIPTION$", olt.comments.get(i),
                                "$COMMA$", comma));
                        if (needsSubtypeLookups) {
                            constructors.append(replace(default_parent_object_lookup_subclass_constructors_source,
                                    DOCK_PLACEHOLDER, dockShortName,
                                    CONTROL_PLACEHOLDER, controlClassName,
                                    "$LOOKUP_METHOD$", defaultParentMethod,
                                    "$DEFAULT_PARENT_DESCRIPTION$", defaultParentDescription,
                                    "$DECLARED_PARAMETERS$", declaredParameters.toString(),
                                    "$USED_PARAMETERS$", usedParameters.toString(),
                                    "$LOOKUP_SUBTYPE$", "cls",
                                    "$LOOKUP_DESCRIPTION$", olt.comments.get(i),
                                    "$COMMA$", comma));
                        }
                    }
                }
                replace(body, "$CONSTRUCTORS$", constructors.toString());
                //wrapper
                replace(body, "$WRAP_GETTER$", replace(
                        anonymous ? anon_wrap_getter_source : wrap_getter_source,
                        CONTROL_PLACEHOLDER, controlClassName,
                        WRAP_PLACEHOLDER, wrapClass).toString());
                //interfaces
                StringBuilder interfaces = new StringBuilder();
//                List<AnnotationMirror> controlInterfaceTypeAnns = findAnnotations(e, ControlInterfaceType.class);
                List<AnnotationMirror> controlInterfacesAnns = findAnnotations(e, ControlInterfaces.class);

                //visitedNodes - hashset to avoid duplicates, when different interfaces/classes/enums comes in the same ControlInterface node
                HashSet<TypeElement> visitedNodes = new HashSet<TypeElement>();
                for (AnnotationMirror am : controlInterfacesAnns) {
                    List<String> intrfcs = getElementValue(am, "value").accept(new ClassArrayValueGetter(), null);
                    List<String> inner = null;
                    AnnotationValue av = getElementValue(am, "encapsulates");
                    if (av != null) {
                        inner = av.accept(new ClassArrayValueGetter(), null);
                    }
                    List name = null;
                    av = getElementValue(am, "name");
                    if (av != null) {
                        name = (List) av.getValue();
                    }
                    for (int i = 0; i < intrfcs.size(); i++) {
                        String innerType = (inner != null && inner.size() > i) ? inner.get(i) : null;
                        StringBuilder one_interface_getter = replace(
                                (innerType != null) ? typed_interface_getter_source : interface_getter_source,
                                "$INTERFACE$", intrfcs.get(i));
                        if (innerType != null) {
                            replace(one_interface_getter, "$INTERFACE_TYPE$", innerType);
                        }
                        String nm;
                        if (name != null && name.size() > i) {
                            nm = (String) ((AnnotationValue) name.get(i)).getValue();
                        } else {
                            nm = "as" + getSimpleName(intrfcs.get(i));
                        }
                        replace(one_interface_getter, "$INTERFACE_GETTER$", nm);
                        interfaces.append(one_interface_getter);
                    }
                    interfaces.append(generateInterfaceShorcuts(am, visitedNodes));
                }
                visitedNodes.clear();
//                for (AnnotationMirror am : controlInterfacesAnns) {
//                    String interfaceClass = getElementValue(am, "value").accept(new ClassArrayValueGetter(), null).get(0);
//                    String type = null;
//                    for (AnnotationMirror ami : controlInterfaceTypeAnns) {
//                        if (getElementValue(ami, "intrfc").accept(new ClassValueGetter(), null).equals(interfaceClass)) {
//                            type = getElementValue(ami, "incapsulates").accept(new ClassValueGetter(), null);
//                        }
//                    }
//                    StringBuilder one_interface_getter = replace(
//                            (type != null) ? typed_interface_getter_source : interface_getter_source,
//                            "$INTERFACE$", interfaceClass,
//                            "$INTERFACE_GETTER$", "as" + getSimpleName(interfaceClass));
//                    if (type != null) {
//                        replace(one_interface_getter, "$INTERFACE_TYPE$", type);
//                    }
//                    interfaces.append(one_interface_getter);
//                }
                replace(body, "$INTERFACES$", interfaces.toString());
                //properties
                StringBuilder properties = new StringBuilder();
                //method properties
                addReflectionProperties(properties, e, MethodProperties.class, method_property_getter_source);
                addReflectionProperties(properties, e, FieldProperties.class, field_property_getter_source);
                //declared properties
                Map<String, String> declaresProperties = new HashMap<String, String>();
                for (Element ie : ((TypeElement) e).getEnclosedElements()) {
                    for (AnnotationMirror am : findAnnotations(ie, Property.class)) {
                        declaresProperties.put((String) getElementValue(am, "value").getValue(),
                                ((ExecutableElement) ie).getReturnType().toString());
                        String propString = (String) getElementValue(am, "value").getValue();
                        properties.append(replace(
                                anonymous ? anon_declared_property_getter_source : declared_property_getter_source,
                                "$PROP_NAME$", propString,
                                "$PROP_TYPE$", substitutePrimitiveType(((ExecutableElement) ie).getReturnType().toString()),
                                "$GETTER_NAME$", createGetterName(propString),
                                "$METHOD_NAME$", ((ExecutableElement) ie).getSimpleName().toString()));
                    }
                }
                replace(body, "$PROPERTIES$", properties.toString());
                try {
                    JavaFileObject f = processingEnv.getFiler().
                            createSourceFile(dockPackage + "." + dockShortName);
                    Writer w = f.openWriter();
                    PrintWriter pw = new PrintWriter(w);
                    pw.print(body);
                    pw.flush();
                    pw.close();
                } catch (IOException ex) {
                    processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, ex.getMessage());
                }
            }
        }
        return true;
    }

    private String generateInterfaceShorcuts(AnnotationMirror am, HashSet<TypeElement> visitedNodes) {
        StringBuilder shortcuts = new StringBuilder();

        List<? extends AnnotationValue> interfaces = (List<? extends AnnotationValue>) getElementValue(am, "value").getValue();
        for (AnnotationValue iface : interfaces) {
            TypeElement e = iface.accept(new SimpleAnnotationValueVisitor6<TypeElement, Object>() {

                @Override
                public TypeElement visitType(TypeMirror t, Object p) {
                    return (TypeElement) ((DeclaredType) t).asElement();
                }
            }, null);
            if(e.getKind() == ElementKind.CLASS){
                shortcutsClassesBypass(e, shortcuts, visitedNodes);
            }
            else if(e.getKind() == ElementKind.INTERFACE || e.getKind() == ElementKind.ENUM)
                shortcutsInterfacesBypass(e, shortcuts, visitedNodes);
        }
        return shortcuts.toString();
    }

    private void shortcutsClassesBypass(TypeElement e, StringBuilder shortcuts, HashSet<TypeElement> visitedNodes){
        if(e == null)
            return;

        TypeMirror supperC = e.getSuperclass();
        if(supperC.getKind() != TypeKind.NONE){
            shortcutsClassesBypass((TypeElement) processingEnv.getTypeUtils().asElement(supperC), shortcuts, visitedNodes);
            shortcutsInterfacesBypass(e, shortcuts, visitedNodes);
        }else{ //in case when class directly extends ControlInterface and to handle classes with no super class
            shortcutsInterfacesBypass(e, shortcuts, visitedNodes);
        }
    }

    private void shortcutsInterfacesBypass(TypeElement e, StringBuilder shortcuts, HashSet<TypeElement> visitedNodes){
        if(e == null)
            return;

        List<? extends TypeMirror> innerFaces = e.getInterfaces();
        for(TypeMirror face : innerFaces){
            if(IsAppropriateNode(face)){
                shortcutsInterfacesBypass((TypeElement) processingEnv.getTypeUtils().asElement(face), shortcuts, visitedNodes);
            }
        }

        if(IsAppropriateNode(e.asType())){
            if(visitedNodes.add(e)){
                handleInterfaceShorcuts(e, shortcuts);
            }
        }
    }

    private boolean IsAppropriateNode(TypeMirror eM){
        return processingEnv.getTypeUtils().isSubtype(eM, processingEnv.getElementUtils().getTypeElement(ControlInterface.class.getName()).asType()) &&
            !processingEnv.getTypeUtils().isSameType(eM, processingEnv.getElementUtils().getTypeElement(ControlInterface.class.getName()).asType());
    }

    private void handleInterfaceShorcuts(TypeElement e, StringBuilder shortcuts){
        for (Element method : methodsIn(processingEnv.getElementUtils().getAllMembers(e))) {
            //first condition is to define whether method is inherited or declared directly
            if (method.getEnclosingElement() == e && method.getAnnotation(Shortcut.class) != null) {
                StringBuilder setter = new StringBuilder().append(method.getAnnotation(Shortcut.class).name().equals("") ? ((ExecutableElement) method).getSimpleName() : method.getAnnotation(Shortcut.class).name()).append('(');

                StringBuilder invokeSetter = new StringBuilder().append(((ExecutableElement) method).getSimpleName()).append('(');
                final TypeMirror returnType = ((ExecutableElement) method).getReturnType();
                String returnTypeString;
                if(returnType.getKind() == TypeKind.TYPEVAR) {
                    returnTypeString = "Object";
                } else {
                    returnTypeString = returnType.toString();
                    int genericStartIndex = returnType.toString().indexOf("<");
                    if(genericStartIndex > -1) {
                        returnTypeString = returnTypeString.substring(0, genericStartIndex) + "<?>";
                    }
                }
                boolean firstParameter = true;
                for (VariableElement ve : ((ExecutableElement) method).getParameters()) {
                    if (!firstParameter) {
                        setter.append(", ");
                        invokeSetter.append(", ");
                    }
                    setter.append(ve.asType().toString()).append(" ").append(ve.getSimpleName());
                    invokeSetter.append(ve.getSimpleName());
                    firstParameter = false;
               }
               setter.append(")");
               invokeSetter.append(")");
               processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "generating setter " + setter);
               shortcuts.append(replace(shortcut_methods_source,
                       "$RETURN_TYPE$", returnTypeString, "$RETURN_STATEMENT$", returnTypeString.equals("void") ? "" : "return ",
                       "$INTERFACE_SETTER$", setter.toString(), "$INVOKE_SETTER$", invokeSetter.toString(),
                       "$INTERFACE$", ((TypeElement) e).getQualifiedName().toString()));
            }
        }
    }

    private void addReflectionProperties(StringBuilder source, Element e, Class annClass, String template) {
        List<AnnotationMirror> propsAnn = findAnnotations(e, annClass);
        if (propsAnn.size() > 0) {
            //List<?> props = (List<?>) getElementValue(propsAnn.get(0), "value").getValue();
            List<String> props = getElementValue(propsAnn.get(0), "value").
                    accept(new StringArrayValueGetter(), null);
            List<String> propsTypes;
            AnnotationValue typesValue = getElementValue(propsAnn.get(0), "types");
            if (typesValue != null) {
                propsTypes = typesValue.accept(new ClassArrayValueGetter(), null);
            } else {
                propsTypes = new LinkedList<String>();
            }
            for (int i = 0; i < props.size(); i++) {
                String propString = props.get(i);
                String propType = (propsTypes.size() > i) ? propsTypes.get(i) : Object.class.getName();
                source.append(replace(template,
                        "$PROP_NAME$", props.get(i),
                        "$PROP_TYPE$", substitutePrimitiveType(propType),
                        "$GETTER_NAME$", createGetterName(propString)));
            }
        }
    }

    private String toLowerCaseCamel(String camel) {
        return camel.substring(0, 1).toLowerCase() + camel.substring(1);
    }

    private String toUpperCaseCamel(String camel) {
        StringBuilder res = new StringBuilder(camel);
        res.replace(0, 1, res.substring(0, 1).toUpperCase());
        int dot = res.indexOf(".");
        while (dot > 0) {
            res.delete(dot, dot + 1);
            if (res.length() > dot) {
                res.replace(dot, dot + 1, res.substring(dot, dot + 1).toUpperCase());
            }
            dot = res.indexOf(".");
        }
        return res.toString();
    }

    private String unQuote(Object data) {
        return data.toString().substring(1, data.toString().length() - 1);
    }

    private AnnotationValue getElementValue(AnnotationMirror am, String name) {
        Map<? extends ExecutableElement, ? extends AnnotationValue> values = am.getElementValues();
        for (ExecutableElement ee : values.keySet()) {
            if (ee.getSimpleName().contentEquals(name)) {
                return values.get(ee);
            }
        }
        return null;
    }

    private List<AnnotationMirror> findAnnotations(Element e, Class annotationType) {
        List<AnnotationMirror> res = new LinkedList<AnnotationMirror>();
        for (AnnotationMirror am : e.getAnnotationMirrors()) {
            if (am.getAnnotationType().toString().equals(annotationType.getName())) {
                res.add(am);
            }
        }
        return res;
    }

    private String getPackageName(String fullName) {
        return fullName.substring(0, fullName.lastIndexOf("."));
    }

    private String getSimpleName(String className) {
        return className.substring(className.lastIndexOf(".") + 1);
    }

    private String createGetterName(String propString) {
        String result;
        if (!propString.startsWith("get") && !propString.startsWith("is")) {
            result = "get" + toUpperCaseCamel(propString);
        } else {
            result = propString;
        }
        return result.replace('.', '_');
    }

    private class ObjectLookupTable {

        List<List<String>> types = new ArrayList<List<String>>();
        List<List<String>> names = new ArrayList<List<String>>();
        List<String> methodNames = new ArrayList<String>();
        List<String> comments = new ArrayList<String>();

        public ObjectLookupTable(TypeElement wrap) {
            TypeMirror mirror = wrap.asType();
            processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "looking for object lookups");
            while (!mirror.accept(new TypeNameGetter(), null).equals(Wrap.class.getName())) {
                TypeElement te = (TypeElement) ((DeclaredType) mirror).asElement();
                addObjectLookups(te);
                mirror = (DeclaredType) te.getSuperclass();
            }
        }

        private void addObjectLookups(TypeElement wrap) {
            for (Element me : wrap.getEnclosedElements()) {
                ObjectLookup ol = me.getAnnotation(ObjectLookup.class);
                if (ol != null) {
                    boolean foundSameSignature = false;
                    processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, me.getSimpleName());
                    List<String> tps = new ArrayList<String>();
                    List<String> nms = new ArrayList<String>();
                    List<? extends VariableElement> params = ((ExecutableElement) me).getParameters();
                    if (params.isEmpty()
                            || !params.get(0).asType().toString().startsWith(Class.class.getName())) {
                        throw new IllegalStateException("Expect first parameter to ba a class but found "
                                + (params.isEmpty() ? "none" : params.get(0).asType().toString()));
                    }
                    for (int i = 1; i < ((ExecutableElement) me).getParameters().size(); i++) {
                        VariableElement param = ((ExecutableElement) me).getParameters().get(i);
                        tps.add(param.asType().toString());
                        nms.add(param.getSimpleName().toString());
                    }
                    for (List<String> oneTps : types) {
                        foundSameSignature = compareParamTypesList(oneTps, tps);
                        if (foundSameSignature) {
                            break;
                        }
                    }
                    if (!foundSameSignature) {
                        types.add(tps);
                        names.add(nms);
                        methodNames.add(wrap.getQualifiedName() + "." + me.getSimpleName());
                        comments.add((ol.value().length() > 0) ? "by " + ol.value() : "");
                    }
                }
            }
        }

        private boolean compareParamTypesList(List<String> oneTps, List<String> tps) {
            if (oneTps.size() != tps.size()) {
                return false;
            }
            for (int i = 0; i < oneTps.size(); i++) {
                if (!oneTps.get(i).equals(tps.get(i))) {
                    return false;
                }
            }
            return true;
        }
    }

    private class ClassValueGetter implements AnnotationValueVisitor<String, Object> {

        public String visit(AnnotationValue av, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visit(AnnotationValue av) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitBoolean(boolean bln, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitByte(byte b, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitChar(char c, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitDouble(double d, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitFloat(float f, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitInt(int i, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitLong(long l, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitShort(short s, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitString(String string, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitType(TypeMirror tm, Object p) {
            return tm.toString();
        }

        public String visitEnumConstant(VariableElement ve, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitAnnotation(AnnotationMirror am, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitArray(List<? extends AnnotationValue> list, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitUnknown(AnnotationValue av, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    private class ClassArrayValueGetter implements AnnotationValueVisitor<List<String>, Object> {

        public List<String> visitArray(List<? extends AnnotationValue> list, Object p) {
            List<String> result = new ArrayList<String>();
            for (AnnotationValue av : list) {
                result.add(av.accept(new ClassValueGetter(), null));
            }
            return result;
        }

        public List<String> visitBoolean(boolean bln, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitByte(byte b, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitChar(char c, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitDouble(double d, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitFloat(float f, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitInt(int i, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitLong(long l, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitShort(short s, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitString(String string, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitType(TypeMirror tm, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitEnumConstant(VariableElement ve, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitAnnotation(AnnotationMirror am, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visit(AnnotationValue av, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visit(AnnotationValue av) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitUnknown(AnnotationValue av, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    private static class TypeNameGetter extends AbstractTypeVisitor6<String, Object> {

        public TypeNameGetter() {
        }

        public String visitDeclared(DeclaredType dt, Object p) {
            return ((TypeElement) dt.asElement()).getQualifiedName().toString();
        }

        public String visitPrimitive(PrimitiveType t, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitNull(NullType t, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitArray(ArrayType t, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitError(ErrorType t, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitTypeVariable(TypeVariable t, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitWildcard(WildcardType t, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitExecutable(ExecutableType t, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitNoType(NoType t, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    private static class StringArrayValueGetter extends AbstractAnnotationValueVisitor6<List<String>, Object> {

        public StringArrayValueGetter() {
        }

        public List<String> visitArray(List<? extends AnnotationValue> list, Object p) {
            List<String> res = new ArrayList<String>();
            for (AnnotationValue av : list) {
                res.add(av.getValue().toString());
            }
            return res;
        }

        public List<String> visitBoolean(boolean b, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitByte(byte b, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitChar(char c, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitDouble(double d, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitFloat(float f, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitInt(int i, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitLong(long i, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitShort(short s, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitString(String s, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitType(TypeMirror t, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitEnumConstant(VariableElement c, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<String> visitAnnotation(AnnotationMirror a, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    private class SuperWrapClassNamesGetter extends AbstractTypeVisitor6<String, Object> {

        public SuperWrapClassNamesGetter() {
        }

        public String visitDeclared(DeclaredType dt, Object p) {
            AnnotationMirror controlTypeAnn = findAnnotations(dt.asElement(), ControlType.class).get(0);
            return getElementValue(controlTypeAnn, "value").accept(new ClassArrayValueGetter(), null).get(0);
        }

        public String visitPrimitive(PrimitiveType t, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitNull(NullType t, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitArray(ArrayType t, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitError(ErrorType t, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitTypeVariable(TypeVariable t, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitWildcard(WildcardType t, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitExecutable(ExecutableType t, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String visitNoType(NoType t, Object p) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }
}
TOP

Related Classes of org.jemmy.dock.DockGenerator$ClassArrayValueGetter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.