public List<IAppField> GetAppFields(app app)
        {
            IApp apphandle = GetAppHandle(app.ID);
            List<IAppField> appfields = AppExtensions.GetAppFields(apphandle).ToList();

            return appfields;
        }
        public List<string> GetFieldValues(app app, IAppField appField2)
        {
            List<string> strValues = new List<string>();

            Uri uri = new Uri(url + ":443");
            ILocation remoteQlikSenseLocation = Qlik.Engine.Location.FromUri(uri);
            remoteQlikSenseLocation.AsNtlmUserViaProxy();

            IAppIdentifier appidentifier = remoteQlikSenseLocation.AppWithId(app.ID);
            using (var doc = remoteQlikSenseLocation.App(appidentifier))
            {
                var field = doc.GetAppField(appField2.DimensionInfo.FallbackTitle);

                var p = new List<NxPage> { new NxPage { Height = 20, Width = 1 } };
                var dataPages = field.GetData(p);
                foreach (var dataPage in dataPages)
                {
                    var matrix = dataPage.Matrix;
                    foreach (var cellRows in matrix)
                    {
                        foreach (var cellRow in cellRows)
                        {
                            strValues.Add(cellRow.Text);
                            //Console.WriteLine("## " + cellRow.Text + " - " + cellRow.State);
                        }
                    }
                }

            }
            return strValues;
        }
        public string CopyAndModifyApp(string appid, string name, CustomProperty LoopProperty, string loopvalue, string script)
        {
            Dictionary<string, string> queries = new Dictionary<string, string>();
            queries.Add("name", name);
            string copyresult = qrsClient.Post("/qrs/app/" + appid + "/copy", "", queries);

            app newapp = (app)JsonConvert.DeserializeObject<app>(copyresult);

            //Sleep for 1 second, then GET the app again (handles updates to modified date during copy)
            Thread.Sleep(1000);
            newapp = (app)JsonConvert.DeserializeObject<app>(qrsClient.Get("/qrs/app/" + newapp.ID));

            //Apply tag & custom property
            newapp.tags.Add(addTag("generated by LR"));

            CustomPropertyApplied newcp = new CustomPropertyApplied();
            newcp.value = loopvalue;
            newcp.definition = LoopProperty;

            newapp.customproperties = new List<CustomPropertyApplied>();
            newapp.customproperties.Add(newcp);

            //update it
            qrsClient.Put("/qrs/app/" + newapp.ID, JsonConvert.SerializeObject(newapp, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }));

            //now modify its script
            SetLoopAndReduceScript(newapp.ID, loopvalue, script);

            return newapp.ID;
        }
        public bool LoopAndReduce(app sourceapp, stream stream, string script, List<string> LoopValues)
        {
            //create as custom property with the values
            CustomProperty LoopProperty = qs.addCustomProperty("LoopValueForApp" + sourceapp.name, LoopValues);

            List<Newapp> newapps = new List<Newapp>();

            //PHASE 1:   Make app Copies

            for (int i = 0; i < LoopValues.Count; i++)
            {
                Newapp newapp = new Newapp();
                newapp.newappname = sourceapp.name + "_" + LoopValues[i];

                //first see if this app exists and get its info
                app target = qs.GetApp(newapp.newappname);
                if(target != null)
                    newapp.oldappid = target.ID;

                //now copy
                newapp.newappid = qs.CopyAndModifyApp(sourceapp.ID, newapp.newappname, LoopProperty, LoopValues[i], script);

                //keep it for later
                newapps.Add(newapp);
            }

            //PHASE 2:   Reload the apps by creating a reload task, (Check if the apps have already been published to the stream in which case just start its task)

            foreach (Newapp newapp in newapps)
            {
                string taskID;
                taskID = qs.CreateTask(newapp.newappid, newapp.newappname, "Reload of : " + newapp.newappname);
                string executionID;
                executionID = qs.StartTask(taskID);

                newapp.taskid = taskID;
                newapp.executionid = executionID;

            }

            //Phase 2a:  Wait for reloads to complete

            // loop through each app, and wait on each loop until the reload completes checking every 3 seconds
            foreach (Newapp newapp in newapps)
            {
                int appreloadstatus = qs.checkprogress(newapp.executionid);
                int reloadtimeout = 15;
                int statuscheckcount = 0;

                while (appreloadstatus != 7 && statuscheckcount < reloadtimeout)
                {
                    Thread.Sleep(3000);
                    appreloadstatus = qs.checkprogress(newapp.executionid);
                    statuscheckcount += 1;
                }

                if(appreloadstatus==7)
                {
                    newapp.reloadok = true;
                }
                else
                {
                    newapp.reloadok = false;
                }
            }
            //once the code gets here all tasks have completed

            //PHASE 3:   Publish the apps (or replace if they exist

            foreach (Newapp newapp in newapps)
            {
                if (newapp.oldappid != null)
                {
                    //if the app is already published then replace it
                    qs.Replace(newapp.newappid, newapp.oldappid);
                    //remove the un-needed copy and the task we no longer need
                    qs.Delete(newapp.newappid);
                }
                else
                {
                    //if the app is not already published then publish it
                    qs.Publish(newapp.newappid, stream.ID);
                }
            }

            return true;
        }
        public bool LoopAndReduce(app sourceapp, stream stream, string script, List <string> LoopValues)
        {
            //create as custom property with the values
            CustomProperty LoopProperty = qs.addCustomProperty("LoopValueForApp" + sourceapp.name, LoopValues);

            List <Newapp> newapps = new List <Newapp>();

            //PHASE 1:   Make app Copies

            for (int i = 0; i < LoopValues.Count; i++)
            {
                Newapp newapp = new Newapp();
                newapp.newappname = sourceapp.name + "_" + LoopValues[i];

                //first see if this app exists and get its info
                app target = qs.GetApp(newapp.newappname);
                if (target != null)
                {
                    newapp.oldappid = target.ID;
                }

                //now copy
                newapp.newappid = qs.CopyAndModifyApp(sourceapp.ID, newapp.newappname, LoopProperty, LoopValues[i], script);

                //keep it for later
                newapps.Add(newapp);
            }

            //PHASE 2:   Reload the apps by creating a reload task, (Check if the apps have already been published to the stream in which case just start its task)

            foreach (Newapp newapp in newapps)
            {
                string taskID;
                taskID = qs.CreateTask(newapp.newappid, newapp.newappname, "Reload of : " + newapp.newappname);
                string executionID;
                executionID = qs.StartTask(taskID);

                newapp.taskid      = taskID;
                newapp.executionid = executionID;
            }


            //Phase 2a:  Wait for reloads to complete

            // loop through each app, and wait on each loop until the reload completes checking every 3 seconds
            foreach (Newapp newapp in newapps)
            {
                int appreloadstatus  = qs.checkprogress(newapp.executionid);
                int reloadtimeout    = 15;
                int statuscheckcount = 0;

                while (appreloadstatus != 7 && statuscheckcount < reloadtimeout)
                {
                    Thread.Sleep(3000);
                    appreloadstatus   = qs.checkprogress(newapp.executionid);
                    statuscheckcount += 1;
                }

                if (appreloadstatus == 7)
                {
                    newapp.reloadok = true;
                }
                else
                {
                    newapp.reloadok = false;
                }
            }
            //once the code gets here all tasks have completed

            //PHASE 3:   Publish the apps (or replace if they exist

            foreach (Newapp newapp in newapps)
            {
                if (newapp.oldappid != null)
                {
                    //if the app is already published then replace it
                    qs.Replace(newapp.newappid, newapp.oldappid);
                    //remove the un-needed copy and the task we no longer need
                    qs.Delete(newapp.newappid);
                }
                else
                {
                    //if the app is not already published then publish it
                    qs.Publish(newapp.newappid, stream.ID);
                }
            }


            return(true);
        }