KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openi > olap > drillthrough > CustomDrillthroughUI


1 /*********************************************************************************
2  * The contents of this file are subject to the OpenI Public License Version 1.0
3  * ("License"); You may not use this file except in compliance with the
4  * License. You may obtain a copy of the License at
5  * http://www.openi.org/docs/LICENSE.txt
6  *
7  * Software distributed under the License is distributed on an "AS IS" basis,
8  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
9  * the specific language governing rights and limitations under the License.
10  *
11  * The Original Code is: OpenI Open Source
12  *
13  * The Initial Developer of the Original Code is Loyalty Matrix, Inc.
14  * Portions created by Loyalty Matrix, Inc. are
15  * Copyright (C) 2005 Loyalty Matrix, Inc.; All Rights Reserved.
16  *
17  * Contributor(s): ______________________________________.
18  *
19  ********************************************************************************/

20 package org.openi.olap.drillthrough;
21
22 import com.tonbeller.jpivot.core.ModelChangeEvent;
23 import com.tonbeller.jpivot.core.ModelChangeListener;
24 import com.tonbeller.jpivot.olap.model.Axis;
25 import com.tonbeller.jpivot.olap.model.Cell;
26 import com.tonbeller.jpivot.olap.model.Member;
27 import com.tonbeller.jpivot.olap.model.OlapException;
28 import com.tonbeller.jpivot.olap.model.OlapModel;
29 import com.tonbeller.jpivot.olap.navi.DrillThrough;
30 import com.tonbeller.jpivot.table.CellBuilder;
31 import com.tonbeller.jpivot.table.CellBuilderDecorator;
32 import com.tonbeller.jpivot.table.TableComponent;
33 import com.tonbeller.jpivot.table.TableComponentExtensionSupport;
34 import com.tonbeller.jpivot.xmla.*;
35 import com.tonbeller.wcf.component.RendererParameters;
36 import com.tonbeller.wcf.controller.Dispatcher;
37 import com.tonbeller.wcf.controller.DispatcherSupport;
38 import com.tonbeller.wcf.controller.RequestContext;
39 import com.tonbeller.wcf.controller.RequestListener;
40 import com.tonbeller.wcf.table.EmptyTableModel;
41 import com.tonbeller.wcf.table.ITableComponent;
42 import com.tonbeller.wcf.table.TableModel;
43 import com.tonbeller.wcf.table.TableModelDecorator;
44 import com.tonbeller.wcf.utils.DomUtils;
45 import org.apache.log4j.Logger;
46 import org.w3c.dom.Element JavaDoc;
47 import java.io.OutputStream JavaDoc;
48 import java.net.MalformedURLException JavaDoc;
49 import java.net.URL JavaDoc;
50 import java.text.DateFormat JavaDoc;
51 import java.text.SimpleDateFormat JavaDoc;
52 import java.util.ArrayList JavaDoc;
53 import java.util.Calendar JavaDoc;
54 import java.util.Date JavaDoc;
55 import java.util.HashMap JavaDoc;
56 import java.util.Iterator JavaDoc;
57 import java.util.List JavaDoc;
58 import java.util.Map JavaDoc;
59 import javax.servlet.http.HttpSession JavaDoc;
60 import javax.xml.soap.MessageFactory JavaDoc;
61 import javax.xml.soap.MimeHeaders JavaDoc;
62 import javax.xml.soap.Name JavaDoc;
63 import javax.xml.soap.SOAPBody JavaDoc;
64 import javax.xml.soap.SOAPConnectionFactory JavaDoc;
65 import javax.xml.soap.SOAPElement JavaDoc;
66 import javax.xml.soap.SOAPEnvelope JavaDoc;
67 import javax.xml.soap.SOAPException JavaDoc;
68 import javax.xml.soap.SOAPMessage JavaDoc;
69 import javax.xml.soap.SOAPPart JavaDoc;
70
71
72 public class CustomDrillthroughUI extends TableComponentExtensionSupport
73 implements ModelChangeListener {
74     private static Logger logger = Logger.getLogger(CustomDrillthroughUI.class);
75     public static final String JavaDoc ID = "drillThrough";
76     boolean available;
77     boolean renderActions;
78     Dispatcher dispatcher = new DispatcherSupport();
79     DrillThrough extension;
80     TableModelDecorator tableModel = new TableModelDecorator(EmptyTableModel
81             .instance());
82     OlapModel model = null;
83     
84     public String JavaDoc getId() {
85         return ID;
86     }
87     
88     public void initialize(RequestContext context, TableComponent table)
89     throws Exception JavaDoc {
90         super.initialize(context, table);
91         table.getOlapModel().addModelChangeListener(this);
92         model = table.getOlapModel();
93         
94         // does the underlying data model support drill?
95
if (!initializeExtension()) {
96             available = false;
97             
98             return;
99         }
100         
101         available = true;
102         
103         // extend the controller
104
table.getDispatcher().addRequestListener(null, null, dispatcher);
105         
106         // add some decorators via table.get/setRenderer
107
CellBuilder cb = table.getCellBuilder();
108         DomDecorator cr = new DomDecorator(table.getCellBuilder());
109         table.setCellBuilder(cr);
110     }
111     
112     public void startBuild(RequestContext context) {
113         super.startBuild(context);
114         renderActions = RendererParameters.isRenderActions(context);
115         
116         if (renderActions) {
117             dispatcher.clear();
118         }
119     }
120     
121     /** @return true if extension is available */
122     protected boolean initializeExtension() {
123         OlapModel om = table.getOlapModel();
124         extension = (DrillThrough) om.getExtension(DrillThrough.ID);
125         
126         return extension != null;
127     }
128     
129     protected boolean canDrillThrough(Cell cell) {
130         return extension.canDrillThrough((Cell) cell.getRootDecoree());
131     }
132     
133     /**
134      * returns a DrillThroughTableModel object for the drill through
135      * @param cell
136      * @return
137      */

138     protected TableModel drillThrough(Cell cell) {
139         return extension.drillThrough((Cell) cell.getRootDecoree());
140     }
141     
142     public boolean isAvailable() {
143         return available;
144     }
145     
146     public void modelChanged(ModelChangeEvent e) {
147     }
148     
149     public void structureChanged(ModelChangeEvent e) {
150         initializeExtension();
151         dispatcher.clear();
152     }
153     
154     public TableModel getTableModel() {
155         return tableModel;
156     }
157     
158     class DomDecorator extends CellBuilderDecorator {
159         DomDecorator(CellBuilder delegate) {
160             super(delegate);
161         }
162         
163         public Element JavaDoc build(Cell cell, boolean even) {
164             Element JavaDoc parent = super.build(cell, even);
165             
166             if (!enabled || !renderActions || (extension == null)) {
167                 return parent;
168             }
169             
170             String JavaDoc id = DomUtils.randomId();
171             
172             if (canDrillThrough(cell) && (!cell.isNull())) {
173                 // add a drill through child node to cell element
174
Element JavaDoc elem = table.insert("drill-through", parent);
175                 elem.setAttribute("id", id);
176                 elem.setAttribute("title", "Show source data");
177                 dispatcher.addRequestListener(id, null,
178                         new DrillThroughHandler(cell));
179             } else {
180                 // dont add anything
181
}
182             
183             return parent;
184         }
185     }
186     
187     class DrillThroughHandler implements RequestListener {
188         Cell cell;
189         
190         DrillThroughHandler(Cell cell) {
191             this.cell = cell;
192         }
193         
194         public void request(RequestContext context)
195         throws Exception JavaDoc {
196             if (canDrillThrough(cell)) {
197                 HttpSession JavaDoc session = context.getSession();
198                 final String JavaDoc drillTableRef = table.getOlapModel().getID()
199                 + ".drillthroughtable";
200                 ITableComponent tc = (ITableComponent) session.getAttribute(drillTableRef);
201                 
202                 // get a new drill through table model
203
TableModel tm = drillThrough(cell);
204                 XMLA_DrillThroughTableModel dmodel = (XMLA_DrillThroughTableModel) tm;
205                 String JavaDoc mdx = buildDrillThroughMdx(dmodel,
206                         (XMLA_Result) table.getOlapModel().getResult());
207                 logger.debug("Got DT Request. MDX : " + mdx);
208                 executeDrillQuery(context, (XMLA_Model) dmodel.getModel(), mdx);
209             }
210         }
211         
212         private void executeDrillQuery(RequestContext context, XMLA_Model model, String JavaDoc query)
213         throws Exception JavaDoc {
214             try {
215                 //this needs to be removed once we explictly add datasourceinfo in XMLA Query Tag
216

217                 // since we need the browser popup to save results.
218
// hence the need to set content type.
219
// If not set, results will be rendered on main analysis window
220
// should be done before flushing anything else.
221
context.getResponse()
222                 .setContentType("text/plain");
223                 context.getResponse()
224                 .setHeader("Pragma", "no-cache");
225                 context.getResponse()
226                 .setHeader("Content-Disposition",
227                 "attachment; filename=\"drillthrough.txt\"");
228                 
229                 OutputStream JavaDoc responseStream;
230                 responseStream = context.getResponse().getOutputStream();
231                 
232                 URL JavaDoc url = constructUrl(model.getUri(), model.getUser(), model.getPassword());
233                 try {
234                     
235                     String JavaDoc datasource = model.getDataSource();
236                     if(datasource == null || datasource.equals("")) {
237                         logger.debug("Datasource is not available in model.So discovering default one");
238                         XMLA_SOAP soap = new XMLA_SOAP(model.getUri(), model.getUser(),
239                                 model.getPassword());
240                         Map JavaDoc ds = soap.discoverDS();
241                         if(ds!=null) {
242                             datasource = (String JavaDoc)ds.get("DataSourceName");
243                         }
244                     }
245                     
246                     if(datasource == null || datasource.equals("")) {
247                         logger.error("Datasource is not found");
248                         return;
249                     }
250                     SOAPMessage JavaDoc message = DrillthroughHelper
251                     .constructDrillthroughSoapMessage(query, datasource,
252                             model.getCatalog());
253                     logger.debug("executing drillthrough request");
254                     DrillthroughHelper.executeDrillthrough(url,
255                             message, responseStream);
256                 } catch (Exception JavaDoc ex) {
257                     logger.error(ex);
258                     RequestContext.instance().setResponseComplete(true);
259                     try {
260                         if (responseStream != null) {
261                             responseStream.write(ex.getMessage().getBytes());
262                         }
263                     } catch (Exception JavaDoc exx) {
264                         logger.warn(
265                                 "Response OutputStream error/r/n root cause:/r/n"
266                                 + exx.getMessage());
267                     }
268                 }
269                 
270                 RequestContext.instance().setResponseComplete(true);
271             } catch (Exception JavaDoc se) {
272                 throw se;
273             }
274         }
275         
276         
277         
278         private URL JavaDoc constructUrl(String JavaDoc uri, String JavaDoc user, String JavaDoc password)
279         throws MalformedURLException JavaDoc {
280             URL JavaDoc url = null;
281             
282             try {
283                 url = new URL JavaDoc(uri);
284             } catch (MalformedURLException JavaDoc e1) {
285                 throw e1;
286             }
287             
288             if ((user != null) && (user.length() > 0)) {
289                 String JavaDoc newUri = url.getProtocol() + "://" + user;
290                 
291                 if ((password != null) && (password.length() > 0)) {
292                     newUri += (":" + password);
293                 }
294                 
295                 newUri += ("@" + url.getHost() + ":" + url.getPort()
296                         + url.getPath());
297                 
298                 try {
299                     url = new URL JavaDoc(newUri);
300                 } catch (MalformedURLException JavaDoc e2) {
301                     throw e2;
302                 }
303             }
304             
305             return url;
306         }
307         
308         private String JavaDoc buildDrillThroughMdx(
309                 XMLA_DrillThroughTableModel tmodel, XMLA_Result res) {
310             Axis[] axes = res.getAxes();
311             StringBuffer JavaDoc mdxBuf = new StringBuffer JavaDoc(" Drillthrough Select ");
312             int nXPositions = axes[0].getPositions().size();
313             int posIdx = 0;
314             
315             for (int i = 0; i < axes.length; i++) {
316                 // axis 0 ==> x-Coordinate
317
// axis 1 ==> y-Coordinate
318
if (i == 0) {
319                     posIdx = tmodel.getCellOrdinal()
320                     - ((tmodel.getCellOrdinal() / nXPositions) * nXPositions);
321                 } else {
322                     posIdx = tmodel.getCellOrdinal() / nXPositions;
323                 }
324                 
325                 XMLA_Position position = (XMLA_Position) axes[i].getPositions()
326                 .get(posIdx);
327                 Member[] positionMembers = position.getMembers();
328                 
329                 if (i == 1) {
330                     mdxBuf.append(",");
331                 }
332                 
333                 mdxBuf.append("{(");
334                 
335                 for (int j = 0; j < positionMembers.length; j++) {
336                     XMLA_Member member = (XMLA_Member) positionMembers[j];
337                     
338                     if (j > 0) {
339                         mdxBuf.append(",");
340                     }
341                     
342                     mdxBuf.append(member.getUniqueName());
343                 }
344                 
345                 mdxBuf.append(")}");
346                 
347                 if (i == 0) {
348                     mdxBuf.append(" on Columns");
349                 } else {
350                     mdxBuf.append(" on Rows");
351                 }
352             }
353             
354             mdxBuf.append(" from ["
355                     + ((XMLA_Model) tmodel.getModel()).getCube() + "]");
356             
357             Axis slicer = res.getSlicer();
358             
359             // note at this stage we only deal with position 0
360
List JavaDoc slicerList = slicer.getPositions();
361             XMLA_Position slicerPosition = (XMLA_Position) slicerList.get(0);
362             Member[] slicerMembers = slicerPosition.getMembers();
363             
364             for (int j = 0; j < slicerMembers.length; j++) {
365                 XMLA_Member member = (XMLA_Member) slicerMembers[j];
366                 
367                 if (j == 0) {
368                     mdxBuf.append(" Where ( ");
369                 } else if (j > 0) {
370                     mdxBuf.append(" , ");
371                 }
372                 
373                 mdxBuf.append(member.getUniqueName());
374             }
375             
376             if (slicerMembers.length > 0) {
377                 mdxBuf.append(")");
378             }
379             
380             return mdxBuf.toString();
381         }
382     }
383 }
384
Popular Tags