import java.io.*;
import java.util.HashMap;
import java.util.Vector;
import java.awt.*;

import jet.api.*;
import jet.jetc.*;
import jet.universe.exception.*;

/**
 * This class creates a report called subreport1 that inserts a subreport into the report header in a banded report component.
 * It requires the catalog JinfonetGourmetJava.cat, query ProductSalesAnalysis, and report AnnualSalesbyRegion.cls as subReport.
 * 
 * Report Structure: reportset | reportbody | report | group header | subreport | group header | detail |
 * 
 * Usage TestDesignGraph -path=<path> -catalog=<catalog> -report=<report> [-log=<log file>]
 */
public class TestDesignSubreport
{
	String path;
	Designer desg;
	String errorMsg = null;     // Holds error message related to a failure that is visible to main().
	HashMap<Integer, String> handleNames = new HashMap<Integer, String>();

	/**
	 * Constructor. Create a new TestDesignSubreport object.
	 */
	public TestDesignSubreport(String path, String cat, String log) throws IOException, ReadFailureException, UniverseFileException
	{
		this.path = path + '\\';
		// Needs Designer API License Key or Server Designer API License Key depending on the classpath
		DesignerUserInfo userInfo=new DesignerUserInfo("Jinfonet", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
		desg = new Designer(path, cat,userInfo);
		if ( log != null && log.length() > 0 )
		{
			desg.setLog(new FileOutputStream(log), "8859_1");
		}
		  // Fill up hash map to support converting handle type to name, for logging.
        handleNames.put(new Integer(Designer.PAGE),        "Page");
        handleNames.put(new Integer(Designer.PAGEHEADER),  "Page Header");
        handleNames.put(new Integer(Designer.PAGEFOOTER),  "Page Footer");
        handleNames.put(new Integer(Designer.PAGEEND),     "Page End");
        handleNames.put(new Integer(Designer.PAGESTART),   "Page Start");
        handleNames.put(new Integer(Designer.DATASET),     "Dataset");
        handleNames.put(new Integer(Designer.BANDEDOBJECT_HEADER),     "Banded Object Header");
        handleNames.put(new Integer(Designer.BANDEDOBJECT_FOOTER),     "Banded Object Footer");
        handleNames.put(new Integer(Designer.BANDEDOBJECT),            "Banded Object");
        handleNames.put(new Integer(Designer.BANDEDOBJECT_PAGEHEADER), "Banded Object Page Header");
        handleNames.put(new Integer(Designer.BANDEDOBJECT_PAGEFOOTER), "Banded Object Page Footer");
        handleNames.put(new Integer(Designer.GROUPHEADER), "Group Header");
        handleNames.put(new Integer(Designer.GROUPFOOTER), "Group Footer");
        handleNames.put(new Integer(Designer.DETAIL),      "Detail");
        handleNames.put(new Integer(Designer.REPORTSET), "Report Set");
        handleNames.put(new Integer(Designer.REPORTBODY), "Report Body");
        handleNames.put(new Integer(Designer.DATAOBJECT),  "Data Container"); 
        handleNames.put(new Integer(Designer.REPORTSHEET), "Report Sheet");
        handleNames.put(new Integer(Designer.REPORTFOOTER),  "Report Footer"); 
        handleNames.put(new Integer(Designer.REPORTHEADER), "Report Header");

	}

	/**
	 * Show the handles of the current report structure, to assist in debugging programs using the Designer class methods.
	 */
	public void showHandles(String label)
	{
	    Integer type;
	    String sType;
	    String handles[] = desg.getHandles();    
	    System.out.println("---- " + label + " --- size: " + handles.length + " ----");
	    for (int i = 0; i < handles.length; i++) {
	        type=desg.getObjectType(handles[i]);

	        // generate readable and output-formatted name of type
	        // intent is to show type and name and ignore unknown types
	        sType=handleNames.get(type);
	        if(sType != null) 
	        {
	            sType="("+sType+")";
	            System.out.println(handles[i] + "  Type: " + type + sType  );
	        }
	        else if (type != -1)
	        {
	            System.out.println(handles[i] + "Type: " + type);
	        }
	    }
	    System.out.println("---- " + label + " --- end");
	   
	    return;
	}

	/**
	 * Create report according to parameter name.
	 * @throws DesignerErrorException 
	 */
	public boolean create(String name) throws DesignerErrorException
	{
		String handle, handles[], reportset, report, reportbody, banded, dataset, groupPT, groupPN, header, footer;

		// Delete old <report>.cls if it is present
		desg.deleteReportFile(name);
		// Create new <report>.cls
		reportset = desg.createReportSet(name);
		if (reportset == null) {
            this.errorMsg = "Failure addDataSet(): " + desg.getError();
            return false;
        }
		
		// 2. Register the existing query "ProductSalesAnalysis" to this report set.
        dataset = desg.addDataset(reportset, "Data Source 1", "ProductSalesAnalysis","dsProductSalesAnalysis", "",Designer.DATASET_TYPE_QUERY);
        if (dataset == null) {
            this.errorMsg = "Failure addDataSet(): " + desg.getError();
            return false;
        }
        //   showHandles("After createReportSet");       
        // 3. Create the named report tab within the Page Report
        //    For this example program, the name of the added report tab is hard coded.
        report = desg.addReport(reportset, "myreport");
        if (report == null) {
            this.errorMsg = "Failure addReport(): " + desg.getError();
            return false;
        }
 
        reportbody = desg.getHandles(report, Designer.REPORTBODY, -1)[0];
             
        // 4. Insert a PagePanel into the myreport tab
        String page = desg.insertPage(report);
             
        desg.insertPageStartEnd(page, reportbody, 0, 0);
        desg.set(page, "Width", 8.0f);
        desg.set(page, "Height", 9.2f);
              
        //showHandles("after insert page");
              
            String[] pageFooter = desg.getHandles(report, Designer.PAGEFOOTER, -1);
            desg.set(pageFooter[0], "Height", 0.2f);

            // 5. Insert the banded object for myreport tab             
            banded = desg.insertBandedObject(reportbody, true, true, true);
            desg.set(banded, "Width", 8.0f);
            // designer.set(banded, "Height", 9.2f);

            String[] sections = desg.getSections(banded);
            //to set width of all sections in banded object 
            for ( int i = 0; i< sections.length;i++)
            {
            	desg.set(sections[i], "Width", 8.0f);
            }
            handles = desg.getHandles(banded, Designer.BANDEDOBJECT_HEADER);
            System.out.println("banded object header handle: " + handles[0]);
            desg.set(handles[0], "Invisible", true);
             
            // You should see that we have a Report tab called myreport, a ReportBody, a PagePanel and a BandedObject in the tree
            showHandles("after insert banded object");

            // 6. bind the dataset to the report body and set banded object to inherit the dataset
            // it is an container object that must have a data set bound to it.
            if( ! desg.bindDataSet(reportbody, "dsProductSalesAnalysis") ) {
                this.errorMsg = "Failure bindDataSet(): " + desg.getError();
                return false;
            }
            desg.set(banded, "dataInherit", true);
		
			// After creating the report there will be one report header,two report footers,
			//one page header and two groups.
			handles = desg.getHandles(report, Designer.DETAIL);
			for ( int i = handles.length; --i >= 0; )
			{
				desg.set(handles[i], "Invisible", true);
			}

			//================draw the report
			//page footer
			handles = desg.getHandles(report, Designer.PAGEFOOTER, -1);
			desg.set(handles[0], "Height", 0.05f);

			//report header
			handles = desg.getHandles(report, Designer.BANDEDOBJECT_PAGEHEADER, -1);
			desg.set(handles[0], "Height", 1.25f);

			handle = desg.insert(handles[0], Designer.LABEL, "Label9");
			desg.set(handle, "Width", 5.67f);
			desg.set(handle, "Height", 0.45f);
			desg.set(handle, "X", 0.12f);
			desg.set(handle, "Y", 0.12f);
			desg.set(handle, "Text", "Product Sales by Region");
			desg.set(handle, "Foreground", new Color(0x900000));
			desg.set(handle, "Bold", true);
			desg.set(handle, "Alignment", Designer.LEFTCENTER);
			desg.set(handle, "Format", "XXXXXXXXXX.."); 
			desg.set(handle, "FontSize", 0.31f);

			handle = desg.insert(handles[0], Designer.PRINTDATE, "SystemField2");
			desg.set(handle, "Width", 1.56f);
			desg.set(handle, "Height", 0.2f);
			desg.set(handle, "X", 0.12f);
			desg.set(handle, "Y", 0.62f);
			desg.set(handle, "Bold", true);
			desg.set(handle, "Alignment", Designer.LEFTCENTER);
			desg.set(handle, "Format", "MM/dd/yyyy"); 
			desg.set(handle, "FontSize", 0.11f);

			//report footer 1
			handles = desg.getHandles(report, Designer.BANDEDOBJECT_PAGEFOOTER, -1);
			desg.set(handles[0], "Height", 0.87f);
			
			//insert report footer 2
			footer = desg.insert(report, Designer.REPORTFOOTER, "ReportFooterPanel2");
			desg.set(footer, "Label", "Report Footer");
			desg.set(footer, "Height", 0.87f);

			//insert group panel 3
			handles = desg.getHandles(report, Designer.BANDEDOBJECT, -1);

			GroupInfo ginfo =new GroupInfo( "Product Type Name", GroupInfo.DESCENDING );
			groupPT = desg.insertSectionGroup(handles[0], ginfo);
			if (groupPT == null) {
	            this.errorMsg = "Failure addGroup(Product Type Name): " + desg.getError();
	            return false;
	        }
			// After inserting a group the details of report are moved into this group and a group header/footer is created.
			//group1.header
			header = desg.getHandles(groupPT, Designer.GROUPHEADER)[0];
			desg.set(header, "Height", 2.50f);
			// Hide the special group field that is added automatically with the group
            handles = desg.getHandles(header, Designer.GROUPNAME);
            desg.set(handles[0], "Invisible", true);
			
            //insert the subreport into the group header. 
            Vector<Object> v = new Vector<Object>();
			SubReportInfo sinfo = new SubReportInfo("AnnualSalesbyRegion.cls","report1", true, v,v,v);		
			handle = desg.insertSubReport(header, sinfo);
			desg.set(handle, "Height", 7.65f);
			desg.set(handle, "Width", 7.65f);
				
			//insert DB field at group panel3 header
			handle = desg.insert(header, Designer.DBFIELD, "DBField2", "Product Type Name");
			desg.set(handle, "Width", 7.14f);
			desg.set(handle, "Height", 0.26f);
		    desg.set(handle, "X", 0.11f);
			desg.set(handle, "Y", 0.05f);
			desg.set(handle, "Background", new Color(0x000090));
			desg.set(handle, "Foreground", new Color(0xffffff));
			desg.set(handle, "Bold", true);
			desg.set(handle, "Alignment", Designer.LEFTCENTER);
			desg.set(handle, "Format", "XXXXXXXXXX.."); 
			desg.set(handle, "FontSize", 0.19f);

			//insert other group panel3 header
			header = desg.insert(groupPT, Designer.GROUPHEADER, "groupheader6");
			
			handle = desg.insert(header, Designer.LABEL, "Label13");
			desg.set(handle, "Width", 2.58f);
			desg.set(handle, "Height", 0.26f);
			desg.set(handle, "X", 3.74f);
			desg.set(handle, "Y", 0.05f);
			desg.set(handle, "Foreground", new Color(0x000090));
			desg.set(handle, "Text", "Product List of");
			desg.set(handle, "Bold", true);
			desg.set(handle, "Alignment", Designer.LEFTCENTER);
			desg.set(handle, "FontSize", 0.17f);

			//group2.footer
			footer = desg.getHandles(groupPT, Designer.GROUPFOOTER)[0];
			desg.set(footer, "Invisible", true);

			//insert group panel 4
			ginfo =new GroupInfo( "Product Name", GroupInfo.DESCENDING );
			groupPN = desg.insertSectionGroup(groupPT, ginfo);
			if (groupPN == null) {
		        this.errorMsg = "Failure addGroup(Product Name): " + desg.getError();
		        return false;
			}
			
			header = desg.getHandles(groupPN, Designer.GROUPHEADER)[0];
			handles = desg.getHandles(header, Designer.GROUPNAME);
            desg.set(handles[0], "Invisible", true);
 
			//insert system field at group panel3 header
			handle = desg.insert(header, Designer.DBFIELD, "DBField1", "Product Name");
			desg.set(handle, "Width", 1.95f);
			desg.set(handle, "Height", 0.2f);
		    desg.set(handle, "X", 4.30f);
			desg.set(handle, "Y", 0f);
			desg.set(handle, "Bold", true);
			desg.set(handle, "Alignment", Designer.LEFTCENTER);
			desg.set(handle, "Format", "XXXXXXXXXX.."); 
			desg.set(handle, "FontSize", 0.13f);

			footer = desg.getHandles(groupPN, Designer.GROUPFOOTER)[0];
			desg.set(footer, "Invisible", true);
			String detail = desg.getHandles(groupPN, Designer.DETAIL)[0];
			desg.set(detail, "Invisible", true);
					
        desg.exit();
		try
		{
			desg.closeLog();
			return true;
		}
		catch ( IOException e )
		{
			e.printStackTrace();
			return false;
		}
	}
	// parameter tokens
    private final static String pathArg = "-path=";
    private final static String catArg = "-catalog=";
    private final static String rptArg = "-report=";
    private final static String logArg = "-log=";

    private final static void showUsage() {
        System.out.println( "TestDesignSubreport - programattically define a banded report with a subreport inserted into the Banded Header.");
        System.out.println( "Usage:  java TestDesignSubreport <-options>");
        System.out.println("\nwhere options include:");
        System.out.println("    " + pathArg +   "<path to catalog>  indicates the full path name to the report catalog directory");
        System.out.println("    " + catArg +    "<catalog name>  indicates the name of the report catalog");
        System.out.println("    " + rptArg +    "<report name>  indicates the name of the report to create");
        System.out.println("    " + logArg +    "<log file path and name>   indicates to log to this file, defined by full path name");
        System.out.println("\nExample to create and define a report from the command line:");
        System.out.println("java TestDesignSubreport -path=C:\\JReport\\Designer\\Demo\\Reports\\TutorialReports  -catalog=JinfonetGourmetJava.cat  -report=TestSubreport.cls -log=C:\\JReport\\Designer\\logs\\subreport.log");
    }

    public static void main(String argv[])
    {
        // values of command line arguments.
        String path = "";
        String catalog = "";
        String report = "";
        String log = "";

        // get values of command line arguments
        for (int i = 0; i < argv.length; i++) {
            if (argv[i].toLowerCase().startsWith(catArg)) {
                catalog = argv[i].substring(catArg.length(), argv[i].length());
            } else if (argv[i].toLowerCase().startsWith(rptArg)) {
                report = argv[i].substring(rptArg.length(), argv[i].length());
            } else if (argv[i].toLowerCase().startsWith(pathArg)) {
                path = argv[i].substring(pathArg.length(), argv[i].length());
            } else if (argv[i].toLowerCase().startsWith(logArg)) {
                log = argv[i].substring(logArg.length(), argv[i].length());
            } else {
                // is not a valid command line argument
                showUsage();
                System.exit(1);
            }
         }    

        // log file is an optional parameter.
        // path, catalog, and report are required parameters.
        if ( (path.length() == 0) || (catalog.length() == 0) || report.length() == 0 ) {
                showUsage();
                System.exit(1);
        }

        System.out.println("Catalog = " + catalog);
        System.out.println("   Path = " + path);
        System.out.println(" Report = " + report);
        System.out.println("    Log = " + ((log==null) ? "" : log));

			if ( path.length() > 0 && catalog.length() > 0 && report.length() > 0)
			{
				try
				{
					TestDesignSubreport test = new TestDesignSubreport(path, catalog, log);
					if (test.create(report))
					{
						System.out.println("Successfully created " + report + " in "+ path);
					}
					else
					{
						System.out.println("Error creating " + report + ", check log file "+ log);
					}
				}
				catch ( Exception e )
				{
					e.printStackTrace();
					showUsage();
				}
			}
		else
		{
			showUsage();
		}

		System.exit(0);
	}
}
