org.kalypso.ogc.gml.AbstractKalypsoTheme.java Source code

Java tutorial

Introduction

Here is the source code for org.kalypso.ogc.gml.AbstractKalypsoTheme.java

Source

/*--------------- Kalypso-Header --------------------------------------------------------------------
    
 This file is part of kalypso.
 Copyright (C) 2004, 2005 by:
    
 Technical University Hamburg-Harburg (TUHH)
 Institute of River and coastal engineering
 Denickestr. 22
 21073 Hamburg, Germany
 http://www.tuhh.de/wb
    
 and
    
 Bjoernsen Consulting Engineers (BCE)
 Maria Trost 3
 56070 Koblenz, Germany
 http://www.bjoernsen.de
    
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 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
 Lesser General Public License for more details.
    
 You should have received a copy of the GNU Lesser 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
    
 Contact:
    
 E-Mail:
 belger@bjoernsen.de
 schlienger@bjoernsen.de
 v.doemming@tuhh.de
    
 ---------------------------------------------------------------------------------------------------*/
package org.kalypso.ogc.gml;

import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import org.apache.commons.lang3.ObjectUtils;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.kalypso.commons.i18n.I10nString;
import org.kalypso.contribs.eclipse.core.runtime.SafeRunnable;
import org.kalypso.core.KalypsoCoreExtensions;
import org.kalypso.core.KalypsoCorePlugin;
import org.kalypso.core.i18n.Messages;
import org.kalypso.ogc.gml.mapmodel.IMapModell;
import org.kalypsodeegree.model.geometry.GM_Envelope;

/**
 * Abstract implementation of IKalypsoTheme<br>
 * Implements common features to all KalypsoTheme's
 *
 * @author Gernot Belger
 */
public abstract class AbstractKalypsoTheme extends PlatformObject implements IKalypsoTheme {
    protected interface IListenerRunnable {
        void visit(final IKalypsoThemeListener l);
    }

    protected static final Object[] EMPTY_CHILDREN = new Object[] {};

    protected static final IStatus PAINT_STATUS = new Status(IStatus.INFO, KalypsoCorePlugin.getID(),
            Messages.getString("org.kalypso.ogc.gml.AbstractKalypsoTheme.0")); //$NON-NLS-1$

    private final Collection<IKalypsoThemeListener> m_listeners = Collections
            .synchronizedSet(new HashSet<IKalypsoThemeListener>());

    private final Map<String, String> m_properties = Collections.synchronizedMap(new HashMap<String, String>());

    private final IMapModell m_mapModel;

    /**
     * Stores the relative URL or an URN for an icon, which can be used for the layer in a legend. May be null.
     */
    private String m_externIconUrn = null;

    /**
     * The context, if the theme is part of a template loaded from a file. May be null. Used to resolve dependend
     * resources like the legend-icon.
     */
    private URL m_context = null;

    private I10nString m_name;

    private String m_type;

    /**
     * The status of this theme. Should be set of implementing classes whenever something unexpected occurs (e.g. error
     * while loading the theme, ...).
     */
    private IStatus m_status = Status.OK_STATUS;

    private boolean m_isVisible = true;

    /**
     * Holds the descriptor for the default icon of all themes. Is used in legends, such as the outline.
     */
    private org.eclipse.swt.graphics.Image m_standardThemeIcon;

    /**
     * True, if the theme should show its children in an outline. Otherwise false.
     */
    private boolean m_showLegendChildren = true;

    /**
     * The id of this theme.
     */
    private String m_id;

    /**
     * The constructor.
     *
     * @param name
     *          The name of the theme.
     * @param type
     *          The type of the theme.
     * @param mapModel
     *          The map model to use.
     */
    public AbstractKalypsoTheme(final I10nString name, final String type, final IMapModell mapModel) {
        Assert.isNotNull(mapModel);

        m_id = null;
        m_name = name;
        m_type = type;
        m_mapModel = mapModel;

        /* Initialize properties */
        // deleteable defaults to 'true', because this was the old behavior
        m_properties.put(IKalypsoTheme.PROPERTY_DELETEABLE, Boolean.toString(true));
    }

    /**
     * Runs the given runnable on every listener in a safe way.
     */
    protected void acceptListenersRunnable(final IListenerRunnable r) {
        final IKalypsoThemeListener[] listeners = m_listeners
                .toArray(new IKalypsoThemeListener[m_listeners.size()]);
        for (final IKalypsoThemeListener l : listeners) {
            final ISafeRunnable code = new SafeRunnable() {
                @Override
                public void run() throws Exception {
                    r.visit(l);
                }
            };

            SafeRunner.run(code);
        }
    }

    /**
     * @see org.kalypso.ogc.gml.IKalypsoTheme#addKalypsoThemeListener(org.kalypso.ogc.gml.IKalypsoThemeListener)
     */
    @Override
    public void addKalypsoThemeListener(final IKalypsoThemeListener listener) {
        Assert.isNotNull(listener);

        m_listeners.add(listener);
    }

    /**
     * @see org.kalypso.ogc.gml.IKalypsoTheme#dispose()
     */
    @Override
    public void dispose() {
        m_listeners.clear();

        if (m_standardThemeIcon != null) {
            m_standardThemeIcon.dispose();
            m_standardThemeIcon = null;
        }
    }

    /**
     * Fire the given event to my registered listeners.
     */
    protected void fireContextChanged() {
        acceptListenersRunnable(new IListenerRunnable() {
            @Override
            public void visit(final IKalypsoThemeListener l) {
                if (l == null)
                    return;

                l.contextChanged(AbstractKalypsoTheme.this);
            }
        });
    }

    /**
     * Fire the given event to my registered listeners.
     */
    protected void fireStatusChanged(final IKalypsoTheme theme) {
        // TODO: this is also used to fire events for child-themes
        // we should get the child-theme as parameter and give this instead of myself to the statusChanged event

        final IKalypsoTheme changedTheme = theme == null ? this : theme;

        acceptListenersRunnable(new IListenerRunnable() {
            @Override
            public void visit(final IKalypsoThemeListener l) {
                if (l == null)
                    return;

                l.statusChanged(changedTheme);
            }
        });
    }

    /**
     * Fire the given event to my registered listeners.
     */
    protected void fireVisibilityChanged(final boolean newVisibility) {
        acceptListenersRunnable(new IListenerRunnable() {
            @Override
            public void visit(final IKalypsoThemeListener l) {
                if (l == null)
                    return;

                l.visibilityChanged(AbstractKalypsoTheme.this, newVisibility);
            }
        });
    }

    /**
     * Fire the given event to my registered listeners.<br>
     *
     * @param invalidExtent
     *          The extent that is no more valid; <code>null</code> indicating that the complete theme should be
     *          repainted.
     */
    protected void fireRepaintRequested(final GM_Envelope invalidExtent) {
        final IKalypsoTheme theme = AbstractKalypsoTheme.this;
        acceptListenersRunnable(new IListenerRunnable() {
            @Override
            public void visit(final IKalypsoThemeListener l) {
                if (l == null)
                    return;

                l.repaintRequested(theme, invalidExtent);
            }
        });
    }

    /**
     * Returns the type of the theme by default. Override if needed.
     *
     * @see org.kalypso.ogc.gml.IKalypsoTheme#getContext()
     */
    @Override
    public String getTypeContext() {
        return getType();
    }

    /**
     * This function should return the default image descriptor representing the theme. <br>
     * Subclasses should override, if they want an own standard icon for representing them.<br>
     * <strong>Note:</strong><br>
     * <br>
     * This has only an effect, if the user does not define an URL or URN and the theme has more then one style or rule.
     *
     * @return The default image descriptor.
     */
    @Override
    public ImageDescriptor getDefaultIcon() {
        // FIXME: might be called after theme was already disposed... the image is then never disposed....
        // Maybe we need to introduce a flag ot know if the theme is already disposed.
        if (m_standardThemeIcon == null)
            m_standardThemeIcon = new Image(Display.getCurrent(),
                    AbstractKalypsoTheme.class.getResourceAsStream("resources/standardTheme.gif")); //$NON-NLS-1$

        return ImageDescriptor.createFromImage(m_standardThemeIcon);
    }

    /**
     * @see org.kalypso.ogc.gml.IKalypsoTheme#getLabel()
     */
    @Override
    public String getLabel() {
        return getName().getValue();
    }

    /**
     * @see org.kalypso.ogc.gml.IKalypsoTheme#getMapModell()
     */
    @Override
    public IMapModell getMapModell() {
        return m_mapModel;
    }

    @Override
    public I10nString getName() {
        return m_name;
    }

    /**
     * @see org.eclipse.ui.model.IWorkbenchAdapter#getParent(java.lang.Object)
     */
    public Object getParent(final Object o) {
        Assert.isTrue(o == this);

        return m_mapModel.getThemeParent(this);
    }

    /**
     * @return <code>defaultValue</code>, if the requested property is not set.
     * @see org.kalypso.ogc.gml.IKalypsoTheme#getProperty(java.lang.String, java.lang.String)
     */
    @Override
    public String getProperty(final String name, final String defaultValue) {
        if (!m_properties.containsKey(name))
            return defaultValue;

        return m_properties.get(name);
    }

    @Override
    public String[] getPropertyNames() {
        return m_properties.keySet().toArray(new String[m_properties.keySet().size()]);
    }

    @Override
    public IStatus getStatus() {
        return m_status;
    }

    @Override
    public String getType() {
        return m_type;
    }

    /**
     * @see org.kalypso.ogc.gml.IKalypsoTheme#isLoaded()
     */
    @Override
    public boolean isLoaded() {
        return true;
    }

    /**
     * @see org.kalypso.ogc.gml.IKalypsoTheme#isVisible()
     */
    @Override
    public boolean isVisible() {
        return m_isVisible;
    }

    /**
     * @see org.kalypso.ogc.gml.IKalypsoTheme#removeKalypsoThemeListener(org.kalypso.ogc.gml.IKalypsoThemeListener)
     */
    @Override
    public void removeKalypsoThemeListener(final IKalypsoThemeListener listener) {
        m_listeners.remove(listener);
    }

    /**
     * @see org.kalypso.ogc.gml.IKalypsoTheme#setName(org.kalypso.contribs.java.lang.I10nString)
     */
    @Override
    public void setName(final I10nString name) {
        m_name = name;

        fireStatusChanged(this);
    }

    /**
     * @see org.kalypso.ogc.gml.IKalypsoTheme#setProperty(java.lang.String, java.lang.String)
     */
    @Override
    public void setProperty(final String name, final String value) {
        m_properties.put(name, value);

        // REMARK: we use status changed at the moment, maybe we should fire a special event for properties?
        fireStatusChanged(this);
    }

    public void setStatus(final IStatus status) {
        // Do not fire change if status did not change really; else we may get endless loop
        if (ObjectUtils.equals(status.getSeverity(), m_status.getSeverity())
                && ObjectUtils.equals(status.getMessage(), m_status.getMessage()))
            return;

        m_status = status;

        fireStatusChanged(this);
    }

    public void setType(final String type) {
        m_type = type;

        fireStatusChanged(this);
    }

    /**
     * @see org.kalypso.ogc.gml.IKalypsoTheme#setVisible(boolean)
     */
    @Override
    public void setVisible(final boolean visible) {
        if (visible != m_isVisible) {
            m_isVisible = visible;
            fireVisibilityChanged(visible);
        }
    }

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

    @Override
    public Object getAdapter(final Class adapter) {
        if (adapter == IKalypsoThemeInfo.class) {
            /* If an explicit info is configured for this map, use it */
            final String themeInfoId = getProperty(IKalypsoTheme.PROPERTY_THEME_INFO_ID, null);
            if (themeInfoId != null)
                return KalypsoCoreExtensions.createThemeInfo(themeInfoId, this);
        }

        return super.getAdapter(adapter);
    }

    /**
     * This function returns the URL or URN defined by the user for an icon, which should be displayed in a legend or an
     * outline.
     *
     * @return The URL or URN string. May be null.
     */
    @Override
    public String getLegendIcon() {
        return m_externIconUrn;
    }

    protected void setContext(final URL context) {
        m_context = context;
    }

    @Override
    public void setLegendIcon(final String legendIcon, final URL context) {
        if (ObjectUtils.equals(m_externIconUrn, legendIcon) && ObjectUtils.equals(m_context, context))
            return;

        m_externIconUrn = legendIcon;
        m_context = context;

        fireStatusChanged(this);
    }

    /**
     * This function returns the context.
     *
     * @return The context, if the theme is part of a template loaded from a file. May be null.
     */
    @Override
    public URL getContext() {
        return m_context;
    }

    /**
     * This function returns true, if the theme allows showing its children in an outline. Otherwise, it will return
     * false.
     *
     * @return True,if the theme allows showing its children in an outline. Otherwise, false.
     */
    @Override
    public boolean shouldShowLegendChildren() {
        return m_showLegendChildren;
    }

    public void setShowLegendChildren(final boolean showChildren) {
        if (ObjectUtils.equals(m_showLegendChildren, showChildren))
            return;

        m_showLegendChildren = showChildren;

        fireStatusChanged(this);
    }

    @Override
    public void setId(final String id) {
        m_id = id;
    }

    @Override
    public String getId() {
        return m_id;
    }
}