/*
* � Copyright IBM Corp. 2014
*
* 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.singlepageapp;
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.text.MessageFormat;
import java.util.ArrayList;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
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.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.swt.SWTLayoutUtils;
import com.ibm.commons.swt.SWTUtils;
import com.ibm.commons.swt.data.controls.DCPanel;
import com.ibm.commons.swt.data.controls.DCUtils;
import com.ibm.commons.util.StringUtil;
import com.ibm.commons.xml.DOMUtil;
import com.ibm.designer.domino.constants.XSPAttributeNames;
import com.ibm.designer.domino.constants.XSPTagNames;
import com.ibm.designer.domino.ide.resources.extensions.DesignerProject;
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.XPagesKey;
import com.ibm.designer.domino.xsp.api.util.XPagesPropertiesViewUtils;
import com.ibm.designer.domino.xsp.dominoutils.DominoImportException;
import com.ibm.designer.domino.xsp.dominoutils.DominoUtil;
import com.ibm.designer.domino.xsp.utils.FormModelUtil;
import com.ibm.xsp.extlib.designer.tooling.constants.IExtLibAttrNames;
import com.ibm.xsp.extlib.designer.tooling.constants.IExtLibTagLib;
import com.ibm.xsp.extlib.designer.tooling.constants.IExtLibTagNames;
import com.ibm.xsp.extlib.designer.tooling.utils.ExtLibToolingLogger;
import com.ibm.xsp.extlib.designer.tooling.utils.WizardUtils;
import com.ibm.xsp.extlib.designer.tooling.visualizations.AbstractCommonControlVisualizer;
import com.ibm.xsp.registry.FacesRegistry;
/**
* @author Gary Marjoram
*
*/
public class WizardSubPageDataSource extends WizardSubPage {
public static final int DS_VIEW = 0;
public static final int DS_DOC = 1;
private int dsType;
private DCPanel _mainPanel;
private ComplexPanelComposite dynamicComposite;
private Node clonedXPageViewElement;
public Element viewDOMElement;
public Element dsElement;
private DataNode viewDataNode;
private PanelExtraData extraData;
private DataNode childDataSourceDataNode;
private XPagesKey key;
private String savedServerName = "";
private String savedDbName = "";
private String savedFormName = "";
private String savedViewName = "";
private String[][] savedViewColumns;
private ArrayList<FormField> savedFormFields;
public WizardSubPageDataSource(WizardDataSub pd, int t) {
super(pd);
dsType = t;
Document doc = null;
Node currentNode = wizardData.panelData.getNode();
if (currentNode != null) {
doc = currentNode.getOwnerDocument();
}
if (doc != null) {
// First find the <view> node on the page that we are dealing with..
Element originalXPageViewNode = XPagesDOMUtil.getViewNode(doc);
if (originalXPageViewNode != null) {
clonedXPageViewElement = originalXPageViewNode.cloneNode(false);
}
//clone the paneldata
extraData = new PanelExtraData();
extraData.setDesignerProject(wizardData.panelData.getDesignerProject());
extraData.setNode(clonedXPageViewElement);
extraData.setDocument(clonedXPageViewElement.getOwnerDocument());
extraData.setHostWorkbenchPart(wizardData.panelData.getHostWorkbenchPart());
extraData.setWorkbenchPart(wizardData.panelData.getWorkbenchPart());
}
}
@Override
public void createControl(Composite parent) {
container = new Composite(parent, SWT.NONE);
GridLayout layout = WizardUtils.createGridLayout(2, 5);
container.setLayout(layout);
WizardUtils.createLabel(container, "Select Data Source :", 1); // $NLX-WizardSubPageDataSource.SelectDataSource-1$
Combo dsCombo = WizardUtils.createCombo(container ,1, null);
if (dsType == DS_DOC) {
String [] dsItems = {"Domino Document"}; // $NLX-WizardSubPageDataSource.DominoDocument-1$
dsCombo.setItems(dsItems);
} else {
String [] dsItems = {"Domino View"}; // $NLX-WizardSubPageDataSource.DominoView-1$
dsCombo.setItems(dsItems);
}
dsCombo.select(0);
_mainPanel = new DCPanel(container, SWT.NONE);
layout = SWTLayoutUtils.createLayoutDefaultSpacing(1);
_mainPanel.setLayout(layout);
GridData data = new GridData(GridData.FILL_HORIZONTAL);
data.horizontalSpan = 2;
_mainPanel.setLayoutData(data);
viewDataNode = initData(_mainPanel);
dynamicComposite = new ComplexPanelComposite(_mainPanel, SWT.NONE);
dynamicComposite.setLayoutData(GridDataFactory.copyData(data));
dynamicComposite.updatePanelData(wizardData.panelData);
updateUI();
setControl(container);
setPageComplete(true);
}
@Override
public void widgetSelected(SelectionEvent arg0) {
}
@Override
public void refreshData() {
super.refreshData();
setMessage(getStepTxt() + MessageFormat.format("Configure the Data Source for the \"{0}\" Application Page.", pageData.name), IMessageProvider.INFORMATION); // $NLX-WizardSubPageDataSource.ConfiguretheDataSourceforthe0Appl-1$
}
@Override
public void pageDeleted(int idx) {
}
//
// Links the UI to a dummy document element
//
private DataNode initData(Composite parent) {
DataNode dn = DCUtils.findDataNode(parent, true); //modify the DataNode to refer to our dataView tag!!
ILoader xpagesDOMLoader = XPagesPropertiesViewUtils.getXPagesMultiDomLoader(wizardData.panelData.getDesignerProject());
IClassDef classDef = getClassDef(xpagesDOMLoader, IExtLibTagLib.EXT_LIB_NAMESPACE_URI, IExtLibTagNames.EXT_LIB_TAG_DATA_VIEW);
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));
getPanelKey();
return dn;
}
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;
}
//
// Gets the key for the UI Panel to display
//
private void getPanelKey() {
if (dsType == DS_DOC) {
key = new XPagesKey(AbstractCommonControlVisualizer.XP_CORE_NAMESPACE, XSPTagNames.XSP_TAG_DATASOURCE_DOMINO_DOCUMENT);
} else {
key = new XPagesKey(AbstractCommonControlVisualizer.XP_CORE_NAMESPACE, XSPTagNames.XSP_TAG_DATASOURCE_DOMINO_VIEW);
}
}
//
// Display/Update the Panel
//
private void updateUI(){
try {
updateDataNode(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);
}
//
// Links the Panel to the dummy element and sets the initial state
//
private void updateDataNode(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();
//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());
dsElement = (Element) 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, dsElement, null);
if(dsElement != null && StringUtil.isEmpty(DOMUtil.getAttributeValue(dsElement, IExtLibAttrNames.EXT_LIB_ATTR_VAR))){
// Generate a unique var name for this dataSource
String var;
if (dsType == DS_DOC) {
var = pageData.name + "Document"; // $NON-NLS-1$
} else {
var = pageData.name + "View"; // $NON-NLS-1$
}
XPagesDOMUtil.setAttribute(dsElement, IExtLibAttrNames.EXT_LIB_ATTR_VAR, var);
}
}
DCUtils.initDataBinding(dynamicComposite.getParent());
DataNode dataNode = DCUtils.findDataNode(dynamicComposite.getParent(), true);
childDataSourceDataNode = dataNode;
if(childDataSourceDataNode != null){
childDataSourceDataNode.setClassDef(def);
childDataSourceDataNode.setDataProvider(new SingleCollection(dsElement));
}
}finally{
//Format the tag and update the UI
XPagesDOMUtil.formatNode(viewDOMElement, null);
}
}
//
// Utility function to retrieve a value from the DataNode
//
private String getValueFromDataNode(String attr) {
String value = "";
if (childDataSourceDataNode != null) {
IMember member = childDataSourceDataNode.getMember(attr);
if (member instanceof IAttribute) {
try {
value = childDataSourceDataNode.getValue((IAttribute) member);
}
catch (NodeException e) {
}
}
}
return value;
}
//
// Gets the DB Name from the UI
//
public String getDbName() {
return getValueFromDataNode(XSPAttributeNames.XSP_ATTR_DATABASE_NAME);
}
//
// Gets the View Name from the UI
//
public String getViewName() {
return getValueFromDataNode(XSPAttributeNames.XSP_ATTR_VIEW_NAME);
}
//
// Gets the Form Name from the UI
//
public String getFormName() {
return getValueFromDataNode(XSPAttributeNames.XSP_ATTR_FORM_NAME);
}
//
// Gets the var element from the UI
//
public String getVarName() {
return getValueFromDataNode(XSPAttributeNames.XSP_ATTR_VAR);
}
//
// Gets action from the UI
//
public String getAction() {
return getValueFromDataNode(XSPAttributeNames.XSP_ATTR_ACTION);
}
//
// Gets documentId from the UI
//
public String getDocumentId() {
return getValueFromDataNode(XSPAttributeNames.XSP_ATTR_DOCUMENT_ID);
}
//
// Get computeWithFrom from the UI
//
public String getComputeWithForm() {
return getValueFromDataNode(XSPAttributeNames.XSP_ATTR_COMPUTE_WITH_FORM);
}
//
// Gets column Titles and Names for the selected View
//
public String [][] getViewColumns() {
String dbName = getDbName();
DesignerProject prj = extraData.getDesignerProject();
if (StringUtil.isEmpty(dbName)) {
if (prj != null) {
dbName = prj.getDatabaseName();
}
}
if (StringUtil.isEmpty(dbName)) {
return null;
}
String serverName = prj != null ? prj.getServerName() : null;
if (StringUtil.isEmpty(serverName)) {
serverName = DominoUtil.LOCAL_CLIENT;
}
// Check if the dbName contains a server
if (dbName.contains(DominoUtil.DB_SERVER_SEPARATOR)) {
serverName = dbName.substring(0, dbName.indexOf(DominoUtil.DB_SERVER_SEPARATOR));
dbName = dbName.substring(dbName.indexOf(DominoUtil.DB_SERVER_SEPARATOR) + 2);
}
String viewName = getViewName();
if (StringUtil.isEmpty(viewName)) {
return null;
}
if (!hasDataSourceChanged(serverName, dbName, "", viewName)) {
return savedViewColumns;
}
savedServerName = serverName;
savedDbName = dbName;
savedFormName = "";
savedViewName = viewName;
savedViewColumns = null;
try {
// GMAM9PBDPA - Show hidden columns
String[][] columns = WizardUtils.getViewColumns(serverName, dbName, viewName, false, false);
if (columns != null && columns.length > 0) {
savedViewColumns = columns;
}
}
catch (DominoImportException e) {
}
return savedViewColumns;
}
//
// Gets form fields for the selected Form
//
public ArrayList<FormField> getFormFields() {
String dbName = getDbName();
DesignerProject prj = extraData.getDesignerProject();
if (StringUtil.isEmpty(dbName)) {
if (prj != null) {
dbName = prj.getDatabaseName();
}
}
if (StringUtil.isEmpty(dbName)) {
return new ArrayList<FormField>();
}
String serverName = prj != null ? prj.getServerName() : null;
if (StringUtil.isEmpty(serverName)) {
serverName = DominoUtil.LOCAL_CLIENT;
}
// Check if the dbName contains a server
if (dbName.contains(DominoUtil.DB_SERVER_SEPARATOR)) {
serverName = dbName.substring(0, dbName.indexOf(DominoUtil.DB_SERVER_SEPARATOR));
dbName = dbName.substring(dbName.indexOf(DominoUtil.DB_SERVER_SEPARATOR) + 2);
}
String formName = getFormName();
if (StringUtil.isEmpty(formName)) {
return new ArrayList<FormField>();
}
if (!hasDataSourceChanged(serverName, dbName, formName, "")) {
return savedFormFields;
}
savedServerName = serverName;
savedDbName = dbName;
savedFormName = formName;
savedViewName = "";
savedFormFields = new ArrayList<FormField>();
try {
savedFormFields = WizardUtils.getFormFields(serverName, dbName, formName);
}
catch (DominoImportException e) {
}
return savedFormFields;
}
//
// Returns the dataSource type
//
public int getType() {
return dsType;
}
//
// Returns the next Page in the Wizard
//
@Override
public WizardPage getNextPage() {
refreshData();
switch(dsType) {
case DS_VIEW:
if (!(pageData.wizardPage[2] instanceof WizardSubPageDataView)) {
pageData.wizardPage[2] = new WizardSubPageDataView(pageData);
((Wizard)getWizard()).addPage(pageData.wizardPage[2]);
}
return(pageData.wizardPage[2]);
case DS_DOC:
if (!(pageData.wizardPage[2] instanceof WizardSubPageFormTable)) {
pageData.wizardPage[2] = new WizardSubPageFormTable(pageData);
((Wizard)getWizard()).addPage(pageData.wizardPage[2]);
}
return(pageData.wizardPage[2]);
}
return null;
}
//
// Generate the DataSource markup
//
@Override
public void addElementMarkup(Element base, FacesRegistry registry) {
Document doc = base.getOwnerDocument();
Element dominoEl = null;
Element dataEl = null;
// Setup the main elements
dataEl = FormModelUtil.createElement(doc, registry, AbstractCommonControlVisualizer.XP_CORE_NAMESPACE, XSPTagNames.XSP_TAG_THIS_DATA);
switch(dsType) {
case DS_VIEW:
dominoEl = FormModelUtil.createElement(doc, registry, AbstractCommonControlVisualizer.XP_CORE_NAMESPACE, XSPTagNames.XSP_TAG_DATASOURCE_DOMINO_VIEW);
break;
case DS_DOC:
dominoEl = FormModelUtil.createElement(doc, registry, AbstractCommonControlVisualizer.XP_CORE_NAMESPACE, XSPTagNames.XSP_TAG_DATASOURCE_DOMINO_DOCUMENT);
break;
default:
return;
}
// Add the common attributes
if (StringUtil.isNotEmpty(getVarName())) {
FormModelUtil.setAttribute(dominoEl, XSPAttributeNames.XSP_ATTR_VAR, getVarName());
}
if (StringUtil.isNotEmpty(getDbName())) {
if (StringUtil.compareToIgnoreCase(extraData.getDesignerProject().getDatabaseName(), getDbName()) != 0) {
FormModelUtil.setAttribute(dominoEl, XSPAttributeNames.XSP_ATTR_DATABASE_NAME, getDbName());
}
}
// Add the specific attributes
switch(dsType) {
case DS_VIEW:
if (StringUtil.isNotEmpty(getViewName())) {
FormModelUtil.setAttribute(dominoEl, XSPAttributeNames.XSP_ATTR_VIEW_NAME, getViewName());
}
break;
case DS_DOC:
if (StringUtil.isNotEmpty(getFormName())) {
FormModelUtil.setAttribute(dominoEl, XSPAttributeNames.XSP_ATTR_FORM_NAME, getFormName());
}
if (StringUtil.isNotEmpty(getAction())) {
FormModelUtil.setAttribute(dominoEl, XSPAttributeNames.XSP_ATTR_ACTION, getAction());
}
if (StringUtil.isNotEmpty(getDocumentId())) {
FormModelUtil.setAttribute(dominoEl, XSPAttributeNames.XSP_ATTR_DOCUMENT_ID, getDocumentId());
}
if (StringUtil.isNotEmpty(getComputeWithForm())) {
FormModelUtil.setAttribute(dominoEl, XSPAttributeNames.XSP_ATTR_COMPUTE_WITH_FORM, getComputeWithForm());
}
break;
}
dataEl.appendChild(dominoEl);
base.appendChild(dataEl);
}
//
// Checks has the DataSource changed
//
public boolean hasDataSourceChanged(String serverName, String dbName, String formName, String viewName) {
if (StringUtil.compareToIgnoreCase(serverName, savedServerName) != 0) {
return true;
}
if (StringUtil.compareToIgnoreCase(dbName, savedDbName) != 0) {
return true;
}
if (StringUtil.compareToIgnoreCase(formName, savedFormName) != 0) {
return true;
}
if (StringUtil.compareToIgnoreCase(viewName, savedViewName) != 0) {
return true;
}
return (false);
}
//
// Clears the DataSource cache data
//
public void clearCachedData() {
savedServerName = "";
savedDbName = "";
savedFormName = "";
savedViewName = "";
}
@Override
public boolean validatePage() {
switch(dsType) {
case DS_VIEW:
if(StringUtil.isEmpty(getViewName())) {
String msg = "You have not selected a View for this Data Source.\n" + // $NLX-WizardSubPageDataSource.YouhavenotselectedaViewforthisDat-1$
"This mobile application will have errors as a result."; // $NLX-WizardSubPageDataSource.Thismobileapplicationwillhavecomp-1$
return WizardUtils.displayContinueDialog(this.getShell(), WizardData.WIZARD_TITLE, msg);
}
break;
case DS_DOC:
if(StringUtil.isEmpty(getFormName())) {
String msg = "You have not selected a Form for this Data Source.\n" + // $NLX-WizardSubPageDataSource.YouhavenotselectedaFormforthisDat-1$
"This Document Viewer will not display any data as a result."; // $NLX-WizardSubPageDataSource.TheassociatedformTablewillnotdisp-1$
return WizardUtils.displayContinueDialog(this.getShell(), WizardData.WIZARD_TITLE, msg);
}
break;
}
return true;
}
//
// Class to model a Form Field
//
public static class FormField {
//
// Form Field Types
//
public static final int TEXT = 1280;
public static final int NUMBER = 768;
public static final int DATETIME = 1024;
public static final int RICH = 1;
public static final int CHECK = 1281;
public static final int AUTHOR = 1076;
public static final int NAME = 1074;
public static final int READER = 1075;
public static final int FORMULA = 1536;
//
// Control Types
//
public static final int NOT_SUPPORTED = -1;
public static final int EDIT_BOX = 0;
public static final int RICH_TEXT = 1;
public static final int DATE_ONLY = 2;
public static final int TIME_ONLY = 3;
public static final int DATE_AND_TIME = 4;
public static final String [] controlNames = {"Edit Box", "Rich Text", "Date only", "Time only", "Date and Time"}; // $NLX-WizardSubPageDataSource.EditBox-1$ $NLX-WizardSubPageDataSource.RichText-2$ $NLX-WizardSubPageDataSource.Dateonly-3$ $NLX-WizardSubPageDataSource.Timeonly-4$ $NLX-WizardSubPageDataSource.DateandTime-5$
public String fieldName;
public String label;
public int type;
public int control;
public boolean checked;
public FormField(String fieldName, int type) {
this.fieldName = fieldName;
this.label = fieldName;
this.type = type;
this.control = getDefaultControl(type);
this.checked = false;
}
private int getDefaultControl(int type) {
switch (type) {
case RICH:
return RICH_TEXT;
case DATETIME:
return DATE_ONLY;
case FORMULA:
return NOT_SUPPORTED;
default:
return EDIT_BOX;
}
}
public static String getControlName(int control) {
return controlNames[control];
}
}
}