
/*--------------------------------------------------------------*
  Copyright (C) 2006-2015 OpenSim Ltd.

  This file is distributed WITHOUT ANY WARRANTY. See the file
  'License' for details on this and other legal matters.
*--------------------------------------------------------------*/

package org.omnetpp.common.properties;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;
import org.eclipse.ui.views.properties.IPropertySource2;
import org.eclipse.ui.views.properties.PropertyDescriptor;

/**
 * Merges several IPropertySource into a single PropertySource (flattens
 * structure)
 *
 * @author rhornig
 */
public class MergedPropertySource implements IPropertySource2 {
    public static final String BASE_CATEGORY = "Base";

    List<IPropertySource> mergedList = new ArrayList<IPropertySource>();

    private boolean readOnly = false;

    /**
     * Adds a property source to be merged into this
     *
     * @param ps
     */
    public void addPropertySource(IPropertySource ps) {
        mergedList.add(ps);
    }

    public boolean isPropertyResettable(Object id) {
        // ask all registered PS if it knows about this
        for (IPropertySource psrc : mergedList)
            if (psrc instanceof IPropertySource2)
                if (((IPropertySource2) psrc).isPropertyResettable(id))
                    return true;

        return false;
    }

    public boolean isPropertySet(Object id) {
        // ask all registered PS if it knows about this
        for (IPropertySource psrc : mergedList)
            if (psrc instanceof IPropertySource2)
                if (((IPropertySource2) psrc).isPropertySet(id))
                    return true;

        return false;
    }

    public Object getEditableValue() {
        return this;
    }

    public IPropertyDescriptor[] getPropertyDescriptors() {
        List<IPropertyDescriptor> mergedPDList = new ArrayList<IPropertyDescriptor>();

        // walk through all property source and merge its descriptors into a single list
        for (IPropertySource psrc : mergedList)
            for (IPropertyDescriptor pdesc : psrc.getPropertyDescriptors()) {
                if (readOnly && (pdesc.getClass() != PropertyDescriptor.class)) {
                    // if we are read only, replace the property descriptor with a readonly one
                    PropertyDescriptor readOnlyPDesc = new PropertyDescriptor(pdesc.getId(), pdesc.getDisplayName());
                    readOnlyPDesc.setCategory(pdesc.getCategory());
                    readOnlyPDesc.setDescription(pdesc.getDescription() + " - (read only)");
                    mergedPDList.add(readOnlyPDesc);
                } else
                    mergedPDList.add(pdesc);
            }

        return mergedPDList.toArray(new IPropertyDescriptor[mergedPDList.size()]);
    }

    public Object getPropertyValue(Object id) {
        // ask all registered property sources for the given value
        for (IPropertySource psrc : mergedList) {
            Object result = psrc.getPropertyValue(id);
            if (result != null)
                return result;
        }

        return null;
    }

    public void resetPropertyValue(Object id) {
        // try to reset the value on all registered property source
        for (IPropertySource psrc : mergedList)
            psrc.resetPropertyValue(id);
    }

    public void setPropertyValue(Object id, Object value) {
        // try to set the value on all registered property source
        for (IPropertySource psrc : mergedList)
            psrc.setPropertyValue(id, value);
    }

    /**
     * Sets the property source's read only state
     */
    public void setReadOnly(boolean readOnly) {
        this.readOnly = readOnly;
    }

}
