org.springframework.ide.eclipse.boot.dash.model.BootProjectDashElement.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.ide.eclipse.boot.dash.model.BootProjectDashElement.java

Source

/*******************************************************************************
 * Copyright (c) 2015 Pivotal, Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Pivotal, Inc. - initial API and implementation
 *******************************************************************************/
package org.springframework.ide.eclipse.boot.dash.model;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.Platform;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.jdt.core.IJavaProject;
import org.springframework.ide.eclipse.boot.core.BootPropertyTester;
import org.springframework.ide.eclipse.boot.dash.livexp.LiveSets;
import org.springframework.ide.eclipse.boot.dash.model.BootDashModel.ElementStateListener;
import org.springframework.ide.eclipse.boot.dash.util.CollectionUtils;
import org.springframework.ide.eclipse.boot.dash.util.DebugUtil;
import org.springframework.ide.eclipse.boot.launch.util.BootLaunchUtils;
import org.springframework.ide.eclipse.boot.pstore.IPropertyStore;
import org.springframework.ide.eclipse.boot.pstore.IScopedPropertyStore;
import org.springframework.ide.eclipse.boot.pstore.PropertyStores;
import org.springframework.ide.eclipse.boot.util.Log;
import org.springsource.ide.eclipse.commons.frameworks.core.workspace.ClasspathListenerManager;
import org.springsource.ide.eclipse.commons.frameworks.core.workspace.ClasspathListenerManager.ClasspathListener;
import org.springsource.ide.eclipse.commons.livexp.core.DisposeListener;
import org.springsource.ide.eclipse.commons.livexp.core.LiveExpression;
import org.springsource.ide.eclipse.commons.livexp.core.ObservableSet;
import org.springsource.ide.eclipse.commons.livexp.core.ValueListener;
import org.springsource.ide.eclipse.commons.livexp.ui.Disposable;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;

/**
 * Concrete BootDashElement that wraps an IProject
 *
 * @author Kris De Volder
 */
public class BootProjectDashElement extends AbstractLaunchConfigurationsDashElement<IProject> {

    private static final boolean DEBUG = DebugUtil.isDevelopment();

    private static void debug(String string) {
        if (DEBUG) {
            System.err.println(string);
        }
    }

    private IScopedPropertyStore<IProject> projectProperties;

    private LaunchConfDashElementFactory childFactory;
    private ObservableSet<BootDashElement> children;
    private ObservableSet<Integer> ports;
    private LiveExpression<Boolean> hasDevtools = null;

    public BootProjectDashElement(IProject project, LocalBootDashModel context,
            IScopedPropertyStore<IProject> projectProperties, BootProjectDashElementFactory factory,
            LaunchConfDashElementFactory childFactory) {
        super(context, project);
        this.projectProperties = projectProperties;
        this.childFactory = childFactory;
        //      if (DEBUG) {
        //         onDispose((e) -> {
        //            debug("disposed: "+this);
        //         });
        //      }
    }

    @Override
    public boolean hasDevtools() {
        if (hasDevtools == null) {
            hasDevtools = new LiveExpression<Boolean>(false) {
                @Override
                protected Boolean compute() {
                    boolean val = BootPropertyTester.hasDevtools(getProject());
                    return val;
                }
            };
            hasDevtools.refresh();
            ClasspathListenerManager classpathListener = new ClasspathListenerManager(new ClasspathListener() {
                public void classpathChanged(IJavaProject jp) {
                    if (jp.getProject().equals(getProject())) {
                        hasDevtools.refresh();
                    }
                }
            });
            this.dependsOn(hasDevtools);
            this.addDisposableChild(classpathListener);
        }
        return hasDevtools.getValue();
    }

    @Override
    public IProject getProject() {
        return delegate;
    }

    @Override
    public String getName() {
        return delegate.getName();
    }

    @Override
    protected IPropertyStore createPropertyStore() {
        return PropertyStores.createForScope(delegate, projectProperties);
    }

    @Override
    public ImmutableSet<ILaunchConfiguration> getLaunchConfigs() {
        return getLaunchConfigsExp().getValues();
    }

    @Override
    public int getLivePort() {
        return CollectionUtils.getAnyOr(getLivePorts(), -1);
    }

    @Override
    public ImmutableSet<Integer> getLivePorts() {
        return getLivePortsExp().getValues();
    }

    private ObservableSet<Integer> getLivePortsExp() {
        if (ports == null) {
            ports = createSortedLiveSummary((BootDashElement element) -> {
                int port = element.getLivePort();
                if (port > 0) {
                    return port;
                }
                return null;
            });
            this.dependsOn(ports);
        }
        return ports;
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private void dependsOn(LiveExpression<?> liveProperty) {
        liveProperty.addListener(new ValueListener() {
            public void gotValue(LiveExpression exp, Object value) {
                getBootDashModel().notifyElementChanged(BootProjectDashElement.this,
                        "livePropertyChanged(" + exp + ", " + value + ")");
            }
        });
    }

    /**
     * Creates a ObservableSet that is a 'summary' of some property of the children of this node. The summary
     * is a set of all the values of the given property on all the children. The set is sorted using the element's
     * natural ordering.
     */
    private <T extends Comparable<T>> ObservableSet<T> createSortedLiveSummary(
            final Function<BootDashElement, T> getter) {

        final ObservableSet<T> summary = new ObservableSet<T>() {

            @Override
            protected ImmutableSet<T> compute() {
                debug("port-summary[" + getName() + "]: compute()...");
                ImmutableSet.Builder<T> builder = ImmutableSortedSet.naturalOrder();
                for (BootDashElement child : getCurrentChildren()) {
                    add(builder, child);
                }
                ImmutableSet<T> result = builder.build();
                debug("port-summary[" + getName() + "]: compute() => " + result);
                return result;
            }

            protected void add(ImmutableSet.Builder<T> builder, BootDashElement child) {
                debug("port-summary[" + getName() + "]: add port for " + child);
                T v = getter.apply(child);
                debug("port-summary[" + getName() + "]: add port for " + child + " = " + v);
                if (v != null) {
                    builder.add(v);
                }
            }
        };
        final ElementStateListener elementListener = new ElementStateListener() {
            public void stateChanged(BootDashElement e) {
                summary.refresh();
            }
        };
        getBootDashModel().addElementStateListener(elementListener);
        summary.onDispose(new DisposeListener() {
            public void disposed(Disposable disposed) {
                getBootDashModel().removeElementStateListener(elementListener);
            }
        });
        addDisposableChild(summary);
        return summary;
    }

    private ObservableSet<ILaunchConfiguration> getLaunchConfigsExp() {
        return getBootDashModel().launchConfTracker.getConfigs(delegate);
    }

    /**
     * All children including 'invisible ones' that may be hidden from the children returned
     * by getChildren.
     */
    @Override
    public ObservableSet<BootDashElement> getChildren() {
        if (children == null) {
            children = LiveSets.mapSync(getBootDashModel().launchConfTracker.getConfigs(delegate),
                    new Function<ILaunchConfiguration, BootDashElement>() {
                        public BootDashElement apply(ILaunchConfiguration input) {
                            return childFactory.createOrGet(input);
                        }
                    });
            children.addListener(new ValueListener<ImmutableSet<BootDashElement>>() {
                public void gotValue(LiveExpression<ImmutableSet<BootDashElement>> exp,
                        ImmutableSet<BootDashElement> value) {
                    getBootDashModel().notifyElementChanged(BootProjectDashElement.this, "children changed");
                    refreshRunState();
                }
            });
            addDisposableChild(children);
        }
        return this.children;
    }

    @Override
    public void refreshLivePorts() {
        for (BootDashElement child : getChildren().getValues()) {
            try {
                ((AbstractLaunchConfigurationsDashElement<?>) child).refreshLivePorts();
            } catch (ClassCastException e) {
                //Should be impossible (unless something changes in how elements in dash are nested)
                Log.log(e);
            }
        }
    }

    @Override
    public ImmutableSet<ILaunch> getLaunches() {
        return ImmutableSet.copyOf(BootLaunchUtils.getLaunches(getLaunchConfigs()));
    }

    @Override
    public Object getParent() {
        return getBootDashModel();
    }
}