/**
 * Oracle Corporation (c) 2003
 * Sample Application for creating a standard Form AW using 
 * the oracle.AWXML API for Oracle 10g
 * 
 * 
 * To compile
 * set OH=c:\oracle10g
 * set CLASSPATH=.;%OH%\olap\olapi\lib\olap_api.jar;%OH%\olap\jlib\AWXML.jar;%OH%\jdbc\lib\classes12.jar;%OH%\lib\xmlparserv2.jar;%OH%\lib\xmlcomp.jar
 * javac AWXMLSample.java
 * java AWXMLSample
 */
 
import java.util.*;
import oracle.AWXML.*;
import oracle.AWAction.*;

/**
 * Sample program creates dimension, cube, aggregation definition, 
 * allocation definition and aggregation solve
 * Creates the AW
 * Build the AW
 * Reads the AW back
 * 
 */
 
public class AWXMLSample {

  public static void main(String[] args) {
    String conn1 = "sbdesai-sun.us.oracle.com:1521:main";
    String conn2 = "dmellor-sun.us.oracle.com:1565:wxmldev";
    String conn3 = "bursun2.us.oracle.com:1521:main";
    String user = "xademo";
    String pwd = "xademo";
    String conn = conn1;
    String awName = "xademo99";
    
    try {
      System.out.println("Connectng to " + conn);

      AWConnection awConnection =
         new AWConnection(user, pwd, conn );     
      
      try {
         System.out.println("Deleting " + awName + " on " + new Date().toString());
         awConnection.executeCommand("aw delete " + awName);         
         System.out.println("Deleted " + awName + " on " + new Date().toString());
      } 
      catch (Exception e) {
        System.out.println(e); 
      }
      
      AW xademoAW = new AW();
      xademoAW.setName(awName);

      // Dimension Names are unique across schema
      Dimension channelDimension = xademoAW.createDimension();
      channelDimension.setSchema("XADEMO");
      channelDimension.setName("CHANNEL");
      // no duplicate members
      //channelDimension.setUseNativeKey(boolean)
      //channelDimension.setIsNativeKeyUnique(boolean) 
      //channelDimension.setIsMeasure(booelan); What ? 
            
      //PerminantCalculatedMember pc = 
      //    channelDimension.createPerminantCalculatedMember(); 
      //pc.setName("MIAMANDBOSTON");
      //How to build expression?
      // AWXMLAPI Expression Language need documentation
      //pc.setExpressionText("'MIAMI' + 'BOSTON'");
      //pc.setStorageType(String) ?

      // inherited from AWObject which is extended by Cube, Dimension, Hierarchy, HierarchyLevelAssociation, MemberSelection 
      // Set Table mappings to be use while doing an AW refresh 
      //.addRefreshMapGroup(MappingGroup input);
      
      //.addSourceMappingGroup(MappingGroup input); What ?

      // BaseObject
      //.Alter() call if short name, long name or plural Name changed
      //.Copy(AWConnection connection) What ? seems to do nothing

      String[] channelAttrNames = new String[] { 
           "SHORTLABEL", "TEXT", null, 
           "LONGLABEL", "TEXT", null }; 
      // level Name, Column Name, parent Column Name, 1st attribute column name, 2nd atribute column Name ...
      String[] channelLevelMap = new String[] { 
         "STANDARD_1", "XADEMO.XADEMO_CHANNEL.CHAN_STD_TOP",     null,                                   
           "XADEMO.XADEMO_CHANNEL.CHAN_STD_TOP_SLABEL", 
           "XADEMO.XADEMO_CHANNEL.CHAN_STD_TOP_LLABEL",
         "STANDARD_2", "XADEMO.XADEMO_CHANNEL.CHAN_STD_CHANNEL", "XADEMO.XADEMO_CHANNEL.CHAN_STD_TOP", 
           "XADEMO.XADEMO_CHANNEL.CHAN_STD_CHANNEL_SLABEL", 
           "XADEMO.XADEMO_CHANNEL.CHAN_STD_CHANNEL_LLABEL"
      };     
      Hierarchy channelHierarchy = 
        createHierarchy( channelDimension, "STANDARD", 
                         channelLevelMap, channelAttrNames);
      //channelHierarchy.setIsDefault(true);
      
      Dimension timeDimension = xademoAW.createDimension();
      timeDimension.setSchema("XADEMO");
      timeDimension.setName("TIME");
      timeDimension.setLongName("TIME");
      timeDimension.setIsTime(true);
      String[] timeAttrNames = new String[] { 
         "SHORTLABEL", "TEXT", null, 
         "LONGLABEL", "TEXT", null, 
         "END_DATE", "DATE", "END_DATE", 
         "TIME_SPAN", "TEXT", "TIME_SPAN" };
      String[] timeLevelMap = new String[] { 
        "L1", "XADEMO.XADEMO_TIME.TIME_STD_YEAR", null, 
          "XADEMO.XADEMO_TIME.TIME_STD_YEAR_SLABEL", 
          "XADEMO.XADEMO_TIME.TIME_STD_YEAR_LLABEL", 
          "XADEMO.XADEMO_TIME.TIME_STD_YEAR_END_DATE", 
          "XADEMO.XADEMO_TIME.TIME_STD_YEAR_TIMESPAN",
        "L2", "XADEMO.XADEMO_TIME.TIME_STD_QUARTER", "XADEMO.XADEMO_TIME.TIME_STD_YEAR",
          "XADEMO.XADEMO_TIME.TIME_STD_QUARTER_SLABEL", 
          "XADEMO.XADEMO_TIME.TIME_STD_QUARTER_LLABEL", 
          "XADEMO.XADEMO_TIME.TIME_STD_QUARTER_END_DATE", 
          "XADEMO.XADEMO_TIME.TIME_STD_QUARTER_TIMESPAN",
        "L3", "XADEMO.XADEMO_TIME.TIME_STD_MONTH", "XADEMO.XADEMO_TIME.TIME_STD_QUARTER", 
          "XADEMO.XADEMO_TIME.TIME_STD_MONTH_SLABEL", 
          "XADEMO.XADEMO_TIME.TIME_STD_MONTH_LLABEL", 
          "XADEMO.XADEMO_TIME.TIME_STD_MONTH_END_DATE", 
          "XADEMO.XADEMO_TIME.TIME_STD_MONTH_TIMESPAN",
      };
      Hierarchy timeHierarchy = 
        createHierarchy(timeDimension, "STANDARD", 
                        timeLevelMap, timeAttrNames);     

      Dimension productDimension = xademoAW.createDimension();
      productDimension.setSchema("XADEMO");
      productDimension.setName("PRODUCT");
      String[] productAttrNames = new String[] { 
         "SHORTLABEL", "TEXT", null, 
         "LONGLABEL", "TEXT", null }; 
      // level Name, Column Name, parent Column Name, 1st attribute column name, 2nd atribute column Name ...
      String[] productLevelMap = new String[] { 
         "L1", "XADEMO.XADEMO_PRODUCT.PROD_STD_TOP",     null,                                   
           "XADEMO.XADEMO_PRODUCT.PROD_STD_TOP_SLABEL", 
           "XADEMO.XADEMO_PRODUCT.PROD_STD_TOP_LLABEL",
         "L2", "XADEMO.XADEMO_PRODUCT.PROD_STD_DIVISION", "XADEMO.XADEMO_PRODUCT.PROD_STD_TOP", 
           "XADEMO.XADEMO_PRODUCT.PROD_STD_DIVISION_SLABEL", 
           "XADEMO.XADEMO_PRODUCT.PROD_STD_DIVISION_LLABEL",
         "L3", "XADEMO.XADEMO_PRODUCT.PROD_STD_GROUP", "XADEMO.XADEMO_PRODUCT.PROD_STD_DIVISION", 
           "XADEMO.XADEMO_PRODUCT.PROD_STD_GROUP_SLABEL", 
           "XADEMO.XADEMO_PRODUCT.PROD_STD_GROUP_LLABEL",  
         "L4", "XADEMO.XADEMO_PRODUCT.PROD_STD_PRODUCT", "XADEMO.XADEMO_PRODUCT.PROD_STD_GROUP", 
           "XADEMO.XADEMO_PRODUCT.PROD_STD_PRODUCT_SLABEL", 
           "XADEMO.XADEMO_PRODUCT.PROD_STD_PRODUCT_LLABEL"  
      };     
      Hierarchy productHierarchy = 
        createHierarchy(productDimension, "STANDARD", 
                        productLevelMap, productAttrNames);

      Dimension geographyDimension = xademoAW.createDimension();
      geographyDimension.setSchema("XADEMO");
      geographyDimension.setName("GEOGRAPHY");
      String[] geographyAttrNames = new String[] { "SHORTLABEL", "TEXT", null, "LONGLABEL", "TEXT", null }; 
      // level Name, Column Name, parent Column Name, 1st attribute column name, 2nd atribute column Name ...
      String[] geographyLevelMap = new String[] { 
         "L1", "XADEMO.XADEMO_GEOGRAPHY.GEOG_STD_TOP",     null,                                   
           "XADEMO.XADEMO_GEOGRAPHY.GEOG_STD_TOP_SLABEL", 
           "XADEMO.XADEMO_GEOGRAPHY.GEOG_STD_TOP_LLABEL",
         "L2", "XADEMO.XADEMO_GEOGRAPHY.GEOG_STD_CONTINENT", "XADEMO.XADEMO_GEOGRAPHY.GEOG_STD_TOP", 
           "XADEMO.XADEMO_GEOGRAPHY.GEOG_STD_CONTINENT_SLABEL", 
           "XADEMO.XADEMO_GEOGRAPHY.GEOG_STD_CONTINENT_LLABEL",
         "L3", "XADEMO.XADEMO_GEOGRAPHY.GEOG_STD_AREA", "XADEMO.XADEMO_GEOGRAPHY.GEOG_STD_CONTINENT", 
           "XADEMO.XADEMO_GEOGRAPHY.GEOG_STD_AREA_SLABEL", 
           "XADEMO.XADEMO_GEOGRAPHY.GEOG_STD_AREA_LLABEL",  
         "L4", "XADEMO.XADEMO_GEOGRAPHY.GEOG_STD_CITY", "XADEMO.XADEMO_GEOGRAPHY.GEOG_STD_AREA", 
           "XADEMO.XADEMO_GEOGRAPHY.GEOG_STD_CITY_SLABEL", 
           "XADEMO.XADEMO_GEOGRAPHY.GEOG_STD_CITY_LLABEL"  
      };     
      Hierarchy geographyHierarchy = 
        createHierarchy(geographyDimension, "STANDARD", 
                        geographyLevelMap, geographyAttrNames);

      Dimension channelShortLabelDimension = xademoAW.createDimension();
      channelShortLabelDimension.setSchema("XADEMO");
      channelShortLabelDimension.setName("CHANNELSHORTLABEL");                   

      // Attribute acts as a dimension
      //Attribute channelDimShortLabelAttr = channelDimension.findAttribute("SHORTLABEL");
      //Not working
      //channelDimShortLabelAttr.setDimensionDomain(channelShortLabelDimension);

      Cube analyticCube = createCube(xademoAW,
        channelDimension, geographyDimension, productDimension,timeDimension);

      Measure salesMeasure = analyticCube.findMeasure("SALES");  
      Measure costsMeasure = analyticCube.findMeasure("COSTS");  

      if (salesMeasure != null && costsMeasure != null)
         createDerivedMeasure(analyticCube, salesMeasure, costsMeasure);

      // How are OlapMeasure and DerivedMeasure different?
      createOlapMeasure(analyticCube, salesMeasure, timeDimension);
      
      AggregationDefinition salesAggSolveDefn = 
         createAggregationDefinition(xademoAW, channelDimension);
      createAllocationDefinition(xademoAW, costsMeasure, salesMeasure, channelHierarchy);   
      createForecastDefinition(xademoAW, costsMeasure, salesMeasure, timeDimension);      
      createAggregationSolve(xademoAW, salesMeasure, salesAggSolveDefn);
      createCubeMapping(analyticCube, salesMeasure, channelDimension, 
         geographyDimension, productDimension, timeDimension);
      createModel(xademoAW, channelDimension);

      xademoAW.Create(awConnection);
      xademoAW.Commit(awConnection);
      System.out.println("Created logical " + awName + " on " + new Date().toString());
      //System.out.println("XML for AW = " + xademoAW.WriteToXML());      

      // How does refresh work?
      Interaction ia = new Interaction();
      ia.setConnection(awConnection);
      BuildDatabase bdb = new BuildDatabase(ia);
      bdb.setAWName(awName);
      bdb.Execute();          
      System.out.println("Built " + awName + " on " + new Date().toString());

      //updateAW(awName, xademoAW, awConnection);
      //updateAW2(awName, xademoAW, awConnection);
    }
    catch (Exception e) {
      System.out.println("Exception = " + e);
      e.printStackTrace();
    }
  }

  private static Cube createCube(
      AW xademoAW,
      Dimension channelDimension, 
      Dimension geographyDimension,
      Dimension productDimension,
      Dimension timeDimension)
  {
    // cube Names are unique across schema
    Cube analyticCube = xademoAW.createCube();
    analyticCube.setSchema("XADEMO");
    analyticCube.setName("ANALYTIC_CUBE");    
    // requires compatible in init.ora to be 10.0 to work
    // Do the partition apply to all the measures ?
    // Difference between level partition and hierarchy partition
    //analyticCube.setPartitionLevel(timeDimension.FindLevel("L2"));
    //analyticCube.setPartitionHierarchy(timeHierarchy);
    // set to ULTRA or STANDARD
    //analyticCube.setSparseType() what ? compressed cube
    //if true all partitions share composite, else separate composites per partition
    //analyticCube.setUseGlobalIndex()
    analyticCube.createCubeDimRef().setDimension(channelDimension);     
    analyticCube.createCubeDimRef().setDimension(productDimension);
    analyticCube.createCubeDimRef().setDimension(geographyDimension);
    analyticCube.createCubeDimRef().setDimension(timeDimension);
    Measure salesMeasure = analyticCube.createMeasure();
    salesMeasure.setName("SALES");
    Measure costsMeasure = analyticCube.createMeasure();
    costsMeasure.setName("COSTS");
    // Partitioning Generates Exception (requires compatible in init.ora to be 10.0)
    //salesMeasure.setPartitionLevel(timeDimension.FindLevel("L2"));
    //salesMeasure.setPartitionHierarchy(timeHierarchy);
      
    //salesMeasure.setDataType(String); Possible values
    //salesMeasure.setForceCalc(boolean); 
    //salesMeasure.setForceOrder(boolean); RECALC or ALWAYS
    //salesMeasure.setAutoSolve(String); ?
    //salesMeasure.setIsInternal(boolean); What ?
    
    
    //salesMeasure.setSolveDefinition(SolveDefinition); Aggregations only
    // Difference between cube.setDefaultAggregation() and measure.setSolveDefinition() ?
    //salesMeasure.setSparseType(String); // create compressed measure override cube settings
    //salesMeasure.setUseGlobalIndex(Boolean); What ?
   
    // Specify sparse dimensions
    CubeDimRef cdr1 = salesMeasure.createCubeDimRef();
    cdr1.setDimension(channelDimension);     
    cdr1.setSparse(Boolean.TRUE);     
    CubeDimRef cdr2 = salesMeasure.createCubeDimRef();
    cdr2.setDimension(productDimension);     
    cdr2.setSparse(Boolean.TRUE);     
    CubeDimRef cdr3 = salesMeasure.createCubeDimRef();
    cdr3.setDimension(geographyDimension);     
    cdr3.setSparse(Boolean.TRUE);           

    AggregationDefinition dad = analyticCube.getDefaultAggregationDefinition();
    if (dad != null)
    {
      dad.setName("DefaultAggDefn");
      dad.setLongName("DefaultAggDefn for ANALYTIC_CUBE");
    }

    return analyticCube;
  }

  private static Cube createCube2(
      AW xademoAW,
      Dimension channelDimension, 
      Dimension geographyDimension,
      Dimension productDimension,
      Dimension timeDimension)
  {
    // cube Names are unique across schema
    Cube analyticCube = xademoAW.createCube();
    analyticCube.setSchema("XADEMO");
    analyticCube.setName("TEST_CUBE");    
    // requires compatible in init.ora to be 10.0 to work
    // Do the partition apply to all the measures ?
    // Difference between level partition and hierarchy partition
    //analyticCube.setPartitionLevel(timeDimension.FindLevel("L2"));
    //analyticCube.setPartitionHierarchy(timeHierarchy);
    // set to ULTRA or STANDARD
    //analyticCube.setSparseType() what ? compressed cube
    //if true all partitions share composite, else separate composites per partition
    //analyticCube.setUseGlobalIndex()
    CubeDimRef cdr1 = analyticCube.createCubeDimRef();
    cdr1.setDimension(channelDimension);     
    cdr1.setSparse(Boolean.TRUE);
    CubeDimRef cdr2 = analyticCube.createCubeDimRef();
    cdr2.setDimension(productDimension);
    cdr2.setSparse(Boolean.TRUE);
    CubeDimRef cdr3 = analyticCube.createCubeDimRef();
    cdr3.setDimension(geographyDimension);
    cdr3.setSparse(Boolean.TRUE);
    analyticCube.createCubeDimRef().setDimension(timeDimension);
    Measure salesMeasure = analyticCube.createMeasure();
    salesMeasure.setName("SALES");
    // Partitioning Generates Exception (requires compatible in init.ora to be 10.0)
    //salesMeasure.setPartitionLevel(timeDimension.FindLevel("L2"));
    //salesMeasure.setPartitionHierarchy(timeHierarchy);
      
    //salesMeasure.setDataType(String); Possible values
    //salesMeasure.setForceCalc(boolean); 
    //salesMeasure.setForceOrder(boolean); RECALC or ALWAYS
    //salesMeasure.setIsInternal(boolean); What ?
    
    //salesMeasure.setSolveDefinition(SolveDefinition); Aggregations only
    //salesMeasure.setSparseType(String); // create compressed measure override cube settings
    //salesMeasure.setUseGlobalIndex(Boolean); What ?
   
    // Specify sparse dimensions used for composites
    CubeDimRef mcdr1 = salesMeasure.createCubeDimRef();
    mcdr1.setDimension(channelDimension);     
    mcdr1.setSparse(Boolean.TRUE);     
    CubeDimRef mcdr2 = salesMeasure.createCubeDimRef();
    mcdr2.setDimension(productDimension);     
    mcdr2.setSparse(Boolean.TRUE);     
    CubeDimRef mcdr3 = salesMeasure.createCubeDimRef();
    mcdr3.setDimension(geographyDimension);     
    mcdr3.setSparse(Boolean.TRUE);     
    Measure costsMeasure = analyticCube.createMeasure();
    costsMeasure.setName("COSTS");

    AggregationDefinition dad = analyticCube.getDefaultAggregationDefinition();
    if (dad != null)
    {
      dad.setName("DefaultAggDefn");
      dad.setLongName("DefaultAggDefn for ANALYTIC_CUBE");
    }

    return analyticCube;
  }

  private static void createCubeMapping(
      Cube analyticCube,
      Measure salesMeasure, 
      Dimension channelDimension, 
      Dimension geographyDimension,
      Dimension productDimension,
      Dimension timeDimension)
  {
    // Cube Mapping  
    CubeMapGroup cmg1 = analyticCube.createSourceCubeMapGroup();
    MeasureSourceExpression mse1 = cmg1.CreateAttributeMap();
    SourceColumn sc2 = mse1.CreateSourceColumn();
    sc2.setColumn("XADEMO.XADEMO_ANALYTIC_FACTS.SALES");
    mse1.setTargetObject(salesMeasure);
    // required else AW read fails
    CubeDimensionSourceExpression cds1 = cmg1.CreateKeyMap();
    cds1.CreateSourceColumn().setColumn("XADEMO.XADEMO_ANALYTIC_FACTS.CHAN_LEAVES");
    cds1.setTargetObject(channelDimension);
    cds1.setLevel(channelDimension.FindLevel("STANDARD_1"));
    CubeDimensionSourceExpression cds2 = cmg1.CreateKeyMap();
    cds2.CreateSourceColumn().setColumn("XADEMO.XADEMO_ANALYTIC_FACTS.PROD_LEAVES");
    cds2.setTargetObject(productDimension);
    cds2.setLevel(productDimension.FindLevel("L4"));
    CubeDimensionSourceExpression cds3 = cmg1.CreateKeyMap();
    cds3.CreateSourceColumn().setColumn("XADEMO.XADEMO_ANALYTIC_FACTS.GEOG_LEAVES");
    cds3.setTargetObject(geographyDimension);
    cds3.setLevel(geographyDimension.FindLevel("L4"));
    CubeDimensionSourceExpression cds4 = cmg1.CreateKeyMap();
    cds4.setTargetObject(timeDimension);
    cds4.CreateSourceColumn().setColumn("XADEMO.XADEMO_ANALYTIC_FACTS.TIME_LEAVES");
    cds4.setLevel(timeDimension.FindLevel("L3"));
  }

  private static void createDerivedMeasure(
      Cube analyticCube, 
      Measure salesMeasure, 
      Measure costsMeasure)
  {
    DerivedMeasure profitMeasure = analyticCube.createDerivedMeasure();
    profitMeasure.setName("PROFIT");
    // What kind of expressions allowed
    profitMeasure.setExpressionText(
       salesMeasure.getId() + "-" + costsMeasure.getId());
    //profitMeasure.setOperator(String); possible values ?
  }

  private static void createOlapMeasure(
     Cube analyticCube, Measure salesMeasure, Dimension timeDimension) 
  {
    OlapMeasure ommovingtotal = analyticCube.createOlapMeasure();     
    // What are the different kind of OlapMeasure that can be created
    ommovingtotal.setName("OMMovingTotal");
    ommovingtotal.setOlapOperator("MOVINGTOTAL");
    OlapMeasureInput om1 = ommovingtotal.createOlapMeasureInput();
    om1.setName("OlapMeasInput_1");
    om1.setLongName(om1.getName());
    om1.setKeyWord("DIMENSION");
    om1.setReferencedObj(timeDimension);
    OlapMeasureInput om2 = ommovingtotal.createOlapMeasureInput();
    om2.setName("OlapMeasInput_2");
    om2.setLongName(om1.getName());
    om2.setKeyWord("MEASURE");
    om2.setReferencedObj(salesMeasure);
    OlapMeasureInput om3 = ommovingtotal.createOlapMeasureInput();
    om3.setName("OlapMeasInput_3");
    om3.setLongName(om1.getName());
    om3.setKeyWord("START");
    om3.setScalarValue("1");
    OlapMeasureInput om4 = ommovingtotal.createOlapMeasureInput();
    om4.setName("OlapMeasInput_4");
    om4.setLongName(om1.getName());
    om4.setKeyWord("STOP");
    om4.setScalarValue("3");
    OlapMeasureInput om5 = ommovingtotal.createOlapMeasureInput();
    om5.setName("OlapMeasInput_1");
    om5.setLongName(om1.getName());
    om5.setKeyWord("STEP");
    om5.setScalarValue("1");
  }

  private static AggregationDefinition createAggregationDefinition(
     AW xademoAW, Dimension channelDimension)
  {
    AggregationDefinition salesAggSolveDefn = 
         xademoAW.createAggregationDefinition();
    salesAggSolveDefn.setSchema("XADEMO");
    salesAggSolveDefn.setName("SalesAggMap");
    //salesAggSolveDefn.setCacheNa(String) What ?
    //salesAggSolveDefn.setCacheStore(String) What ?
    //salesAggSolveDefn.setAggIndex(String) What ?

    //ModelRef mdr = salesAggSolveDefn.createModelRef();
    //mdr.setModel(Model);
    //mdr.setCalculationOrder(int);
    //How to get ModelRefs back ?
      
    SolveDefDimRef sdr1 = salesAggSolveDefn.createSolveDefDimRef();
    sdr1.setDimension(channelDimension);
    //sdr1.setCalcMemberSolveOrder(String); Orderding takes number as string

    AggregationHierarchySpecification ahs1 = 
       salesAggSolveDefn.createAggregationHierarchySpecification();
    ahs1.setName("Relation1");
    //ahs1.setCalculationOrder(int);
    ahs1.setDimension(channelDimension);
    BaseOperator bo1 = ahs1.createBaseOperator();
    bo1.setOpcode("SUM"); // Possible Values
    // Is the below required ?
    //ahs1.setHierarchy(Hierarchy); // if not set applies to all hierarchies
    // inherited from Aggregation
   
    
    //PreComputeClause pc1 = ahs1.createPreComputeClause();
    PreComputeClause pc1 = ahs1.createPreComputeClause();
    DimensionMemberExpression dme1 = pc1.createDimensionMemberExpression();
    dme1.setExpression("ALL"); // Possible Values
    dme1.setExpressionType("INCLUDE"); // Possible Values 
    // do either above two or below two
    //dme1.setExpressionType("EXCLUDE"); // Possible Values 
    //dme1.setExpressionLevel(Level);

    return salesAggSolveDefn;
  }
  
  private static void createAllocationDefinition(
     AW xademoAW, 
     Measure costMeasure,
     Measure salesMeasure,
     Hierarchy channelHierarchy)
  {
    AllocationDefinition allocationDefinition1 = 
        xademoAW.createAllocationDefinition();
    allocationDefinition1.setSchema("XADEMO");
    allocationDefinition1.setName("AllocDefn1");
    //allocationDefinition1.setChildLock(String);
    //allocationDefinition1.setDeadLock(String);
    //allocationDefinition1.setSourceVal(String);
    
    AllocationHierarchySpecification alhs1 = 
       allocationDefinition1.createAllocateHierarchySpecification();
    alhs1.setName("ChannelAllocation");
    //alhs1.setDimension(Dimensino);
    alhs1.setHierarchy(channelHierarchy);
    //alhs1.setNaOperator(String);
    //alhs1.setRemOperator(String);
    //alhs1.setCalculationOrder(int);
    
    AllocationOperator aop1 = alhs1.createAllocationOperator();
    aop1.setOpcode("EVEN");
    //aop1.setOperatorType(OperatorType); How to create OperatorType
    //OperatorType.setOperatorType(String);
    
    AllocationArgument aa1 = alhs1.createAllocationArgument();
    aa1.setName("AllocationArgument1");
    Parameter p1 = aa1.createParameter();
    p1.setKeyWord("WEIGHTBY");
    p1.setValue(salesMeasure.getId());

    AllocationSolve allocSolve1 = xademoAW.createAllocationSolve();
    allocSolve1.setSchema("XADEMO");
    allocSolve1.setName("AllocSolve1");
    //allocSolve1.setBase(Measure);
    allocSolve1.setSource(costMeasure);
    allocSolve1.setTarget(salesMeasure);
    allocSolve1.setAllocationDefinition(allocationDefinition1);
    //allocSolve1.setSolveOrder(int);
    
    //DimensionMemberSelection dms = allocSolve1.createDimensionMemberSelection();
    //dms.setDimension(Dimension);
    //DimensionMemberExpression dme = dms.createDimensionMemberExpression();
    //dme.setExpression(String);
    //dme.setExpressionType(String);
    //dme.setLevel(level);
  }

  private static void createForecastDefinition(
       AW xademoAW, 
       Measure costsMeasure, 
       Measure salesMeasure, 
       Dimension timeDimension)
  {
    ForecastDefinition forecastDefinition1 = 
         xademoAW.createForecastDefinition();
    forecastDefinition1.setSchema("XADEMO");
    forecastDefinition1.setName("ForecastDefinition1");
    forecastDefinition1.setTimeDimension(timeDimension);
    // forecastDefinition1.setSeasonalTimeTarget(Measure);
    // forecastDefinition1.setSemiSeasonalTimeTarget(Measure);
    
    ForecastArgument fa1 = forecastDefinition1.createForecastArgument();
    //fa1.setForecastKeyWord(String);   What ?
    //fa1.setForecastKeyWord(ForecastKeyWord);   What ?
    // ForecastKeyword seems to have no relevant methods

    ForecastArgumentValue fav1 = fa1.createForecastAgrumentValue();  
    //fav1.setKeyWord(String);
    fav1.setValue("10");       

    ForecastSolve forecastSolve = xademoAW.createForecastSolve();
    forecastSolve.setSchema("XADEMO");
    forecastSolve.setName("ForecastSolve1");
    forecastSolve.setForecastDefinition(forecastDefinition1);
    forecastSolve.setSource(costsMeasure);
    forecastSolve.setTarget(salesMeasure);
    //forecastSolve.setSolveOrder(int);
    
    //DimensionMemberSelection dme = forecastSolve.createDimensionMemberSelection();    
    //dme.setDimension(Dimension);
  }

  private static void createAggregationSolve(
     AW xademoAW, 
     Measure salesMeasure, 
     AggregationDefinition salesAggSolveDefn)
  {
    AggregationSolve aggSolve1 = xademoAW.createAggregationSolve();
    aggSolve1.setSchema("XADEMO");
    aggSolve1.setName("AggregationSolve1");
    aggSolve1.addTarget(salesMeasure);
    //aggSolve1.setSource(Measure); // a base source
    //aggSolve1.setSolveOrder(int); // Which aggSolve to do first
    aggSolve1.setAggregationDefinition(salesAggSolveDefn);
    //inherited from Solve
    //DimensionMemberSelection dms = aggSolve1.createDimensionMemberSelection();
    //dms.setDimension(Dimension);
    //DimensionMemberExpression dme = dms.createDimensionMemberExpression();
    //dme.setExpression(String);
    //dme.setExpressionType(String);
    //dme.setLevel(Level);
  }

  private static void createModel(AW xademoAW, Dimension channelDimension)
  {
    Model model = xademoAW.createModel();
    model.setSchema("XADEMO");
    model.setName("Model1");
    model.setDimension(channelDimension);
    //model.setContents(String);
    //CalculatedMemberRef cmr = model.createCalculatedMemberRef();
    //PerminantCalculatedMember pcm = channelDimension.createPerminantCalculatedMember();
    //pcm.setExpression("MIAMI + BOSTON");
    //pcm.setStorageType(String);
    //cmr.setCalculatedMember(pcm);
  }

  private static void updateAW(String awName, AW xademoAW, AWConnection awConnection)
  {
    // Can we read the AW back
    // workaround limitDimensions bug
    xademoAW.Detach(awConnection);

    xademoAW = AW.readAWDefinitions(awConnection, awName);
    System.out.println("Finished reading " + awName + " on " + new Date().toString());
    //System.out.println("XML for AW = " + xademoAW.WriteToXML());
    xademoAW.Detach(awConnection);
    xademoAW.Attach(awConnection, "rw");
    Interaction iaa = new Interaction();
    iaa.setConnection(awConnection);

    Dimension channelDim = xademoAW.findDimension("CHANNEL");
    channelDim.setLongName("Chunnel");
    Alter a = new Alter(iaa);
    a.setActiveObject(channelDim);
    iaa.addAWAction(a);
    Level n1Level = channelDim.createLevel();
    n1Level.setName("NL1");
    Create c = new Create(iaa);
    c.setActiveObject(n1Level);
    iaa.addAWAction(c);
    Level n2Level = channelDim.createLevel();
    n2Level.setName("NL2");
    c = new Create(iaa);
    c.setActiveObject(n2Level);
    iaa.addAWAction(c);      
    Hierarchy h = channelDim.FindHierarchy("STANDARD");
    HierarchyLevelAssociation hla = h.createHierarchyLevelAssociation();
    hla.setLevel(n1Level);
    c = new Create(iaa);
    c.setActiveObject(hla);
    iaa.addAWAction(c);
    Hierarchy hier = channelDim.createHierarchy();
    hier.setName("HIER");
    c = new Create(iaa);
    c.setActiveObject(hier);
    iaa.addAWAction(c);
    Hierarchy standardHier = channelDim.FindHierarchy("STANDARD");
    for (Iterator hlit = standardHier.getHierarchyLevels().iterator(); hlit.hasNext();)
    {
      HierarchyLevelAssociation hlaz = (HierarchyLevelAssociation) hlit.next();
      //for (Iterator hlmapit = hlaz.getSourceMapGroup().iterator(); hlmapit.hasNext();)
      //{
      //  DimensionMapGroup dmg = (DimensionMapGroup) hlmapit.next();
      //  Delete d = new Delete(iaa);
      //  d.setActiveObject(dmg);
      //  iaa.addAWAction(d);          
      //}
    }
    HierarchyLevelAssociation hlan = hier.createHierarchyLevelAssociation();
    hlan.setLevel(channelDim.FindLevel("STANDARD_1"));
    DimensionMapGroup dmg = hlan.createSourceDimensionMapGroup();
    
    DimensionKeySourceExpression dkse = dmg.CreateKeyMap(); // Singleton
    SourceColumn sc = dkse.CreateSourceColumn();
    sc.setColumn("a");

    iaa.execute();
    xademoAW.Commit(awConnection);
    System.out.println("Added level NL1 and NL2 and hierarchy HIER to Channel " 
       + awName + " on " + new Date().toString());
  }

  private static void updateAW2(String awName, AW xademoAW, AWConnection awConnection)
  {
          // workaround limitDimensions bug
      xademoAW.Detach(awConnection);
      
      xademoAW = AW.readAWDefinitions(awConnection, awName);
      xademoAW.Detach(awConnection);
      xademoAW.Attach(awConnection, "rw");
      Dimension channelDim = xademoAW.findDimension("CHANNEL");
      Level n1Level = channelDim.FindLevel("NL1");
      Level n2Level = channelDim.FindLevel("NL2");
      channelDim.removeLevel(n2Level);

      //n1Level.Rename(awConnection, "N11");
      //n2Level.Delete(awConnection);
      //Alternate way of doing above Rename and Delete
      Interaction ia2 = new Interaction();
      ia2.setConnection(awConnection);
      Delete d = new Delete(ia2);
      d.setActiveObject(n2Level);
      ia2.addAWAction(d);
      //Rename not supported
      //Rename r = new Rename(ia2);
      //r.setTargetName("N11");
      //r.setActiveObject(n1Level);
      //ia2.addAWAction(r);
      ia2.execute();
      
      xademoAW.Commit(awConnection);
      System.out.println("Deleted Level N2 to " + awName + " on " + new Date().toString());      
  }

  /**
   * create a hiearchy, attributes from a list 
   * of levels and their column mappings
   */
  public static Hierarchy createHierarchy( Dimension dimension, 
                                    String hierarchyName, 
                                    String[] levelColumnMap, 
                                    String[] attributeNames) {

    Attribute[] attributes = new Attribute[attributeNames.length / 3];
    for (int i = 0; i < attributeNames.length;) {
      Attribute attr = dimension.createAttribute();
      attr.setName(attributeNames[i++]);
      attr.setDataType(attributeNames[i++]);
      //Define an attribute as a Dimension e.g. gender
      // attr.setDimensionDomain(Dimension) 

      String attrClassification = attributeNames[i++];
      if (attrClassification != null)
         attr.setClassification(attrClassification);
      attributes[(i-1)/3] = attr;
    }
    
    Hierarchy h = dimension.createHierarchy();
    h.setName(hierarchyName);
    //h.addAttributeProjection(AttributeProjection);
    for (int i = 0; i < levelColumnMap.length;) {
      String levelName = levelColumnMap[i++];
      String levelTableColumn = levelColumnMap[i++];
      String parentLevelTableColumn = levelColumnMap[i++];
      // If we set attribute for a level is it inherited by a Hierarchy ?
      Level l = dimension.createLevel();
      l.setName(levelName);
      //l.addAttributeProjection(AttributeProjection);
      //l.setIsDimensioned(boolean) Future
      HierarchyLevelAssociation hla = h.createHierarchyLevelAssociation();
      hla.setLevel(l);

      // Multiple DimensionGroups will perform a union (ignore for now)
      DimensionMapGroup dmg = hla.createSourceDimensionMapGroup();
      DimensionKeySourceExpression dkse = dmg.CreateKeyMap(); // Singleton
      // WhereClause wc = dkse.CreateRestriction()
      // wc.setWhereClause();

      // multiple SourceColumn are used for construction members combinging
      // two columns e.g state and city column can be combined into one
      SourceColumn sc = dkse.CreateSourceColumn();
      sc.setColumn(levelTableColumn);
      if (parentLevelTableColumn != null) {
        HierarchialParentSourceExpression hpse = dmg.CreateParentMap();
        SourceColumn hpsesc = hpse.CreateSourceColumn();
        hpsesc.setColumn(parentLevelTableColumn);  
        //The next line generates an exception while Dimension.Create();
        //hpse.setParentLevelCol(parentLevelTableColumn); What ?
        hpse.setLevel(l);
        hpse.setHierarchy(h);
      }

      for (int j = 0; j < attributes.length; ++j) {
        AttributeProjection attrproj = hla.createAttributeProjection();
        attrproj.setAttribute(attributes[j]);       
        String attrColumn = levelColumnMap[i++];
        if (attrColumn != null) {
           AttributeSourceExpression ase = dmg.CreateAttributeMap();
           ase.setBaseAttribute(attributes[j]);
           ase.setTargetObject(attrproj);
           SourceColumn asc = ase.CreateSourceColumn();
           asc.setColumn(attrColumn);
        }
      }
    }    
    return h;
  }
}
