import com.hp.ucmdb.generated.*;
import com.hp.ucmdb.generated.UcmdbFault;
import com.hp.ucmdb.generated.UcmdbServiceStub.*;


import java.net.MalformedURLException;
import java.rmi.RemoteException;


abstract public class QueryDemo extends Demo {


    public static void main(String[] args) throws RemoteException, UcmdbFault, MalformedURLException {
        UcmdbServiceStub serviceStub = getStub();

        getCIsByIdDemo(serviceStub);
        getCIsByTypeDemo(serviceStub);
        getFilterCIsByTypeWithConditions(serviceStub);
        executeTopologyQueryByNameDemo(serviceStub);
        executeTopologyQueryByNameWithParametersDemo(serviceStub);
        getCINeighboursDemo(serviceStub);//-
    }

    public static void getCINeighboursDemo(UcmdbServiceStub serviceStub) {
        System.out.println("start execute Topology Query neighbour CI");
        GetCINeighbours request = new GetCINeighbours();
        //set cmdbcontext

        request.setCmdbContext(context);
        // set CI id
        ID id = new ID();
        id.setString("42fb561ac0cba5d6be6502f81ee414eb");
        request.setID(id);
        //set neighbour type
        request.setNeighbourType("callhome_event");

        GetCINeighboursE requestE = new GetCINeighboursE();
        requestE.setGetCINeighbours(request);
        try {
            GetCINeighboursResponseE responseE =
                    serviceStub.getCINeighbours(requestE);
            GetCINeighboursResponse response = responseE.getGetCINeighboursResponse();
            Topology topology = response.getTopology();
            System.out.println("end execute Topology Query neighbour CI");
        } catch (RemoteException e) {
            //handle exception
        } catch (UcmdbFault e) {
            //handle exception
        }
    }


    public static void executeTopologyQueryByNameWithParametersDemo(UcmdbServiceStub serviceStub) {
        System.out.println("start execute topology query by name with parameters demo");
        ExecuteTopologyQueryByNameWithParameters request = new ExecuteTopologyQueryByNameWithParameters();
        //set cmdbcontext
        request.setCmdbContext(context);
        //set query name 
        //there should be an existing parametrized query
        request.setQueryName("Query_3");
        //set parameters
        ParameterizedNode parametrizedNode =
                new ParameterizedNode();
        parametrizedNode.setNodeLabel("ConfigurationItem");
        CIProperties parameters = new CIProperties();
        StrProps strProps = new StrProps();
        StrProp strProp = new StrProp();
        //query has one parameter called name
        strProp.setName("name");
        //the value of the parameter should begin with 'c' following anything else
        strProp.setValue("c%");
        strProps.addStrProp(strProp);
        parameters.setStrProps(strProps);
        parametrizedNode.setParameters(parameters);

        request.addParameterizedNodes(parametrizedNode);

        ExecuteTopologyQueryByNameWithParametersE requestE = new ExecuteTopologyQueryByNameWithParametersE();
        requestE.setExecuteTopologyQueryByNameWithParameters(request);

        try {
            ExecuteTopologyQueryByNameWithParametersResponseE
                    responseE =
                    serviceStub.executeTopologyQueryByNameWithParameters
                            (requestE);
            ExecuteTopologyQueryByNameWithParametersResponse response = responseE.getExecuteTopologyQueryByNameWithParametersResponse();

            TopologyMap map =
                    getTopologyMapResult
                            (response.getTopologyMap(), response.getChunkInfo(), serviceStub);
            CINode[] nodes = map.getCINodes().getCINode();

            for (int i = 0; i < nodes.length; i++) {


                CI ci[] = nodes[i].getCIs().getCI();
                for (int j = 0; j < ci.length; j++) {
                    System.out.println("CI type is " + ci[j].getType() + " ,id is " + ci[j].getID());
                }
            }
            System.out.println("end execute topology query by name with parameters demo");
        } catch (RemoteException e) {
            //handle exception
        } catch (UcmdbFault e) {
            //handle exception
        }
    }

    public static void executeTopologyQueryByNameDemo(UcmdbServiceStub serviceStub) {
        ExecuteTopologyQueryByNameE requestE = new ExecuteTopologyQueryByNameE();
        ExecuteTopologyQueryByName request = new ExecuteTopologyQueryByName();
        //set cmdbcontext
        request.setCmdbContext(context);
        //set query name
        request.setQueryName("Query_1");
        requestE.setExecuteTopologyQueryByName(request);
        try {
            ExecuteTopologyQueryByNameResponseE responseE =
                    serviceStub.executeTopologyQueryByName(requestE);
            ExecuteTopologyQueryByNameResponse response = responseE.getExecuteTopologyQueryByNameResponse();

            TopologyMap map =
                    getTopologyMapResult
                            (response.getTopologyMap(), response.getChunkInfo(), serviceStub);
            CINode[] nodes = map.getCINodes().getCINode();

            for (int i = 0; i < nodes.length; i++) {


                CI ci[] = nodes[i].getCIs().getCI();
                for (int j = 0; j < ci.length; j++) {
                    System.out.println("CI type is " + ci[j].getType() + " ,id is " + ci[j].getID());
                }
            }
        } catch (RemoteException e) {
            //handle exception
        } catch (UcmdbFault e) {
            //handle exception
        }
    }

    private static void getFilterCIsByTypeWithConditions(UcmdbServiceStub serviceStub) {
        System.out.println("start getFilterCIsByTypeWithConditions");
        UcmdbServiceStub.GetFilteredCIsByTypeE requestE = new UcmdbServiceStub.GetFilteredCIsByTypeE();
        UcmdbServiceStub.GetFilteredCIsByType request = new UcmdbServiceStub.GetFilteredCIsByType();
        request.setCmdbContext(context);
        request.setType("node"); //anyType gives null pointer exception
        CustomProperties customProperties = new CustomProperties();
        PropertiesList propertiesList = new PropertiesList();
        propertiesList.addPropertyName("name");
        propertiesList.addPropertyName("display_label");//properties format is formed with lowercase and underscore
        customProperties.setPropertiesList(propertiesList);
        request.setProperties(customProperties);
        //conditions objects provides a filtering option
        Conditions conditions = new Conditions();

        StrConditions strConditions = new StrConditions();
        StrCondition strCond = new StrCondition();
        StrProp strProp = new StrProp();
        strProp.setName("name");
        strProp.setValue("c%");
        strCond.setCondition(strProp);
        strCond.setStrOperator(StrOperator_type1.LikeIgnoreCase);
        strConditions.addStrCondition(strCond);


        BooleanConditions booleanConds = new BooleanConditions();
        BooleanCondition booleanCond = new BooleanCondition();

        BooleanProp prop = new BooleanProp();
        prop.setName("root_enableageing");
        prop.setValue(false);

        booleanCond.setBooleanOperator(BooleanOperator_type1.Equal);
        booleanCond.setCondition(prop);
        booleanConds.addBooleanCondition(booleanCond);

        conditions.setBooleanConditions(booleanConds);
        conditions.setStrConditions(strConditions);
        //conditions and contained created above objects must not be null even if there's no logical condition, put empty object
        request.setConditions(conditions);
        request.setConditionsLogicalOperator(UcmdbServiceStub.ConditionsLogicalOperator_type1.AND);
        requestE.setGetFilteredCIsByType(request);
        try {
            GetFilteredCIsByTypeResponseE responseE = serviceStub.getFilteredCIsByType(requestE);
            GetFilteredCIsByTypeResponse response = responseE.getGetFilteredCIsByTypeResponse();
            CIs cis = response.getCIs();
            CI ci[] = cis.getCI();
            for (int i = 0; i < ci.length; i++) {
                System.out.println("CI type is " + ci[i].getType() + " ,id is " + ci[i].getID());
            }

        } catch (RemoteException e) {
            //handle exception
            System.out.println("RemoteException");
            System.out.println(e.toString());
        } catch (UcmdbFault e) {
            //handle exception
            System.out.println("UcmdbFault");
            System.out.println(e.toString());
        }
        System.out.println("getFilterCIsByTypeWithConditions end");
    }


    public static void getCIsByIdDemo(UcmdbServiceStub serviceStub) {
        System.out.println("getCIsByIdDemo begin");
        UcmdbServiceStub.GetCIsByIdE getCIsByIde = new UcmdbServiceStub.GetCIsByIdE();
        UcmdbServiceStub.GetCIsById getCIsById = new UcmdbServiceStub.GetCIsById();
        getCIsById.setCmdbContext(context);
        ID ciId[];
        ciId = new ID[1];
        ciId[0] = new ID();

        ciId[0].setString("48474b1562021e6c8410c80665c04e36");// CI id, not global Id
        IDs param = new IDs();
        param.setID(ciId);
        getCIsById.setIDs(param);
        getCIsByIde.setGetCIsById(getCIsById);
        try {
            GetCIsByIdResponseE responseE = serviceStub.getCIsById(getCIsByIde);
            GetCIsByIdResponse response = responseE.getGetCIsByIdResponse();
            CIs cis = response.getCIs();
            CI ci[] = cis.getCI();
            for (int i = 0; i < ci.length; i++) {
                System.out.println("CI type is " + ci[i].getType() + " ,id is " + ci[i].getID());
            }
        } catch (RemoteException e) {
            //handle exception
        } catch (UcmdbFault e) {
            //handle exception
        }
        System.out.println("getCIsByIdDemo end");
    }


    public static void getCIsByTypeDemo(UcmdbServiceStub serviceStub) {
        System.out.println("getCIsByTypeDemo begin");
        UcmdbServiceStub.GetCIsByTypeE getCIsByTypee = new UcmdbServiceStub.GetCIsByTypeE();
        UcmdbServiceStub.GetCIsByType getCIsByType = new UcmdbServiceStub.GetCIsByType();
        getCIsByType.setCmdbContext(context);

        getCIsByType.setType("node");
        getCIsByTypee.setGetCIsByType(getCIsByType);
        try {
            GetCIsByTypeResponseE responseE = serviceStub.getCIsByType(getCIsByTypee);
            GetCIsByTypeResponse response = responseE.getGetCIsByTypeResponse();
            CIs cis = response.getCIs();

            CI ci[] = cis.getCI();
            for (int i = 0; i < ci.length; i++) {
                System.out.println("CI type is " + ci[i].getType() + " ,id is " + ci[i].getID());
            }

        } catch (RemoteException e) {
            //handle exception
        } catch (UcmdbFault e) {
            //handle exception
        }
        System.out.println("getCIsByTypeDemo end");

    }


    private static TopologyMap getTopologyMapResult(TopologyMap topologyMap, ChunkInfo chunkInfo, UcmdbServiceStub serviceStub) {
        if (chunkInfo.getNumberOfChunks() == 0) {
            return topologyMap;
        } else {

            topologyMap = new TopologyMap();
            for (int i = 1; i <= chunkInfo.getNumberOfChunks(); i++) {
                ChunkRequest chunkRequest = new ChunkRequest();
                chunkRequest.setChunkInfo(chunkInfo);
                chunkRequest.setChunkNumber(i);

                PullTopologyMapChunks req =
                        new PullTopologyMapChunks();
                req.setChunkRequest(chunkRequest);
                req.setCmdbContext(context);
                PullTopologyMapChunksE reqE =
                        new PullTopologyMapChunksE();
                reqE.setPullTopologyMapChunks(req);

                PullTopologyMapChunksResponseE resE;


                try {
                    resE = serviceStub.pullTopologyMapChunks(reqE);
                    PullTopologyMapChunksResponse res = resE.getPullTopologyMapChunksResponse();
                    topologyMap = res.getTopologyMap();

                } catch (RemoteException e) {
                    //handle exception
                } catch (UcmdbFault e) {
                    //handle exception
                }
            }
        }
        return topologyMap;
    }

    private static TopologyMap getTopologyMapResultFromCIs(CIs cis, ChunkInfo chunkInfo, UcmdbServiceStub serviceStub) {
        TopologyMap topologyMap = new TopologyMap();
        if (chunkInfo.getNumberOfChunks() == 0) {
            CINode ciNode = new CINode();
            ciNode.setLabel("");
            ciNode.setCIs(cis);
            CINodes ciNodes = new CINodes();
            ciNodes.addCINode(ciNode);
            topologyMap.setCINodes(ciNodes);
        } else {

            for (int i = 1; i <= chunkInfo.getNumberOfChunks(); i++) {
                ChunkRequest chunkRequest =
                        new ChunkRequest();
                chunkRequest.setChunkInfo(chunkInfo);
                chunkRequest.setChunkNumber(i);
                PullTopologyMapChunks req =
                        new PullTopologyMapChunks();
                req.setChunkRequest(chunkRequest);
                req.setCmdbContext(context);
                PullTopologyMapChunksE reqE = new PullTopologyMapChunksE();
                reqE.setPullTopologyMapChunks(req);

                PullTopologyMapChunksResponse res;
                PullTopologyMapChunksResponseE resE = null;
                try {
                    resE = serviceStub.pullTopologyMapChunks(reqE);
                } catch (RemoteException e) {
                    //handle exception
                } catch (UcmdbFault e) {
                    //handle exception
                }
                assert resE != null;
                res = resE.getPullTopologyMapChunksResponse();
                topologyMap = res.getTopologyMap();
            }

            //release chunks
            ReleaseChunks req = new ReleaseChunks();
            req.setChunksKey(chunkInfo.getChunksKey());
            req.setCmdbContext(context);
            ReleaseChunksE reqE = new ReleaseChunksE();
            reqE.setReleaseChunks(req);
            try {
                serviceStub.releaseChunks(reqE);
            } catch (RemoteException e) {
                //handle exception
            } catch (UcmdbFault e) {
                //handle exception
            }
        }
        return topologyMap;
    }
}