
import com.tonbeller.jpivot.olap.model.*;


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

import mondrian.olap.Util;
import mondrian.olap.Util.PropertyList;
import mondrian.spi.*;






public class MondrianManager implements OlapManager{
	private com.tonbeller.jpivot.mondrian.MondrianModel Model=null;
	private com.tonbeller.jpivot.olap.model.Result Result=null;
	private static String SPATIAL_DIMENSION="Location";
	private static String TIME_DIMENSION="Time";
	private static String EXTENSION_DRILL_POSITION="drillPosition";
	private static String EXTENSION_DRILL_DIMENSION="drillDimension";
	private static String EXTENSION_SLICE="Slice";

	//COSTRUTTORI
	MondrianManager()
	{
	  String conS="Provider=mondrian;" +
		
		
		"Jdbc=jdbc:postgresql://localhost/pollution?user=postgres&password=postgres;" +
		"Catalog=C:\\eclipse\\GEPOLLUTION.xml";
	 
	  String mdx="select "+
		"{[Measures].[PollutionValue]} on columns, "+
		"{([Location],[Pollutants], [Time])}on rows "+
		"from Pollution";
		Init(conS, mdx);	
	}
	
	MondrianManager(String connectionString, String mdxQuery)
	{
		Init(connectionString, mdxQuery);
	}
	
	private void Init(String connectionString, String mdxQuery)
	{
		this.Model = new com.tonbeller.jpivot.mondrian.MondrianModel();
		this.Model.setConnectString(connectionString);
		this.Model.setMdxQuery(mdxQuery);
	
		try 
		{
					    
			this.Model.initialize();
			//Estensioni per le operazioni
			//Drill Member (drill down (expand) o roll up (collapse)
			com.tonbeller.jpivot.olap.query.DrillExpandMemberExt expandDimension= new com.tonbeller.jpivot.olap.query.DrillExpandMemberExt();
			com.tonbeller.jpivot.olap.query.DrillExpandPositionExt expandPosition= new com.tonbeller.jpivot.olap.query.DrillExpandPositionExt();
			com.tonbeller.jpivot.olap.navi.ChangeSlicer slicer= new com.tonbeller.jpivot.mondrian.MondrianChangeSlicer();
			expandDimension.setId(MondrianManager.EXTENSION_DRILL_DIMENSION);
			expandPosition.setId(MondrianManager.EXTENSION_DRILL_POSITION);
			
			//System.out.println(expand.getId());
		    this.Model.addExtension(expandDimension);
		    this.Model.addExtension(expandPosition);
		    this.Model.addExtension(slicer);
		    this.Result = this.Model.getResult();	
		    System.out.println("model in init:"+ this.Model.toString());
		    System.out.println("Result in inti:"+this.Result.toString());
		}
		catch (OlapException e)
		{
		 System.out.println(e.getMessage());
		 
		}
	}
	
	// OPERAZIONI
	
	public void DrillDownDimension(String member)
	{
		this.Expand(this.findMember(member));
	}
	
	public void RollUpDimension(String member)
	{
		this.Collapse(this.findMember(member));
	}
	
	public void DrillDownMember(String name, String position)
	{
		this.ExpandMember(this.findMember(name),this.findPosition(name,position));
		
	}
	
	public void RollUpMember(String name, String position)
	{
		this.CollapseMember(this.findMember(name),this.findPosition(name,position));
		
	}
	private void CollapseMember(Member member, Position position) {
		 com.tonbeller.jpivot.olap.query.DrillExpandPositionExt collapse= (com.tonbeller.jpivot.olap.query.DrillExpandPositionExt)this.Model.getExtension(MondrianManager.EXTENSION_DRILL_POSITION);
			
		  collapse.collapse(position, member);
		  try{
		  this.Result= this.Model.getResult();
		  }
		  catch(Exception e)
		  {
			  System.out.println(e.getMessage());
		  }
		
	}

	private void Expand(com.tonbeller.jpivot.olap.model.Member member)
	{
	  com.tonbeller.jpivot.olap.query.DrillExpandMemberExt expand= (com.tonbeller.jpivot.olap.query.DrillExpandMemberExt)this.Model.getExtension(MondrianManager.EXTENSION_DRILL_DIMENSION);
	
	  expand.expand(member);
	  try{
	  this.Result= this.Model.getResult();
	  }
	  catch(Exception e)
	  {
		  System.out.println(e.getMessage());
	  }
		
	}
	
	private void ExpandMember(com.tonbeller.jpivot.olap.model.Member member,com.tonbeller.jpivot.olap.model.Position position)
	{
	  com.tonbeller.jpivot.olap.query.DrillExpandPositionExt expand= (com.tonbeller.jpivot.olap.query.DrillExpandPositionExt)this.Model.getExtension(MondrianManager.EXTENSION_DRILL_POSITION);
	
	  expand.expand(position,member);
	  try{
	  this.Result= this.Model.getResult();
	  }
	  catch(Exception e)
	  {
		  System.out.println(e.getMessage());
	  }
		
	}
	
	private void Collapse(com.tonbeller.jpivot.olap.model.Member member)
	{
	  com.tonbeller.jpivot.olap.query.DrillExpandMemberExt expand= (com.tonbeller.jpivot.olap.query.DrillExpandMemberExt)this.Model.getExtension(MondrianManager.EXTENSION_DRILL_DIMENSION);
	
	  expand.collapse(member);
	  try{
	  this.Result= this.Model.getResult();
	  }
	  catch(Exception e)
	  {
		  System.out.println(e.getMessage());
	  }
		
	}
	
	private com.tonbeller.jpivot.olap.model.Member findMember(String name)
	{
		Axis[] axes= Result.getAxes();
		for (int i=0; i<axes.length; i++)
		{
			//List positions= axes[i].getPositions();
		     ArrayList posList = (ArrayList)axes[i].getPositions();
			
		     for (Iterator posIter = posList.iterator();posIter.hasNext();) 
             {
		    	 com.tonbeller.jpivot.olap.model.Position currentPos =(com.tonbeller.jpivot.olap.model.Position) posIter.next();
		    	 // iterate through all members of the current position
                 for (int j=0;j<currentPos.getMembers().length;j++)
                 {
                  if (currentPos.getMembers()[j].getLabel().trim().contentEquals(name))
                	  {
                	  //System.out.println(currentPos.toString()+"-"+j); 
                	  return currentPos.getMembers()[j];
                	  
                	  }
                 }
             }
                     
            
		}
		return null;
	}
	
	private com.tonbeller.jpivot.olap.model.Position findPosition(String name, String position)
	{
		Axis[] axes= Result.getAxes();
		//axes[0] rappresenta le misure
		//axes[1] rappresenta le altre dimensioni (pollutants, locations, time)
		     ArrayList posList = (ArrayList)axes[1].getPositions();
		
		     com.tonbeller.jpivot.olap.model.Position currentPos =(com.tonbeller.jpivot.olap.model.Position) posList.get(Integer.parseInt(position));
	
                for (int j=0;j<currentPos.getMembers().length;j++)
                {
                 if (currentPos.getMembers()[j].getLabel().trim().contentEquals(name))
               	  {
               	 
               	  return currentPos;
               	  
               	  }
                }
    
		return null;
	}
	
	//Naviga il cubo e restituisce l'xml
	public String getXmlCube()
	{
		Axis[] axes= Result.getAxes();
		List cells = Result.getCells();
		
		//axes[0] rappresenta le misure
		//axes[1] rappresenta le altre dimensioni (pollutants, locations, time)
		ArrayList posList = (ArrayList)axes[1].getPositions();
		int riga=0;
		String cubeXml="<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+
						//"<!DOCTYPE cube SYSTEM \"protocolloComunicazione.dtd\">"+
						"<CUBE>";
		
		for (Iterator posIter = posList.iterator();posIter.hasNext();) 
             {
		    	 //riga
		    	 com.tonbeller.jpivot.olap.model.Position currentPos =(com.tonbeller.jpivot.olap.model.Position) posIter.next();
		    	 // iterate through all members of the current position
		    	 String rigaXml="<ROW id=\""+riga+"\">\n";
		    	 String SpatialDim="<SPATIALDIMENSION ";
		    	 String TimeDimension="<TIMEDIMENSION ";
		    	 com.tonbeller.jpivot.mondrian.MondrianCell misura= (com.tonbeller.jpivot.mondrian.MondrianCell) cells.get(riga);
		    	 String Misures=new String();
		    	 if (misura.isNull())
		    	 {
		    		 Misures ="<MISURES>\n   <MISURE hierarchy=\"Pollution Value\" Value=\"0\">";
		    	 }
		    	 else
		    	 {
		    	 Misures ="<MISURES>\n   <MISURE hierarchy=\"Pollution Value\" Value=\""+misura.getValue() +"\">";
		    	 }
                 
                 for (int j=0;j<currentPos.getMembers().length;j++)
                 {
                	//itero per colonne 
                	 
                	 Member currentMember= currentPos.getMembers()[j];
                	 
                	 Level currentLevel= currentMember.getLevel();
                	 Dimension currentDimension= currentMember.getLevel().getHierarchy().getDimension();
                	 com.tonbeller.jpivot.olap.query.DrillExpandPositionExt expand= (com.tonbeller.jpivot.olap.query.DrillExpandPositionExt)this.Model.getExtension(MondrianManager.EXTENSION_DRILL_POSITION);
                	 com.tonbeller.jpivot.mondrian.MondrianMemberTree membTree= new com.tonbeller.jpivot.mondrian.MondrianMemberTree();
                	  
                	 String dim= " hierarchy=\"" + currentDimension.getLabel().trim() +"\" ";
                //	 Member[] children = membTree.getChildren(currentMember);
                	 //System.out.print(currentMember.getLabel());
                	// System.out.println("-"+membTree.hasChildren(currentMember));
                	 if (expand.canExpand(currentPos,currentMember))
                	 {
                		
                		if(membTree.hasChildren(currentMember))
                		 
                	//	 if(children.length==0)
                		 {
                		 dim+=" operation=\"DRILLDOWN\"";
                		 
                		 }
                		 else
                		 {
                			 dim+=" operation=\"\"";
                		 }
                		 
                	 }
                	 else if (expand.canCollapse(currentPos,currentMember))
                    	 {
                    		 dim+=" operation=\"ROLLUP\"";
                    	 }
                	 	else
                	 	{
                	 		 dim+=" operation=\"\"";
                	 	}
                	
                	 dim+= " level =\"" + currentLevel.getLabel().trim()+"\">"+
                	 		  currentMember.getLabel().trim();
                	 
                	 if (currentDimension.getLabel().compareToIgnoreCase(MondrianManager.SPATIAL_DIMENSION)==0)
                	 {
                		 SpatialDim+=dim+"</SPATIALDIMENSION>\n";
                  	 }
                	
                	 else if (currentDimension.getLabel().compareToIgnoreCase(MondrianManager.TIME_DIMENSION)==0)
                	 {
                		 TimeDimension+=dim +"</TIMEDIMENSION>\n";
                  	 }
                	 else
                	 {
                		 Misures+="\n<DIMENSION "+dim +"</DIMENSION>";
                	 }
                             
                 }
                 rigaXml+=SpatialDim+TimeDimension+Misures+"</MISURE>\n</MISURES>\n</ROW>\n";
                 cubeXml+=rigaXml;
                 riga++;
             }
				cubeXml+="</CUBE>";
        		
				return cubeXml;
        		
	}

	public String findDimensionOfMember(String member) {
		com.tonbeller.jpivot.olap.model.Member olapMember= this.findMember(member);
		
		return olapMember.getLevel().getHierarchy().getLabel();
	}

}
