/**
*
* LICENSE: see LICENSE.txt file
*
*/
package it.eng.spagobi.jpivotaddins.crossnavigation;
import java.util.ArrayList;
import java.util.List;
import mondrian.olap.Cell;
import mondrian.olap.Connection;
import mondrian.olap.Cube;
import mondrian.olap.Dimension;
import mondrian.olap.Hierarchy;
import mondrian.olap.Level;
import mondrian.olap.Member;
import mondrian.olap.Query;
import mondrian.rolap.RolapCubeMember;
import mondrian.rolap.RolapMember;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.log4j.Logger;
import org.dom4j.Node;
import com.tonbeller.jpivot.mondrian.MondrianModel;
/**
* An instance of this class contains information for cross navigation choices, retrieved by SpagoBI OLAP document template.
* An example of this configuration could be:<br/>
* <CROSS_NAVIGATION><br/>
* <TARGET documentLabel="QBE_FOODMART" customizedView="Unit sales on product family"><br/>
* <TITLE><br/>
* <![CDATA[<br/>
* Go to QbE over Foodmart DB<br/>
* ]]><br/>
* </TITLE><br/>
* <DESCRIPTION><br/>
* <![CDATA[<br/>
* Detail on unit sales per selected product family<br/>
* ]]><br/>
* </DESCRIPTION><br/>
* <PARAMETERS><br/>
* <PARAMETER name="family" scope="relative" dimension="Product" hierarchy="[Product]" level="[Product].[Product Family]" /><br/>
* <PARAMETER name="city" scope="relative" dimension="Region" hierarchy="[Region]" level="[Region].[Sales City]" property="code" /><br/>
* </PARAMETERS><br/>
* </TARGET><br/>
* </CROSS_NAVIGATION><br/>
*
* @author Zerbetto Davide (davide.zerbetto@eng.it)
*
* DATE CONTRIBUTOR/DEVELOPER NOTE
* 17-12-2009 Zerbetto Davide/Gilles CAFIERO (G2C) parameter value can be retrieved by a member property
*
*/
public class SpagoBICrossNavigationConfig {
private static transient Logger logger = Logger.getLogger(SpagoBICrossNavigationConfig.class);
private List<Target> targets = null;
public static final String ID = "cross_navigation_config";
/**
* Constructor given the CROSS_NAVIGATION node of the xml document template.
* @param config: the CROSS_NAVIGATION node of the xml document template
*/
public SpagoBICrossNavigationConfig(Node config) {
logger.debug("Configuration:\n" + config.asXML());
init(config);
}
private void init(Node node){
targets = new ArrayList<Target>();
List targetNodes = node.selectNodes("TARGET");
if (targetNodes != null && !targetNodes.isEmpty()) {
for (int i = 0; i < targetNodes.size(); i++) {
Target target = new Target((Node) targetNodes.get(i));
if (target != null) {
targets.add(target);
}
}
}
}
public int getChoicesNumber() {
logger.debug("IN");
int toReturn = targets.size();
logger.debug("OUT: returning [" + toReturn + "]");
return toReturn;
}
public String[] getChoice(int rowIndex, Cell cell, MondrianModel model) {
logger.debug("IN");
String[] toReturn = new String[2];
Target target = targets.get(rowIndex);
String url = getCrossNavigationUrl(target, cell, model);
toReturn[0] = target.title;
toReturn[1] = url;
logger.debug("OUT: returning [" + toReturn + "]");
return toReturn;
}
private String getCrossNavigationUrl(Target target, Cell cell, MondrianModel model) {
logger.debug("IN");
StringBuffer buffer = new StringBuffer("parent.execCrossNavigation(window.name, '"
+ StringEscapeUtils.escapeJavaScript(target.documentLabel) + "', '");
String query = model.getCurrentMdx();
Connection monConnection = model.getConnection();
Query monQuery = monConnection.parseQuery(query);
Cube cube = monQuery.getCube();
List<TargetParameter> parameters = target.parameters;
if (!parameters.isEmpty()) {
for (int i = 0; i < parameters.size(); i++) {
TargetParameter aParameter = parameters.get(i);
String parameterName = aParameter.name;
String parameterValue = getParameterValue(aParameter, cube, cell);
if (parameterValue != null) {
buffer.append(StringEscapeUtils.escapeJavaScript(parameterName + "=" + parameterValue + "&"));
}
}
}
if (buffer.charAt(buffer.length() - 1) == '&') {
buffer.deleteCharAt(buffer.length() - 1);
}
if (target.customizedView != null) {
buffer.append("', '" + StringEscapeUtils.escapeJavaScript(target.customizedView) + "'");
} else {
buffer.append("', ''");
}
if(target.titleCross!=null && target.targetCross!=null && target.targetCross.equalsIgnoreCase("tab")){
buffer.append(",'"+target.titleCross+"','tab'");
}else if(target.titleCross!=null){
buffer.append(",'"+target.titleCross+"'");
}
buffer.append(");");
String toReturn = buffer.toString();
logger.debug("OUT: returning [" + toReturn + "]");
return toReturn;
}
private String getParameterValue(TargetParameter parameter, Cube cube, Cell cell) {
if (parameter.isAbsolute) {
return parameter.value;
}
String value = null;
String dimensionName = parameter.dimension;
String hierarchyName = parameter.hierarchy;
String levelName = parameter.level;
String propertyName = parameter.property;
logger.debug("Looking for dimension " + dimensionName + ", hierarchy " + hierarchyName + ", level " + levelName + ", property " + propertyName + " ...");
Dimension dimension = getDimension(cube, dimensionName);
if (dimension == null) {
logger.error("Dimension " + dimensionName + " not found in cube " + cube.getName() + "Returning null");
return null;
}
logger.debug("Dimension " + dimensionName + " found.");
Member member = cell.getContextMember(dimension);
logger.debug("Considering context member " + member.getUniqueName());
Hierarchy hierarchy = member.getHierarchy();
logger.debug("Member hierarchy is " + hierarchy.getUniqueName());
if (hierarchy.getUniqueName().equals(hierarchyName)) {
if (propertyName == null || propertyName.trim().equals("")) {
value = getLevelValue(member, levelName);
} else {
value = getMemberPropertyValue(member, propertyName);
}
}
return value;
}
private Dimension getDimension(Cube cube, String dimensionName) {
Dimension toReturn = null;
Dimension[] dimensions = cube.getDimensions();
for (int i = 0; i < dimensions.length; i++) {
Dimension aDimension = dimensions[i];
if (aDimension.getName().equals(dimensionName)) {
toReturn = aDimension;
break;
}
}
return toReturn;
}
private String getLevelValue(Member member, String levelName) {
logger.debug("IN: Member is " + member.getUniqueName() + ", levelName is " + levelName);
String toReturn = null;
Level level = member.getLevel();
logger.debug("Member level is " + level.getUniqueName());
if (level.getUniqueName().equals(levelName)) {
logger.debug("Member level matches input level name " + levelName + "!!");
String uniqueName = member.getUniqueName();
// The uniqueName is the name of the member retrieved by the column defined in "nameColumn" property of the level in the xml schema.
// If the key value is required (retrieved by the column defined in "column" property), use the following code
// TODO: test it!!!
//RolapCubeMember rcm = (RolapCubeMember) member;
//System.out.println(rcm.getKey());
toReturn = uniqueName.substring(uniqueName.lastIndexOf("].[") + 3, uniqueName.lastIndexOf("]"));
} else {
logger.debug("Member level does NOT match input level name " + levelName + "!!");
// look for parent member at parent level
Member parent = member.getParentMember();
if (parent == null) {
return null;
} else {
return getLevelValue(parent, levelName);
}
}
logger.debug("OUT: returning " + toReturn);
return toReturn;
}
private String getMemberPropertyValue(Member member, String propertyName) {
logger.debug("IN: Member is " + member.getUniqueName() + ", propertyName is " + propertyName);
String toReturn = null;
Object propertyNameValue = member.getPropertyValue(propertyName, false);
if (propertyNameValue != null) {
toReturn = propertyNameValue.toString();
}
logger.debug("OUT: returning " + toReturn);
return toReturn;
}
protected class Target {
String documentLabel;
String customizedView;
String title;
String description;
String targetCross;
String titleCross;
List<TargetParameter> parameters;
Target(Node node) {
documentLabel = node.valueOf("@documentLabel");
customizedView = node.valueOf("@customizedView");
targetCross = node.valueOf("@target");
titleCross = node.valueOf("@title");
if (customizedView != null && customizedView.trim().equals("")) {
customizedView = null;
}
title = node.selectSingleNode("TITLE").getText();
description = node.selectSingleNode("DESCRIPTION").getText();
List parametersNodes = node.selectNodes("PARAMETERS/PARAMETER");
boolean hasParameters = parametersNodes != null && !parametersNodes.isEmpty();
parameters = new ArrayList<TargetParameter>();
if (hasParameters) {
for (int i = 0; i < parametersNodes.size(); i++) {
TargetParameter aParameter = new TargetParameter((Node) parametersNodes.get(i));
if (aParameter != null) {
parameters.add(aParameter);
}
}
}
}
}
protected class TargetParameter {
String name;
boolean isAbsolute;
String value;
String dimension;
String hierarchy;
String level;
String property;
TargetParameter(Node node) {
name = node.valueOf("@name");
isAbsolute = node.valueOf("@scope").trim().equalsIgnoreCase("absolute");
if (isAbsolute) {
value = node.valueOf("@value");
} else {
dimension = node.valueOf("@dimension");
hierarchy = node.valueOf("@hierarchy");
level = node.valueOf("@level");
}
property = node.valueOf("@property");
}
}
}