/* * � Copyright IBM Corp. 2010 * * 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.component.rest; import static com.ibm.domino.services.HttpServiceConstants.HTTP_GET; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Vector; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import javax.faces.el.ValueBinding; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lotus.domino.DateRange; import com.ibm.commons.util.StringUtil; import com.ibm.domino.services.ServiceException; import com.ibm.domino.services.rest.RestServiceEngine; import com.ibm.domino.services.rest.das.view.RestViewColumn; import com.ibm.domino.services.rest.das.view.RestViewJsonLegacyService; import com.ibm.domino.services.rest.das.view.ViewParameters; import com.ibm.domino.xsp.module.nsf.NotesContext; import com.ibm.xsp.ajax.AjaxUtil; import com.ibm.xsp.designer.context.XSPContext; import com.ibm.xsp.extlib.resources.ExtLibResources; import com.ibm.xsp.model.domino.DominoUtils; import com.ibm.xsp.resource.DojoModuleResource; import com.ibm.xsp.util.StateHolderUtil; import com.ibm.xsp.util.TypedUtil; /** * Retrieve content of a Notes/Domino calendar view in JSON format * * @author Martin Donnelly * */ public class DominoCalendarJsonLegacyService extends DominoService { private String var; private String viewName; private Object keys; private Boolean keysExactMatch; private String colCalendarDate; private String colStartTime; private String colEndTime; private String colSubject; private String colAltSubject; private String colEntryIcon; private String colEntryType; private String colChair; private String colConfidential; private String colStatus; private String colCustomData; private List<RestViewColumn> columns; private static String [] defaultColumns = { "$134", // colCalendarDate "$149", // colEntryIcon "$144", // colStartTime "$146", // colEndTime "$147", // colSubject "$152", // colEntryType "$153", // colChair "$154", // colConfidential "$160", // colStatus "$151", // colAltSubject "$UserData" // colCustomData $NON-NLS-1$ }; public DominoCalendarJsonLegacyService() { } @Override public boolean writePageMarkup(FacesContext context, UIBaseRestService parent, ResponseWriter writer) throws IOException { writeDojoStore(context, parent, writer); return true; } @Override public String getStoreDojoType() { return "dwa.data.DominoCalendarStore"; // $NON-NLS-1$ } @Override public DojoModuleResource getStoreDojoModule() { return ExtLibResources.extlibDominoCalendarRestStore; } @Override public void writeDojoStore(FacesContext context, UIBaseRestService parent, ResponseWriter writer) throws IOException { String jsId = parent.getDojoStoreId(context); String dojoType = getDojoType(); if(StringUtil.isEmpty(dojoType)) { dojoType = getStoreDojoType(); DojoModuleResource dojoRes = getStoreDojoModule(); if(dojoRes!=null) { ExtLibResources.addEncodeResource(context, dojoRes); } } // Only needed for client-side debugging (otherwise the dojo require is enough): // ExtLibResources.addEncodeResource(context, new ScriptResource("/.ibmxspres/.dwa/cv/calendarView.js", true)); // ExtLibResources.addEncodeResource(context, new ScriptResource("/.ibmxspres/.dwa/cv/calendarDataStore.js", true)); // ExtLibResources.addEncodeResource(context, new ScriptResource("/.ibmxspres/.dwa/date/calendar.js", true)); // ExtLibResources.addEncodeResource(context, new ScriptResource("/.ibmxspres/.dwa/data/DominoCalendarStore.js", true)); if(dojoType!=null) { writer.startElement("span",null); // $NON-NLS-1$ writeId(writer, context, parent); writer.writeAttribute("jsId",jsId,null); // $NON-NLS-1$ writeDojoStoreAttributes(context, parent, writer, dojoType); // PHIL: this is not needed // // TODO do we need to support AJAX this way? // String pathInfo = parent.getPathInfo(); // if (StringUtil.isNotEmpty(pathInfo)) { // writer.writeAttribute("pathInfo", pathInfo, null); // $NON-NLS-1$ // } writer.endElement("span"); // $NON-NLS-1$ writer.write('\n'); } } @Override public void writeDojoStoreAttributes(FacesContext context, UIBaseRestService parent, ResponseWriter writer, String dojoType) throws IOException { String pathInfo = parent.getPathInfo(); String url = parent.getUrlPath(context,pathInfo,null); writer.writeAttribute("dojoType",dojoType,null); // $NON-NLS-1$ writer.writeAttribute("target",url,null); // $NON-NLS-1$ writer.writeAttribute("idAttribute","@unid",null); // $NON-NLS-1$ $NON-NLS-2$ // Create the extra parameters StringBuilder b = new StringBuilder(); String viewId = parent.getAjaxViewid(context); if(StringUtil.isNotEmpty(viewId)) { b.append(b.length()==0?'?':'&'); b.append(AjaxUtil.AJAX_VIEWID); b.append('='); b.append(viewId); } String targetId = parent.getAjaxTarget(context,pathInfo); if(StringUtil.isNotEmpty(targetId)) { b.append(b.length()==0?'?':'&'); b.append(AjaxUtil.AJAX_AXTARGET); b.append('='); b.append(targetId); } String extraArgs = context.getExternalContext().encodeActionURL(b.toString()); if(StringUtil.isNotEmpty(extraArgs)) { // remove the leading '?' writer.writeAttribute("extraArgs",extraArgs.substring(1),null); // $NON-NLS-1$ } } public String getVar() { return var; } public void setVar(String var) { this.var = var; } public String getViewName() { if (viewName != null) { return viewName; } ValueBinding vb = getValueBinding("viewName"); //$NON-NLS-1$ if (vb != null) { return (String)vb.getValue(getFacesContext()); } return null; } public void setViewName(String viewName) { this.viewName = viewName; } public Object getKeys() { if (keys != null) { return keys; } ValueBinding vb = getValueBinding("keys"); //$NON-NLS-1$ if (vb != null) { return vb.getValue(getFacesContext()); } return null; } public void setKeys(Object keys) { this.keys = keys; } public boolean isKeysExactMatch() { if (keysExactMatch != null) { return keysExactMatch; } ValueBinding vb = getValueBinding("keysExactMatch"); //$NON-NLS-1$ if (vb != null) { Boolean v = (Boolean)vb.getValue(getFacesContext()); if(v!=null) { return v; } } return false; } public void setKeysExactMatch(boolean keysExactMatch) { this.keysExactMatch = keysExactMatch; } public List<RestViewColumn> getColumns() { return columns; } public void addColumn(DominoViewColumn column) { if(columns==null) { columns = new ArrayList<RestViewColumn>(); } columns.add(column); } /* The 11 Magic Calendar Columns */ // 1 public void setColCalendarDate(String colCalendarDate) { this.colCalendarDate = colCalendarDate; } public String getColCalendarDate() { if (colCalendarDate != null) { return colCalendarDate; } ValueBinding vb = getValueBinding("colCalendarDate"); //$NON-NLS-1$ if (vb != null) { return (String)vb.getValue(getFacesContext()); } return colCalendarDate; } // 2 public void setColStartTime(String colStartTime) { this.colStartTime = colStartTime; } public String getColStartTime() { if (colStartTime != null) { return colStartTime; } ValueBinding vb = getValueBinding("colStartTime"); //$NON-NLS-1$ if (vb != null) { return (String)vb.getValue(getFacesContext()); } return colStartTime; } // 3 public void setColEndTime(String colEndTime) { this.colEndTime = colEndTime; } public String getColEndTime() { if (colEndTime != null) { return colEndTime; } ValueBinding vb = getValueBinding("colEndTime"); //$NON-NLS-1$ if (vb != null) { return (String)vb.getValue(getFacesContext()); } return colEndTime; } // 4 public void setColSubject(String colSubject) { this.colSubject = colSubject; } public String getColSubject() { if (colSubject != null) { return colSubject; } ValueBinding vb = getValueBinding("colSubject"); //$NON-NLS-1$ if (vb != null) { return (String)vb.getValue(getFacesContext()); } return colSubject; } // 5 public void setColAltSubject(String colAltSubject) { this.colAltSubject = colAltSubject; } public String getColAltSubject() { if (colAltSubject != null) { return colAltSubject; } ValueBinding vb = getValueBinding("colAltSubject"); //$NON-NLS-1$ if (vb != null) { return (String)vb.getValue(getFacesContext()); } return colAltSubject; } // 6 public void setColEntryIcon(String colEntryIcon) { this.colEntryIcon = colEntryIcon; } public String getColEntryIcon() { if (colEntryIcon != null) { return colEntryIcon; } ValueBinding vb = getValueBinding("colEntryIcon"); //$NON-NLS-1$ if (vb != null) { return (String)vb.getValue(getFacesContext()); } return colEntryIcon; } // 7 public void setColEntryType(String colEntryType) { this.colEntryType = colEntryType; } public String getColEntryType() { if (colEntryType != null) { return colEntryType; } ValueBinding vb = getValueBinding("colEntryType"); //$NON-NLS-1$ if (vb != null) { return (String)vb.getValue(getFacesContext()); } return colEntryType; } // 8 public void setColChair(String colChair) { this.colChair = colChair; } public String getColChair() { if (colChair != null) { return colChair; } ValueBinding vb = getValueBinding("colChair"); //$NON-NLS-1$ if (vb != null) { return (String)vb.getValue(getFacesContext()); } return colChair; } // 9 public void setColConfidential(String colConfidential) { this.colConfidential = colConfidential; } public String getColConfidential() { if (colConfidential != null) { return colConfidential; } ValueBinding vb = getValueBinding("colConfidential"); //$NON-NLS-1$ if (vb != null) { return (String)vb.getValue(getFacesContext()); } return colConfidential; } // 10 public void setColStatus(String colStatus) { this.colStatus = colStatus; } public String getColStatus() { if (colStatus != null) { return colStatus; } ValueBinding vb = getValueBinding("colStatus"); //$NON-NLS-1$ if (vb != null) { return (String)vb.getValue(getFacesContext()); } return colStatus; } // 11 public void setColCustomData(String colCustomData) { this.colCustomData = colCustomData; } public String getColCustomData() { if (colCustomData != null) { return colCustomData; } ValueBinding vb = getValueBinding("colCustomData"); //$NON-NLS-1$ if (vb != null) { return (String)vb.getValue(getFacesContext()); } return colCustomData; } @Override public Object saveState(FacesContext context) { Object[] state = new Object[20]; state[0] = super.saveState(context); state[1] = var; state[2] = viewName; state[3] = StateHolderUtil.saveList(context, columns); state[4] = colCalendarDate; state[5] = colStartTime; state[6] = colEndTime; state[7] = colSubject; state[8] = colAltSubject; state[9] = colEntryIcon; state[10] = colEntryType; state[11] = colChair; state[12] = colConfidential; state[13] = colStatus; state[14] = colCustomData; // state[16] = keys; // state[17] = keysExactMatch; // state[4] = globalValues; // state[5] = systemColumns; // state[6] = defaultColumns; // state[7] = start; // state[8] = count; // state[9] = sortColumn; // state[10] = sortOrder; // state[11] = expandLevel; // state[12] = categoryFilter; // state[13] = startKeys; // state[14] = search; // state[15] = parentId; // state[16] = keys; // state[17] = keysExactMatch; // state[18] = searchMaxDocs; // state[19] = ignoreRequestParams; return state; } @Override public void restoreState(FacesContext context, Object value) { Object[] state = (Object[])value; super.restoreState(context, state[0]); var = (String)state[1]; viewName = (String)state[2]; columns = StateHolderUtil.restoreList(context, getComponent(), state[3]); colCalendarDate = (String)state[4]; colStartTime = (String)state[5]; colEndTime = (String)state[6]; colSubject = (String)state[7]; colAltSubject = (String)state[8]; colEntryIcon = (String)state[9]; colEntryType = (String)state[10]; colChair = (String)state[11]; colConfidential = (String)state[12]; colStatus = (String)state[13]; colCustomData = (String)state[14]; // keys = (String)state[16]; // keysExactMatch = (Boolean)state[17]; // globalValues = (Integer)state[4]; // systemColumns = (Integer)state[5]; // defaultColumns = (Boolean)state[6]; // start = (Integer)state[7]; // count = (Integer)state[8]; // sortColumn = (String)state[9]; // sortOrder = (String)state[10]; // expandLevel = (Integer)state[11]; // categoryFilter = (String)state[12]; // startKeys = (String)state[13]; // search = (String)state[14]; // parentId = (String)state[15]; // searchMaxDocs = (Integer)state[18]; // ignoreRequestParams = (Boolean)state[19]; } public RestServiceEngine createEngine(FacesContext context, UIBaseRestService parent, HttpServletRequest httpRequest, HttpServletResponse httpResponse) { Parameters params = new Parameters(context, parent, httpRequest); return new Engine(httpRequest,httpResponse,params); } private class Engine extends RestViewJsonLegacyService { Engine(HttpServletRequest httpRequest, HttpServletResponse httpResponse, Parameters params) { super(httpRequest,httpResponse,params); setDefaultSession(DominoUtils.getCurrentSession()); setDefaultDatabase(DominoUtils.getCurrentDatabase()); } @Override public void renderService() throws ServiceException { // SPR# LHEY8YSE4F - calendar data does not refresh on IE due to browser caching problem // We override the renderService just to set the Expires header to -1 for IE only ... // and only for this specific service! If others report same issue then promote fix accordingly. super.renderService(); if (XSPContext.getXSPContext(FacesContext.getCurrentInstance()).getUserAgent().isIE()) { getHttpResponse().setHeader("Expires", "-1"); // $NON-NLS-1$ $NON-NLS-2$ } } } protected class Parameters implements ViewParameters { Parameters(FacesContext context, UIBaseRestService parent, HttpServletRequest httpRequest) { addKeys(context); addColumns(); } public boolean isCompact() { return DominoCalendarJsonLegacyService.this.isCompact(); } public String getContentType() { return DominoCalendarJsonLegacyService.this.getContentType(); } public List<RestViewColumn> getColumns() { return DominoCalendarJsonLegacyService.this.getColumns(); } public String getDatabaseName() { return DominoCalendarJsonLegacyService.this.getDatabaseName(); } public String getVar() { return DominoCalendarJsonLegacyService.this.getVar(); } public String getViewName() { return DominoCalendarJsonLegacyService.this.getViewName(); } public String getCategoryFilter() { return null; } /* no-ops for now at least - MWD */ public int getCount() { return Integer.MAX_VALUE; } public int getExpandLevel() { return 0; } public int getGlobalValues() { return -1; } public Object getKeys() { return DominoCalendarJsonLegacyService.this.getKeys(); } public String getParentId() { return null; } public String getSearch() { return null; } public int getSearchMaxDocs() { return 32; } public String getSortColumn() { return null; } public String getSortOrder() { return null; } public int getStart() { return 0; } public String getStartKeys() { return null; } public int getSystemColumns() { return -1; } public boolean isDefaultColumns() { return false; } public boolean isIgnoreRequestParams() { return false; } public boolean isKeysExactMatch() { return DominoCalendarJsonLegacyService.this.isKeysExactMatch(); } public String getFormName() { return null; } public boolean isComputeWithForm() { return false; } private void addColumns() { // TODO MWD Need to decide how to validate our properties // e.g. when do we use the default list v explicit col properties? if (StringUtil.isEmpty(colCalendarDate)) { // create default column listing for (int i = 0; i < defaultColumns.length; i++) { addColumn(new DominoViewColumn(defaultColumns[i])); } } else { String columnName = getColCalendarDate(); if (StringUtil.isNotEmpty(columnName)) { addColumn(new DominoViewColumn(defaultColumns[0], columnName)); } columnName = getColEntryIcon(); if (StringUtil.isNotEmpty(columnName)) { addColumn(new DominoViewColumn(defaultColumns[1], columnName)); } columnName = getColStartTime(); if (StringUtil.isNotEmpty(columnName)) { addColumn(new DominoViewColumn(defaultColumns[2], columnName)); } columnName = getColEndTime(); if (StringUtil.isNotEmpty(columnName)) { addColumn(new DominoViewColumn(defaultColumns[3], columnName)); } columnName = getColSubject(); if (StringUtil.isNotEmpty(columnName)) { addColumn(new DominoViewColumn(defaultColumns[4], columnName)); } columnName = getColEntryType(); if (StringUtil.isNotEmpty(columnName)) { addColumn(new DominoViewColumn(defaultColumns[5], columnName)); } columnName = getColChair(); if (StringUtil.isNotEmpty(columnName)) { addColumn(new DominoViewColumn(defaultColumns[6], columnName)); } columnName = getColConfidential(); if (StringUtil.isNotEmpty(columnName)) { addColumn(new DominoViewColumn(defaultColumns[7], columnName)); } columnName = getColStatus(); if (StringUtil.isNotEmpty(columnName)) { addColumn(new DominoViewColumn(defaultColumns[8], columnName)); } columnName = getColAltSubject(); if (StringUtil.isNotEmpty(columnName)) { addColumn(new DominoViewColumn(defaultColumns[9], columnName)); } columnName = getColCustomData(); if (StringUtil.isNotEmpty(columnName)) { addColumn(new DominoViewColumn(defaultColumns[10], columnName)); } } } private void addKeys(FacesContext context) { Map<String, String> parameterMap = TypedUtil.getRequestParameterMap(context.getExternalContext()); String startKey = parameterMap.get("startKey"); // $NON-NLS-1$ String untilKey = parameterMap.get("untilKey"); // $NON-NLS-1$ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); // $NON-NLS-1$ //System.out.println(startKey + " | " + untilKey); try { Date sDate = sdf.parse(startKey); Date eDate = sdf.parse(untilKey); DateRange dr = NotesContext.getCurrent().getCurrentSession().createDateRange(sDate, eDate); //System.out.println(dr.toString()); Vector v = new Vector(1); v.add(dr); DominoCalendarJsonLegacyService.this.setKeys(v); } catch (Exception e) { // TODO MWD log exception but do not throw error // Just continue - all entries will be retrieved } } public boolean isEntryCount() { return false; } } }