com.ibm.xsp.extlib.designer.tooling.palette.view.GenericViewDropDialog.java Source code

Java tutorial

Introduction

Here is the source code for com.ibm.xsp.extlib.designer.tooling.palette.view.GenericViewDropDialog.java

Source

/*
 *  Copyright IBM Corp. 2011
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at:
 * 
 * http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
 * implied. See the License for the specific language governing 
 * permissions and limitations under the License.
 */
package com.ibm.xsp.extlib.designer.tooling.palette.view;

import static com.ibm.xsp.extlib.designer.tooling.constants.IExtLibAttrNames.EXT_LIB_ATTR_DATA;
import static com.ibm.xsp.extlib.designer.tooling.constants.IExtLibAttrNames.EXT_LIB_ATTR_VALUE;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import com.ibm.commons.iloader.node.DataNode;
import com.ibm.commons.iloader.node.DataNodeAdapter;
import com.ibm.commons.iloader.node.IAttribute;
import com.ibm.commons.iloader.node.IClassDef;
import com.ibm.commons.iloader.node.ILoader;
import com.ibm.commons.iloader.node.IMember;
import com.ibm.commons.iloader.node.NodeException;
import com.ibm.commons.iloader.node.collections.SingleCollection;
import com.ibm.commons.iloader.node.views.DataNodeBinding;
import com.ibm.commons.swt.SWTLayoutUtils;
import com.ibm.commons.swt.SWTUtils;
import com.ibm.commons.swt.controls.LookupComboBox;
import com.ibm.commons.swt.data.controls.DCPanel;
import com.ibm.commons.swt.data.controls.DCUtils;
import com.ibm.commons.swt.data.dialog.LWPDCommonDialog;
import com.ibm.commons.util.StringUtil;
import com.ibm.commons.xml.DOMUtil;
import com.ibm.designer.domino.scripting.api.IScriptData.PublishedObject;
import com.ibm.designer.domino.scripting.api.published.PublishedUtil;
import com.ibm.designer.domino.xsp.api.panels.IPanelExtraData;
import com.ibm.designer.domino.xsp.api.panels.PanelExtraData;
import com.ibm.designer.domino.xsp.api.panels.complex.ComplexPanelComposite;
import com.ibm.designer.domino.xsp.api.util.XPagesDOMUtil;
import com.ibm.designer.domino.xsp.api.util.XPagesDataUtil;
import com.ibm.designer.domino.xsp.api.util.XPagesKey;
import com.ibm.designer.domino.xsp.api.util.XPagesPropertiesViewUtils;
import com.ibm.designer.domino.xsp.registry.ComplexDesignerExtension;
import com.ibm.designer.domino.xsp.registry.DesignerExtensionUtil;
import com.ibm.designer.prj.resources.commons.DesignerProjectException;
import com.ibm.xsp.extlib.designer.tooling.constants.IExtLibAttrNames;
import com.ibm.xsp.extlib.designer.tooling.utils.ExtLibToolingLogger;
import com.ibm.xsp.extlib.designer.tooling.utils.XPagesKeyLookup;
import com.ibm.xsp.registry.FacesComplexDefinition;
import com.ibm.xsp.registry.FacesDefinition;

/**
 * @author doconnor
 *
 */
public class GenericViewDropDialog extends LWPDCommonDialog {

    private IPanelExtraData extraData = null;
    private IPanelExtraData realData = null;

    private Node originalXPageViewNode = null;
    private Node clonedXPageViewElement = null;
    private DCPanel _mainPanel = null;

    private Element viewDOMElement = null;
    private DataNode viewDataNode = null;

    private XPagesKeyLookup _dataSources = null;
    private ComplexPanelComposite dynamicComposite;
    private final static String PAGE_DS_NS = "p.d.s.n.s"; // $NON-NLS-1$
    private LookupComboBox picker;
    private DataNode childDataSourceDataNode;
    private String title;
    private String ns;
    private String tag;

    private DataNodeAdapter dataNodeAdapter = new DataNodeAdapter() {

        /* (non-Javadoc)
         * @see com.ibm.commons.iloader.node.DataNodeAdapter#onValueChanged(com.ibm.commons.iloader.node.DataNode, int, java.lang.Object, com.ibm.commons.iloader.node.IAttribute)
         */
        @Override
        public void onValueChanged(DataNode source, int record, Object object, IAttribute attribute) {
            super.onValueChanged(source, record, object, attribute);
        }
    };

    /**
     * @param parentShell
     */
    public GenericViewDropDialog(Shell parentShell, IPanelExtraData data, String title, String ns, String tag,
            Document doc) {
        super(parentShell);
        this.title = title;
        this.ns = ns;
        this.tag = tag;
        if (data != null) {
            realData = data;

            // If doc is null then try to get it from the current node
            if (doc == null) {
                Node currentNode = data.getNode();
                if (currentNode != null) {
                    doc = currentNode.getOwnerDocument();
                }
            }

            // First find the <view> node on the page that we are dealing with..
            originalXPageViewNode = XPagesDOMUtil.getViewNode(doc);
            if (originalXPageViewNode != null) {
                clonedXPageViewElement = originalXPageViewNode.cloneNode(false);
            }

            //clone the paneldata
            extraData = new PanelExtraData();
            ((PanelExtraData) extraData).setDesignerProject(data.getDesignerProject());
            ((PanelExtraData) extraData).setNode(clonedXPageViewElement);
            ((PanelExtraData) extraData).setDocument(clonedXPageViewElement.getOwnerDocument());
            ((PanelExtraData) extraData).setHostWorkbenchPart(data.getHostWorkbenchPart());
            ((PanelExtraData) extraData).setWorkbenchPart(data.getWorkbenchPart());
        }
    }

    /* (non-Javadoc)
     * @see com.ibm.commons.swt.data.dialog.LWPDCommonDialog#getDialogTitle()
     */
    @Override
    protected String getDialogTitle() {
        return StringUtil.isNotEmpty(title) ? title : "Select Data Source for Data View"; // $NLX-GenericViewDropDialog.Selectdatasourcefordataview-1$
    }

    /* (non-Javadoc)
     * @see com.ibm.commons.swt.data.dialog.LWPDCommonDialog#fillClientArea(org.eclipse.swt.widgets.Composite)
     */
    @Override
    protected void fillClientArea(Composite parent) {
        if (parent.getLayout() instanceof GridLayout) {
            ((GridLayout) parent.getLayout()).marginWidth = 7;
            ((GridLayout) parent.getLayout()).marginHeight = 0;
        }

        _mainPanel = new DCPanel(parent, SWT.NONE);
        GridLayout layout = SWTLayoutUtils.createLayoutDefaultSpacing(1);
        _mainPanel.setLayout(layout);
        GridData data = SWTLayoutUtils.createGDFill();
        data.horizontalSpan = 2;
        _mainPanel.setLayoutData(data);

        viewDataNode = initData(_mainPanel);
        if (viewDataNode != null) {
            viewDataNode.addDataNodeListener(dataNodeAdapter);
        }

        Composite pickerParent = new Composite(_mainPanel, SWT.NONE);
        pickerParent.setLayout(SWTLayoutUtils.createLayoutNoMarginDefaultSpacing(2));
        pickerParent.setLayoutData(SWTLayoutUtils.createGDFillHorizontal());
        new Label(pickerParent, SWT.NONE).setText("&Show data from:"); // $NLX-AddViewControlDialog.Showdatafrom-1$
        picker = new LookupComboBox(pickerParent, SWT.DROP_DOWN | SWT.READ_ONLY, "datasource.id"); // $NON-NLS-1$

        picker.setLayoutData(SWTLayoutUtils.createGDFillHorizontal());
        picker.setFirstBlankLine(false);
        picker.setEditableLabels(false);
        picker.setLookup(_dataSources);

        dynamicComposite = new ComplexPanelComposite(_mainPanel, SWT.NONE);
        dynamicComposite.setLayoutData(GridDataFactory.copyData(data));
        dynamicComposite.updatePanelData(realData);

        picker.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(SelectionEvent event) {
                super.widgetSelected(event);
                updateUI();
                dynamicComposite.getDisplay().asyncExec(new Runnable() {

                    public void run() {
                        if (dynamicComposite.isDisposed()) {
                            return;
                        }
                        dynamicComposite.pack();
                        dynamicComposite.layout();
                        Composite parent = dynamicComposite.getParent();
                        Composite prevParent = parent;
                        while (parent != null && !parent.isDisposed()) {
                            try {
                                if (parent instanceof ScrolledComposite) {
                                    ((ScrolledComposite) parent)
                                            .setMinSize(prevParent.computeSize(SWT.DEFAULT, SWT.DEFAULT));
                                    break;
                                }
                                if (parent.isDisposed()) {
                                    return;
                                }
                                parent.pack();
                                parent.layout();
                            } catch (Throwable t) {
                                if (ExtLibToolingLogger.EXT_LIB_TOOLING_LOGGER.isErrorEnabled()) {
                                    ExtLibToolingLogger.EXT_LIB_TOOLING_LOGGER.errorp(this, "widgetSelected", t,
                                            "Error encountered when refreshing UI"); // $NON-NLS-1$ $NLE-DataViewDataPanel.ErrorencounteredwhenrefeshingUI-2$
                                }
                            }
                            prevParent = parent;
                            parent = parent.getParent();
                        }
                    }
                });
            }
        });
        picker.select(0);
        updateUI();
        setMessage(
                "Select the kind of data (the data source) to show in the view. You can also select the data source later in the Data properties for this view control.", // $NLX-AddViewControlDialog.Selectthekindofdatathedatasourcet-1$
                IMessageProvider.INFORMATION);

        Composite columns = new Composite(_mainPanel, SWT.NONE);
        columns.setLayout(SWTLayoutUtils.createLayoutNoMarginDefaultSpacing(2));
        Label l = new Label(columns, SWT.NONE);
        l.setText("");
        SWTUtils.setBackgroundColor(parent, parent.getBackground(), true);
        parent.layout(true);
        parent.pack();
    }

    private IClassDef getClassDef(ILoader xpagesDOMLoader, String ns, String tagName) {
        try {
            IClassDef classDef = xpagesDOMLoader.loadClass(ns, tagName);
            return classDef;
        } catch (NodeException e) {
            if (ExtLibToolingLogger.EXT_LIB_TOOLING_LOGGER.isErrorEnabled()) {
                String errMsg = "Internal error, failed to create an element for: {0}:{1}"; // $NLE-GenericViewDropDialog.Internalerrorfailedtocreateanelem-1$
                ExtLibToolingLogger.EXT_LIB_TOOLING_LOGGER.errorp(this, "getClassDef", e, errMsg, ns, tagName); //$NON-NLS-1$
            }
        }
        return null;
    }

    private DataNode initData(Composite parent) {
        DataNode dn = DCUtils.findDataNode(parent, true); //modify the DataNode to refer to our dataView tag!!

        ILoader xpagesDOMLoader = XPagesPropertiesViewUtils.getXPagesMultiDomLoader(extraData.getDesignerProject());

        IClassDef classDef = getClassDef(xpagesDOMLoader, ns, tag);
        dn.setClassDef(classDef);
        try {
            viewDOMElement = (Element) classDef.newInstance(clonedXPageViewElement);
        } catch (NodeException e) {
            if (ExtLibToolingLogger.EXT_LIB_TOOLING_LOGGER.isErrorEnabled()) {
                String msg = "Failed to create a new instance of dataView tag"; // $NLE-GenericViewDropDialog.FailedtocreateanewinstanceofdataV-1$
                ExtLibToolingLogger.EXT_LIB_TOOLING_LOGGER.errorp(this, "initData", e, msg); // $NON-NLS-1$
            }
        }
        dn.setDataProvider(new SingleCollection(viewDOMElement));
        updateLookup();
        return dn;

    }

    /* (non-Javadoc)
     * @see com.ibm.commons.swt.data.dialog.LWPDCommonDialog#needsProgressMonitor()
     */
    @Override
    protected boolean needsProgressMonitor() {
        return false;
    }

    /* (non-Javadoc)
     * @see com.ibm.commons.swt.data.dialog.LWPDCommonDialog#performDialogOperation(org.eclipse.core.runtime.IProgressMonitor)
     */
    @Override
    protected boolean performDialogOperation(IProgressMonitor progressMonitor) {
        return true;
    }

    private void updateDataNode(String value, XPagesKey key) throws NodeException {
        try {
            IMember dataAttr = viewDataNode.getMember(EXT_LIB_ATTR_DATA);
            IMember valueAttr = viewDataNode.getMember(EXT_LIB_ATTR_VALUE);
            //get the loader that is used to generate new Elements on the page
            ILoader loader = viewDataNode.getLoader();
            if (StringUtil.isEmpty(value)) { //probably not going to happen
                //Clear all attribute values.. set everything back to null!
                loader.setValue(viewDOMElement, (IAttribute) dataAttr, null, null);
                viewDataNode.setValue((IAttribute) valueAttr, null, null);
                if (childDataSourceDataNode != null) {
                    childDataSourceDataNode.removeDataNodeListener(dataNodeAdapter);
                }
                return;
            } else {
                //figure out which data source was selected from the combo box
                if (StringUtil.equals(key.getNamespaceUri(), PAGE_DS_NS)) {
                    if (childDataSourceDataNode != null) {
                        childDataSourceDataNode.removeDataNodeListener(dataNodeAdapter);
                    }
                    //This means the user has picked a data source that is defined at the page level
                    if (valueAttr instanceof IAttribute) {
                        String newVal = "#{" + value + "}";
                        viewDataNode.setValue((IAttribute) valueAttr, newVal, null);
                        //clear the data attribute also!
                        loader.setValue(viewDOMElement, (IAttribute) dataAttr, null, null);
                        dynamicComposite.getParent().setData(DCUtils.DATANODE_KEY,
                                new DataNodeBinding(viewDataNode));
                        if (childDataSourceDataNode != null) {
                            childDataSourceDataNode.removeDataNodeListener(this.dataNodeAdapter);
                            childDataSourceDataNode = null;
                        }
                    }
                } else {
                    //need to clear the value attribute in case it was previously set
                    viewDataNode.setValue((IAttribute) valueAttr, null, null);
                    //Get a class defintion for a new instance of the given tag (probably xp:dominoView)
                    IClassDef def = loader.loadClass(key.getNamespaceUri(), key.getTagName());
                    Object o = def.newInstance(viewDOMElement); //create a new tag
                    //in this case we know that 'data' is a 'complex attribute'.. but lets make sure
                    if (dataAttr instanceof IAttribute && dataAttr.getType() == IMember.TYPE_OBJECT) {
                        //add a <xp:this.data> to the current viewData tag and add the data source as a child of that!
                        viewDataNode.setObject(viewDOMElement, (IAttribute) dataAttr, o, null);
                        if (o instanceof Element && StringUtil.isEmpty(
                                DOMUtil.getAttributeValue((Element) o, IExtLibAttrNames.EXT_LIB_ATTR_VAR))) {
                            String[] vars = XPagesDOMUtil.getVars(((Element) o).getOwnerDocument(), null);
                            String var = XPagesDOMUtil.generateUniqueVar(Arrays.asList(vars), (Element) o, "view"); // $NON-NLS-1$
                            XPagesDOMUtil.setAttribute((Element) o, IExtLibAttrNames.EXT_LIB_ATTR_VAR, var);
                        }
                    }
                    DCUtils.initDataBinding(dynamicComposite.getParent());
                    DataNode dataNode = DCUtils.findDataNode(dynamicComposite.getParent(), true);
                    childDataSourceDataNode = dataNode;

                    if (childDataSourceDataNode != null) {
                        dataNode.setClassDef(def);
                        dataNode.setDataProvider(new SingleCollection(o));
                        childDataSourceDataNode.addDataNodeListener(this.dataNodeAdapter);
                    }
                }
            }
        } finally {
            //Format the tag and update the UI
            XPagesDOMUtil.formatNode(viewDOMElement, null);
        }
    }

    private void updateLookup() {
        //Get all of the data sources that support view data
        List<FacesDefinition> defs = XPagesDataUtil
                .getViewPanelDataSources(extraData.getDesignerProject().getFacesRegistry());
        if (defs != null) {
            ArrayList<String> names = new ArrayList<String>();
            ArrayList<XPagesKey> keys = new ArrayList<XPagesKey>();
            for (FacesDefinition def : defs) {
                String name = def.getTagName();
                if (def instanceof FacesComplexDefinition) {
                    //Get the display name for the data sources
                    ComplexDesignerExtension extsn = DesignerExtensionUtil
                            .getComplexExtension((FacesComplexDefinition) def);
                    if (extsn != null) {
                        name = StringUtil.getNonNullString(extsn.getDisplayName());
                    }
                }
                names.add(name);
                keys.add(new XPagesKey(def.getNamespaceUri(), def.getTagName()));
            }
            Map<String, PublishedObject> map = new HashMap<String, PublishedObject>();

            try {
                //Get all of the view data sources already defined in the XSP hierarchy
                PublishedUtil.getAllPublishedObjects(map, originalXPageViewNode, extraData.getDesignerProject(),
                        false);
            } catch (DesignerProjectException e) {
                if (ExtLibToolingLogger.EXT_LIB_TOOLING_LOGGER.isErrorEnabled()) {
                    ExtLibToolingLogger.EXT_LIB_TOOLING_LOGGER.errorp(this, "updateLookup", e, //$NON-NLS-1$ 
                            "Failed to find any data sources defined on the page.. An error was encountered by the published object utilities"); // $NLE-GenericViewDropDialog.Failedtofindanydatasourcesdefined-1$
                }
            }
            if (!map.isEmpty()) {
                Set<String> dsNames = map.keySet();
                for (String name : dsNames) {
                    PublishedObject po = map.get(name);
                    if (PublishedUtil.isViewDataSupported(po)) {

                        names.add(name);
                        //These are special data sources.. Page level data sources.. We will use a complex panel to display the information
                        //to be displayed in the event of one of these being used..
                        //See: com.ibm.xsp.extlib.designer.tooling.panels.complex.PageDataSourcePanel
                        keys.add(new XPagesKey(PAGE_DS_NS, "pageDataSource")); // $NON-NLS-1$
                    }
                }
            }
            _dataSources = new XPagesKeyLookup(keys.toArray(new XPagesKey[0]), names.toArray(new String[0]));
        }
    }

    private void updateUI() {
        if (!picker.isDisposed()) {
            String value = picker.getValue();
            if (StringUtil.isNotEmpty(value)) {
                for (int i = 0; i < _dataSources.size(); i++) {
                    if (StringUtil.equals(_dataSources.getCode(i), value)) {
                        XPagesKey key = _dataSources.getKey(i);
                        if (key != null) {
                            try {
                                updateDataNode(value, key);
                            } catch (NodeException e) {
                                ExtLibToolingLogger.EXT_LIB_TOOLING_LOGGER.error(e, e.toString());
                            }
                            dynamicComposite.updatePanel(key.getNamespaceUri(), key.getTagName());
                            SWTUtils.setBackgroundColor(dynamicComposite.getParent(),
                                    dynamicComposite.getParent().getBackground(), true);
                        }
                    }
                }
            }

        }
    }

    /* (non-Javadoc)
     * @see com.ibm.commons.swt.data.dialog.LWPDCommonDialog#useScrollableContents()
     */
    @Override
    protected boolean useScrollableContents() {
        return false;
    }

    public Element getElementToInsert() {
        return viewDOMElement;
    }

}