Skip to content

Commit

Permalink
First commit: Added following examples
Browse files Browse the repository at this point in the history
AbstractStructure, AppPreload, AppTraverser, ConnectDesktop, CustomDesktop
  • Loading branch information
Arbon Vata committed Apr 5, 2016
0 parents commit 26c2637
Show file tree
Hide file tree
Showing 49 changed files with 2,689 additions and 0 deletions.
76 changes: 76 additions & 0 deletions AbstractStructure/AbstractStructure.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{25BEE9B7-4244-4ED6-9935-361CF17D0880}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AbstractStructure</RootNamespace>
<AssemblyName>AbstractStructure</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Autofac, Version=3.5.0.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>packages\Autofac.3.5.2\lib\net40\Autofac.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Qlik.Engine, Version=2.1.1.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>packages\QlikSense.NetSDK.2.1.1.0\lib\net452\Qlik.Engine.dll</HintPath>
</Reference>
<Reference Include="Qlik.Sense.Client, Version=2.1.1.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>packages\QlikSense.NetSDK.2.1.1.0\lib\net452\Qlik.Sense.Client.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
22 changes: 22 additions & 0 deletions AbstractStructure/AbstractStructure.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AbstractStructure", "AbstractStructure.csproj", "{25BEE9B7-4244-4ED6-9935-361CF17D0880}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{25BEE9B7-4244-4ED6-9935-361CF17D0880}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{25BEE9B7-4244-4ED6-9935-361CF17D0880}.Debug|Any CPU.Build.0 = Debug|Any CPU
{25BEE9B7-4244-4ED6-9935-361CF17D0880}.Release|Any CPU.ActiveCfg = Release|Any CPU
{25BEE9B7-4244-4ED6-9935-361CF17D0880}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
6 changes: 6 additions & 0 deletions AbstractStructure/App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/>
</startup>
</configuration>
288 changes: 288 additions & 0 deletions AbstractStructure/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,288 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Qlik.Engine;
using Qlik.Engine.Communication;
using Qlik.Sense.Client;
using Qlik.Sense.Client.Visualizations;
using Qlik.Sense.Client.Visualizations.MapComponents;

namespace AbstractStructure
{
/// <summary>
/// This example illustrates the concept of abstract structures as used by the Qlik Sense SDK.
/// More information about the topic of abstract structures can be found on the developer help site at
/// http://help.qlik.com, Building applications with the .NET SDK -> Working with Qlik Sense .NET SDK
/// -> Abstract structure.
/// </summary>
class Program
{
static void Main(string[] args)
{
BasicAbstractStructureUsage();

var location = ConnectToDesktop();
var allApps = OpenAllApps(location).ToArray();
if (allApps.Any())
{
UseAbstractStructureOnMasterObjects(allApps);
UseAbstractStructureOnMapLayers(allApps);
}
Console.WriteLine("Press enter to close.");
Console.ReadLine();
}

private static void BasicAbstractStructureUsage()
{
Console.WriteLine("******************************************");
Console.WriteLine("** Part 1) Basic abstract structure usage");
Console.WriteLine("******************************************");
// Create new instances of the classes A and B.
var a = new A { N = 1 };
var b = new B { S = "Hello" };
// Print the names of all properties found in the two objects.
Console.WriteLine("Properties in object a: {0}", String.Join(", ", a.GetAllProperties()));
Console.WriteLine("Properties in object b: {0}", String.Join(", ", b.GetAllProperties()));

// Interpret "a" as being of class B.
var ab = a.As<B>();

// Print the names of all properties found in object "ab". Notice that the property "n" is visible in
// "ab" even though it is not of type A. "n" is available as a dynamic property in "ab". Notice also
// that "ab" does not contain a property called "s". Accessing S at this point will simply return null.
Console.WriteLine("Properties in object ab: {0}", String.Join(", ", ab.GetAllProperties()));

// Add a dynamic property to "a". The property immediately becomes visible in "ab".
a.Set("s", "Hello from A");
Console.WriteLine("Properties in object ab after modifying dynamic property \"s\" in a: {0}", String.Join(", ", ab.GetAllProperties()));

// The dynamic property "s" written to "a" is the same as the one wrapped by the property S of
// class B. It can therefore be accessed through the property S when interpreting "a" as being of
// class B.
Console.WriteLine("This is the text written to object interpreted as B: {0}", ab.S);

// Changes to S in B will also immediately become visible for the dynamic property "s" for object "a".
ab.S = "Hello from B";
Console.WriteLine("This is the text written to property S for class B: {0}", ab.S);
Console.WriteLine("This is the same text accessed through dynamic property \"s\" for class A: {0}", a.Get<string>("s"));
}

// A class containing a number.
class A : Qlik.Engine.AbstractStructure
{
// Wrapper for a dynamic property named "n".
public int N
{
get { return Get<int>("n"); }
set { Set("n", value); }
}
}

// A class containing a string.
class B : Qlik.Engine.AbstractStructure
{
// Wrapper for a dynamic property named "s".
public string S
{
get { return Get<string>("s"); }
set { Set("s", value); }
}
}

// Master objects are used when it is desirable to add the same object multiple times
// to the same app. A typical scenario would be that a certain visualization should be
// available on multiple sheets.
//
// Master objects have a dedicated type, but the properties for those object will depend
// on the type of the object that they are containers for. A master object created for a
// barchart will for instance have properties of a barchart, while a master object created
// for a line chart will have line chart properties. The type of the C# representation of
// master objects does therefore not represent directly the type of the properties associate
// with those objects.
//
// This example illustrates how the concept of abstract structure can be applied to interact
// with master object properties.
private static void UseAbstractStructureOnMasterObjects(IEnumerable<IApp> apps)
{
Console.WriteLine("****************************************************************");
Console.WriteLine("** Part 2) Use of abstract structure to handle master objects.");
Console.WriteLine("****************************************************************");
// Get all master objects for all apps and process them using abstract structure.
var allMasterObjects = GetAllMasterObjects(apps);
allMasterObjects.ToList().ForEach(ProcessMasterObject);
}

private static void ProcessMasterObject(IMasterObject masterObject)
{
var properties = masterObject.Properties;

// Check if the master object represents a visualization (i.e. has a property called "visualization").
if (properties.Get<string>("visualization") != null)
{
Console.WriteLine("Master object seems to represent a Qlik Sense client visualization.");

// Interpret properties as being of type VisualizationBaseProperties.
var visualizationBaseProperties = properties.As<VisualizationBaseProperties>();

// Check if the visualization represents a bar chart and print information accordingly.
if (visualizationBaseProperties.Visualization == "barchart")
{
Console.WriteLine("Master object with id {0} is a barchart.", properties.Info.Id);
var barchartProperties = visualizationBaseProperties.As<BarchartProperties>();
var barGrouping = barchartProperties.BarGrouping.Grouping;
Console.WriteLine(" BarGrouping is set to: " + barGrouping);
}
else
Console.WriteLine("Master object with id {0} is not a bar chart. It is a {1}.", properties.Info.Id,
visualizationBaseProperties.Visualization);

// Print the title of the master object.
Console.WriteLine(" Title is: \"{0}\"", visualizationBaseProperties.Title);
}
else
{
Console.WriteLine("The master object does not represent a Qlik Sense client visualization.");
}

// Treat the object as a generic hypercube container and access the HyperCubeDef if it exists.
var hyperCubeContainer = properties.As<HyperCubeContainer>();
if (hyperCubeContainer.ContainsHyperCube)
ProcessHyperCubeDef(hyperCubeContainer.HyperCubeDef);
else
Console.WriteLine(" Object has no hypercube.");
}

// A class that contains a hypercube definition.
class HyperCubeContainer : Qlik.Engine.AbstractStructure
{
public IHyperCubeDef HyperCubeDef { get { return Get<HyperCubeDef>("qHyperCubeDef"); } }
public bool ContainsHyperCube { get { return HyperCubeDef != null; } }
}

/// <summary>
/// Print information details of a hypercube definition.
/// </summary>
/// <param name="hyperCubeDef">The hypercube definition to process.</param>
private static void ProcessHyperCubeDef(IHyperCubeDef hyperCubeDef)
{
// Process dimensions
Console.WriteLine(" Number of dimensions: {0}", hyperCubeDef.Dimensions.Count());
var dimensionCount = 0;
foreach (var dimension in hyperCubeDef.Dimensions)
{
Console.Write(" Dimension #{0}: ", dimensionCount++);
if (dimension.LibraryId != null)
Console.WriteLine("Library dimension - {0}", dimension.LibraryId);
else
Console.WriteLine("Inline dimension - {0}", dimension.Def.FieldDefs.First());
}

// Process measures
Console.WriteLine(" Number of measures: {0}", hyperCubeDef.Measures.Count());
var measureCount = 0;
foreach (var measure in hyperCubeDef.Measures)
{
Console.Write(" Measure #{0}: ", measureCount++);
if (measure.LibraryId != null)
Console.WriteLine("Library measure - {0}", measure.LibraryId);
else
Console.WriteLine("Inline measure - {0}", measure.Def.Def);
}
}

private static ILocation ConnectToDesktop()
{
var location = Location.FromUri(new Uri("ws://127.0.0.1:4848"));
location.AsDirectConnectionToPersonalEdition();
return location;
}

private static IEnumerable<IApp> OpenAllApps(ILocation location)
{
try
{
return location.GetAppIdentifiers().Select(x => location.App(x));
}
catch (CommunicationErrorException e)
{
Console.WriteLine("Communication error exception, no Qlik Sense instance found!");
return new IApp[] { };
}
}

private static IEnumerable<IMasterObject> GetAllMasterObjects(IEnumerable<IApp> apps)
{
return apps.SelectMany(GetAllMasterObjects);
}

private static IEnumerable<IMasterObject> GetAllMasterObjects(IApp app)
{
return app.GetMasterObjectList().Items.Select(item => app.GetObject<MasterObject>(item.Info.Id));
}

// The Map visualization of the Qlik.Sense.Client namespace has a concept of layers.
// A map layer contains at least one hypercube used to display information in that layer,
// which makes it possible to display multiple sets of information in the same map. A polygon
// layer can for instance color the polygons according to population density of countries, while
// a point layer might have sizes related to the population size of cities.
//
// This example illustrates how the concept of abstract structure can be applied to interact
// with different types of map layers.
private static void UseAbstractStructureOnMapLayers(IEnumerable<IApp> apps)
{
Console.WriteLine("************************************************************");
Console.WriteLine("** Part 3) Use of abstract structure to handle map layers.");
Console.WriteLine("************************************************************");
// Get all map objects for all apps and process the layers using abstract structure.
var allMaps = apps.SelectMany(GetAllMapObjects);
allMaps.ToList().ForEach(ProcessMap);
}

private static IEnumerable<IMap> GetAllMapObjects(IApp app)
{
return app.GetSheets().
SelectMany(sheet => sheet.GetChildInfos()).
Select(info => app.GetObject<GenericObject>(info.Id)).
OfType<Map>();
}

private static void ProcessMap(IMap map)
{
Console.WriteLine("Processing map with id {0}, and title \"{1}\"", map.Info.Id, map.Title);
Console.WriteLine(" The map has {0} layers.", map.Layers.Count());
var layerCount = 0;
foreach (var layer in map.Properties.Layers)
{
Console.WriteLine( "Layer #{0} is of type {1}", layerCount++, layer.Type);
switch (layer.Type)
{
case LayerType.Point:
// Interpret layer as a point layer.
ProcessPointLayer(layer.As<PointLayerDef>());
break;
case LayerType.Polygon:
// Interpret layer as a polygon layer.
ProcessPolygonLayer(layer.As<Polygon3LayerDef>());
break;
}
}
}

private static void ProcessPointLayer(IPointLayerDef layer)
{
Console.WriteLine(" PointLayer hypercube has {0} dimensions.", layer.HyperCubeDef.Dimensions.Count());
}

private static void ProcessPolygonLayer(IPolygon3LayerDef layer)
{
if (layer.HyperCubeDef != null)
Console.WriteLine(" PolygonLayer hypercube has {0} dimensions.", layer.HyperCubeDef.Dimensions.Count());
else
Console.WriteLine(" PolygonLayer has no hypercube.");
if (layer.Geodata != null)
Console.WriteLine(" PolygonLayer geodata hypercube has {0} dimensions.", layer.Geodata.HyperCubeDef.Dimensions.Count());
else
Console.WriteLine(" PolygonLayer has no geodata.");
}
}
}
Loading

0 comments on commit 26c2637

Please sign in to comment.