Package net.sourceforge.marathon.component

Source Code of net.sourceforge.marathon.component.MarathonNamingStrategy

/*******************************************************************************
*  Copyright (C) 2010 Jalian Systems Private Ltd.
*  Copyright (C) 2010 Contributors to Marathon OSS Project
*
*  This library is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Library General Public
*  License as published by the Free Software Foundation; either
*  version 2 of the License, or (at your option) any later version.
*
*  This library is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*  Library General Public License for more details.
*
*  You should have received a copy of the GNU Library General Public
*  License along with this library; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
*  Project website: http://www.marathontesting.com
*  Help: Marathon help forum @ http://groups.google.com/group/marathon-testing
*
*******************************************************************************/
package net.sourceforge.marathon.component;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dialog;
import java.awt.Frame;
import java.awt.Window;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

import javax.swing.AbstractButton;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;

import net.sourceforge.marathon.Constants;
import net.sourceforge.marathon.recorder.IRecordingArtifact;
import net.sourceforge.marathon.recorder.WindowMonitor;
import net.sourceforge.marathon.util.Retry;

/**
* substitute your own naming strategy to customize how Marathon finds and names
* components
*/
public class MarathonNamingStrategy implements INamingStrategy<Component, Component> {

    private static class NamedComponent {
        private static final ArrayList<NamedComponent> cache = new ArrayList<NamedComponent>();
        private static int cacheIndex = 0;
        private Component component;
        private String name;
        private NamedComponent children;
        private NamedComponent sibling;
        private MarathonNamingStrategy strategy;

        public static NamedComponent get(MarathonNamingStrategy namingStrategy, NamedComponent parent, Component component) {
            NamedComponent nc;
            if (cacheIndex >= cache.size()) {
                nc = new NamedComponent();
                cache.add(nc);
            } else {
                nc = (NamedComponent) cache.get(cacheIndex);
            }
            cacheIndex++;
            nc.init(namingStrategy, parent, component);
            return nc;
        }

        public static void reset(Object o) {
            cacheIndex = 0;
        }

        private NamedComponent() {
        }

        private void init(MarathonNamingStrategy strategy, NamedComponent parent, Component component) {
            this.strategy = strategy;
            this.component = component;
            children = null;
            sibling = null;
            if (component instanceof JInternalFrame)
                name = strategy.getName(component);
            else {
                String nsName = strategy.createName(component);
                if (nsName.startsWith("{"))
                    nsName = '\\' + nsName;
                name = createUniqueName(nsName, 0, strategy.getNameComponentMap());
            }
            if (parent != null) {
                if (parent.children == null)
                    parent.children = this;
                else {
                    NamedComponent nc = parent.children;
                    while (nc.sibling != null) {
                        nc = nc.sibling;
                    }
                    nc.sibling = this;
                }
            }
        }

        private String createUniqueName(String initialName, int startIndex, Map<String, NamedComponent> map) {
            String name = initialName + (startIndex == 0 ? "" : "" + startIndex);
            if (map.get(name) != null)
                return createUniqueName(initialName, ++startIndex, map);
            return strategy.escapeParenthesis(name);
        }

        public String getName() {
            return name;
        }

        public Component getComponent() {
            return component;
        }

        public String toString() {
            StringBuffer sb = new StringBuffer();
            return toString(sb, "");
        }

        private String toString(StringBuffer sb, String indent) {
            sb.append(indent).append("[").append(component.getClass().getName()).append("(").append(name).append(")").append("]")
                    .append("\n");
            if (sibling != null)
                sibling.toString(sb, indent);
            if (children != null)
                children.toString(sb, indent + "  ");
            return sb.toString();
        }
    }

    protected boolean useFieldNames = Boolean.getBoolean(Constants.PROP_USE_FIELD_NAMES);
    private Map<String, NamedComponent> nameComponentMap = new HashMap<String, NamedComponent>();
    private Map<Component, NamedComponent> componentNameMap = new HashMap<Component, NamedComponent>();
    protected Map<Object, String> objectFieldNameMap = new HashMap<Object, String>();
    private NamedComponent head = null;
    private Component container;

    public MarathonNamingStrategy() {
    }

    public void init() {
    }
   
    private String escapeParenthesis(String name) {
        name = name.replaceAll("#", "##");
        name = name.replaceAll("\\(", "#{");
        name = name.replaceAll("\\)", "#}");
        return name;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * net.sourceforge.marathon.component.INamingStrategy#setTopLevelComponent
     * (java.awt.Component)
     */
    public void setTopLevelComponent(Component pcontainer, boolean createIfNeeded) {
        if (pcontainer != container) {
            reset();
            container = pcontainer;
        }
        createNames();
    }

    private void reset() {
        nameComponentMap.clear();
        componentNameMap.clear();
        objectFieldNameMap.clear();
        NamedComponent.reset(this);
    }

    private synchronized void createNames() {
        if (!container.isVisible()) {
            return;
        }
        initializeNamedComponentMap(null, container);
    }

    private void initializeNamedComponentMap(NamedComponent parent, Component component) {
        if (component instanceof IRecordingArtifact)
            return;
        NamedComponent namedComponent;
        if (!componentNameMap.containsKey(component)) {
            namedComponent = NamedComponent.get(this, parent, component);
            nameComponentMap.put(namedComponent.getName(), namedComponent);
            componentNameMap.put(namedComponent.getComponent(), namedComponent);
        } else {
            namedComponent = (NamedComponent) componentNameMap.get(component);
        }
        if (component instanceof Container) {
            getFieldNames(component);
            Container parentContainer = (Container) component;
            int componentCount = parentContainer.getComponentCount();
            for (int i = 0; i < componentCount; i++) {
                Component c = parentContainer.getComponent(i);
                initializeNamedComponentMap(namedComponent, c);
            }
        }
        if (component instanceof Window) {
            Window[] ownedWindows = ((Window) component).getOwnedWindows();
            for (int i = 0; i < ownedWindows.length; i++) {
                if (ownedWindows[i].isVisible()) {
                    initializeNamedComponentMap(namedComponent, ownedWindows[i]);
                }
            }
        }
        if (parent == null) {
            head = namedComponent;
        }
    }

    private void getFieldNames(Object o) {
        Class<?> c = o.getClass();
        getFieldNames(o, c);
        getFieldNames(o, c.getSuperclass());
    }

    private void getFieldNames(Object o, Class<?> c) {
        if (c == null)
            return;
        Field[] fields = c.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            try {
                if (Component.class.isAssignableFrom(fields[i].getType())) {
                    fields[i].setAccessible(true);
                    objectFieldNameMap.put(fields[i].get(o), fields[i].getName());
                }
            } catch (IllegalArgumentException e) {
            } catch (IllegalAccessException e) {
            }
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * net.sourceforge.marathon.component.INamingStrategy#getComponent(java.
     * lang.String)
     */
    public Component getComponent(final String name, int retryCount, boolean isContainer) {
        final Component[] found = new Component[1];
        new Retry("Could not find component", ComponentFinder.RETRY_INTERVAL_MS, retryCount, new Retry.Attempt() {
            public void perform() {
                if ((found[0] = findComponent(name)) == null) {
                    retry();
                }
            }
        });
        return found[0];
    }

    private Component findComponent(String name) {
        NamedComponent c = lookupComponent(name);
        if (c == null && container != null) {
            createNames();
            c = lookupComponent(name);
        }
        if (c == null || !c.getComponent().isVisible() || !c.getComponent().isShowing())
            return null;
        return c.getComponent();
    }

    private NamedComponent lookupComponent(String name) {
        if (name.startsWith("{"))
            return lookupComponent(PropertyHelper.fromString(name, new String[][] {}));
        else
            return (NamedComponent) nameComponentMap.get(name);
    }

    private NamedComponent lookupComponent(Properties props) {
        Collection<NamedComponent> values = nameComponentMap.values();
        for (Iterator<NamedComponent> iterator = values.iterator(); iterator.hasNext();) {
            NamedComponent nc = (NamedComponent) iterator.next();
            if (matched(nc.getComponent(), props))
                return nc;
        }
        return null;
    }

    private boolean matched(Component component, Properties props) {
        Iterator<Entry<Object, Object>> elements = props.entrySet().iterator();
        while (elements.hasNext()) {
            Entry<Object, Object> entry = elements.next();
            MComponent temp = getPropertyWrapperObject(component);
            String actual = temp.getProperty(entry.getKey().toString());
            if (actual == null)
                actual = "null";
            if (!actual.equals(entry.getValue()))
                return false;
        }
        return true;
    }

    private String internalGetName(Component component) {
        NamedComponent namedComponent = (NamedComponent) componentNameMap.get(component);
        if (namedComponent != null && namedComponent.getComponent().isVisible())
            return namedComponent.getName();
        return null;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * net.sourceforge.marathon.component.INamingStrategy#getVisibleComponentNames
     * ()
     */
    public String getVisibleComponentNames() {
        if (head == null)
            createNames();
        if (head == null)
            return "<None Found>";
        return head.toString(new StringBuffer(), "");
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * net.sourceforge.marathon.component.INamingStrategy#getAllComponents()
     */
    public Map<String, Component> getAllComponents() {
        createNames();
        Map<String, Component> m = new HashMap<String, Component>(nameComponentMap.size());
        Iterator<String> iterator = nameComponentMap.keySet().iterator();
        while (iterator.hasNext()) {
            String key = (String) iterator.next();
            m.put(key, ((NamedComponent) nameComponentMap.get(key)).getComponent());
        }
        return m;
    }

    private Map<String, NamedComponent> getNameComponentMap() {
        return nameComponentMap;
    }

    public void setUseFieldNames(boolean b) {
        useFieldNames = b;
    }

    private WindowMonitor windowMonitor;

    protected String createName(Component component) {
        if (component instanceof AbstractButton) {
            AbstractButton button = (AbstractButton) component;
            if (button.getText() != null && button.getText().length() != 0) {
                return button.getText();
            }
            Icon icon = button.getIcon();
            if (icon != null && icon instanceof ImageIcon) {
                String description = ((ImageIcon) icon).getDescription();
                if (description != null && description.length() != 0)
                    return mapFromImageDescription(description);
            }
        }
        if (component instanceof JComponent) {
            try {
                JLabel label = (JLabel) ((JComponent) component).getClientProperty("labeledBy");
                if (label != null && label.getText() != null) {
                    String name = label.getText().trim();
                    if (name.endsWith(":")) {
                        name = name.substring(0, name.length() - 1).trim();
                    }
                    return name;
                }
            } catch (ClassCastException e) {
                // just continue
            }
            String name = component.getName();
            if (name != null && !name.equals(""))
                return name;
        }
        if (useFieldNames && objectFieldNameMap.get(component) != null)
            return (String) objectFieldNameMap.get(component);
        String name = component.getClass().getName();
        return mapToCommonName(name);
    }

    private String mapToCommonName(String name) {
        int index;
        if ((index = name.lastIndexOf('.')) == -1)
            return name;
        String packageName = name.substring(0, index);
        String className = name.substring(name.lastIndexOf('.') + 1);
        if (packageName.equals("javax.swing") && className.charAt(0) == 'J')
            return className.substring(1);
        return className;
    }

    private String mapFromImageDescription(String description) {
        try {
            String name = new URL(description).getPath();
            if (name.lastIndexOf('/') != -1)
                name = name.substring(name.lastIndexOf('/') + 1);
            if (name.lastIndexOf('.') != -1)
                name = name.substring(0, name.lastIndexOf('.'));
            return name;
        } catch (MalformedURLException e) {
            return description;
        }
    }

    public String getName(Component component) {
        if (component instanceof JInternalFrame || component instanceof Window)
            return getNameForWindow(component);
        String name = internalGetName(component);
        if (name == null && container != null) {
            createNames();
            name = internalGetName(component);
        }
        return name;
    }

    private String getNameForWindow(Component window) {
        String title = getTitle(window);
        int index = 0;
        List<Window> windows = getWindowMonitor().getWindows();
        for (ListIterator<Window> iterator = windows.listIterator(); iterator.hasNext();) {
            Window w = (Window) iterator.next();
            if (w.equals(window))
                break;
            if (getTitle(w).equals(title))
                index++;
        }
        if (index > 0)
            title = title + "(" + index + ")";
        return title;
    }

    private String getTitle(Component window) {
        String title = null;
        if (window instanceof Frame) {
            title = ((Frame) window).getTitle();
        } else if (window instanceof Dialog) {
            title = ((Dialog) window).getTitle();
        } else if (window instanceof JInternalFrame) {
            title = ((JInternalFrame) window).getTitle();
        }
        return title == null ? "" : title;
    }

    public MComponent getPropertyWrapperObject(Component component) {
        return new MComponent(component, getWindowMonitor());
    }

    private WindowMonitor getWindowMonitor() {
        if (windowMonitor == null)
            windowMonitor = WindowMonitor.getInstance();
        return windowMonitor;
    }

    public void saveIfNeeded() {
    }

    public void markUnused(Component object) {
    }

    public void markUsed(String name) {
    }

}
TOP

Related Classes of net.sourceforge.marathon.component.MarathonNamingStrategy

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.