Skip to content

Commit

Permalink
Fix issue #99
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Otykier committed Oct 10, 2017
1 parent ad9cd2e commit ef66314
Show file tree
Hide file tree
Showing 15 changed files with 303 additions and 225 deletions.
1 change: 1 addition & 0 deletions TOMWrapper/TOMWrapper.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="TOMWrapper\NamedExpression.cs" />
<Compile Include="TOMWrapper\TabularModelHandlerSettings.cs" />
<Compile Include="IPlugin.cs" />
<Compile Include="Messages.Designer.cs">
Expand Down
11 changes: 9 additions & 2 deletions TOMWrapper/TOMWrapper/Base/Rules.ttinclude
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ class Rules {
case "IsHidden":
case "Description":
return "Basic";
case "Kind":
case "Expression":
case "SortByColumn":
case "FormatString":
Expand Down Expand Up @@ -301,6 +302,7 @@ class Rules {
if(propertyName == "Perspectives") return "[Editor(typeof(TabularEditor.PropertyGridUI.ClonableObjectCollectionEditor<Perspective>),typeof(UITypeEditor)),TypeConverter(typeof(StringConverter))]";
if(propertyName == "Cultures") return "[Editor(typeof(TabularEditor.PropertyGridUI.CultureCollectionEditor),typeof(UITypeEditor)),TypeConverter(typeof(StringConverter))]";
if(propertyName == "Roles") return "[Editor(typeof(TabularEditor.PropertyGridUI.ClonableObjectCollectionEditor<ModelRole>), typeof(UITypeEditor)), TypeConverter(typeof(StringConverter))]";
if(propertyName == "Expressions") return "[Editor(typeof(TabularEditor.PropertyGridUI.ClonableObjectCollectionEditor<NamedExpression>), typeof(UITypeEditor)), TypeConverter(typeof(StringConverter))]";
if(propertyName == "Partitions") return "[NoMultiselect(),Editor(typeof(PartitionCollectionEditor),typeof(UITypeEditor))]";
if(propertyName == "Variations") return "[NoMultiselect(),Editor(typeof(VariationCollectionEditor),typeof(UITypeEditor))]";

Expand All @@ -319,6 +321,7 @@ class Rules {
}

private static readonly string[] _enumTypes = new[] {
"ExpressionKind",
"DataSourceType",
"PartitionSourceType",
"DataType",
Expand Down Expand Up @@ -398,7 +401,8 @@ class Rules {
{ "Relationship", "TabularNamedObject" },
{ "SingleColumnRelationship", "Relationship" },
{ "Table", "TabularNamedObject" },
{ "WindowsModelRoleMember", "ModelRoleMember" }
{ "WindowsModelRoleMember", "ModelRoleMember" },
{ "NamedExpression", "TabularNamedObject" }
};
public static Dictionary<Type, string> ObjectTypes = Convert(_objectTypes).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

Expand All @@ -418,7 +422,8 @@ class Rules {
{ "Culture", "Cultures" },
{ "Relationship", "Relationships" },
{ "DataSource", "DataSources" },
{ "Variation", "Variations" }
{ "Variation", "Variations" },
{ "NamedExpression", "Expressions" }
};
public static Dictionary<Type, string> Collections = Convert(_objectCollections).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

Expand All @@ -427,6 +432,7 @@ class Rules {
case "ModelRole": return "Roles";
case "ModelRoleMember": return "Members";
case "Hierarchy": return "Hierarchies";
case "NamedExpression": return "Expressions";
default: return itemType.Name + "s";
}
}
Expand All @@ -440,6 +446,7 @@ class Rules {
{ new KeyValuePair<string, string>("ModelRole", "Model") },
{ new KeyValuePair<string, string>("Table", "Model") },
{ new KeyValuePair<string, string>("Relationship", "Model") },
{ new KeyValuePair<string, string>("NamedExpression", "Model") },

// Collections owned by a Table (order of items matters, as this is the order in which child objects will be initialized):
{ new KeyValuePair<string, string>("Partition", "Table") },
Expand Down
2 changes: 1 addition & 1 deletion TOMWrapper/TOMWrapper/Base/WrapperBase.tt
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ namespace TabularEditor.TOMWrapper
#><#= props.Any(p => p.Name == "ErrorMessage") ? "\n\t\t\t, IErrorMessageObject" : ""
#><#= props.Any(p => p.Name == "Table") ? "\n\t\t\t, ITabularTableObject" : ""
#><#= props.Any(p => p.Name == "Description") ? "\n\t\t\t, IDescriptionObject" : ""
#><#= props.Any(p => p.Name == "Expression") ? "\n\t\t\t, IDAXExpressionObject" : ""
#><#= props.Any(p => p.Name == "Expression" && t.Name != "NamedExpression") ? "\n\t\t\t, IDAXExpressionObject" : ""
#><#= props.Any(p => p.Name == "FormatString") ? "\n\t\t\t, IFormattableObject" : ""
#><#= props.Any(p => p.Name == "Annotations") ? "\n\t\t\t, IAnnotationObject" : ""
#><#= Rules.IsPerspectiveObject(t) ? "\n\t\t\t, ITabularPerspectiveObject" : ""
Expand Down
61 changes: 32 additions & 29 deletions TOMWrapper/TOMWrapper/LogicalGroup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,34 @@ public class LogicalGroups: IEnumerable<LogicalGroup>
{
public static readonly LogicalGroups Singleton = new LogicalGroups();

public readonly LogicalGroup Tables = new LogicalGroup("Tables");
public readonly LogicalGroup DataSources = new LogicalGroup("Data Sources");
public readonly LogicalGroup Perspectives = new LogicalGroup("Perspectives");
public readonly LogicalGroup Relationships = new LogicalGroup("Relationships");
public readonly LogicalGroup Translations = new LogicalGroup("Translations");
public readonly LogicalGroup Roles = new LogicalGroup("Roles");
public readonly LogicalGroup Partitions = new LogicalGroup("Table Partitions");
public const string TABLES = "Tables";
public const string ROLES = "Roles";
public const string PERSPECTIVES = "Perspectives";
public const string TRANSLATIONS = "Translations";
public const string RELATIONSHIPS = "Relationships";
public const string DATASOURCES = "Data Sources";
public const string TABLEPARTITIONS = "Table Partitions";
public const string EXPRESSIONS = "Shared Expressions";

public readonly LogicalGroup DataSources = new LogicalGroup(DATASOURCES);
public readonly LogicalGroup Perspectives = new LogicalGroup(PERSPECTIVES);
public readonly LogicalGroup Relationships = new LogicalGroup(RELATIONSHIPS);
public readonly LogicalGroup Roles = new LogicalGroup(ROLES);
public readonly LogicalGroup Expressions = new LogicalGroup(EXPRESSIONS);
public readonly LogicalGroup Partitions = new LogicalGroup(TABLEPARTITIONS);
public readonly LogicalGroup Tables = new LogicalGroup(TABLES);
public readonly LogicalGroup Translations = new LogicalGroup(TRANSLATIONS);

private IEnumerable<LogicalGroup> Groups()
{
yield return Tables;
yield return Partitions;
yield return DataSources;
yield return Perspectives;
yield return Relationships;
yield return Translations;
yield return Roles;
if(TabularModelHandler.Singleton.Database.CompatibilityLevel >= 1400) yield return Expressions;
yield return Partitions;
yield return Tables;
yield return Translations;
}

public IEnumerator<LogicalGroup> GetEnumerator()
Expand All @@ -52,15 +63,6 @@ IEnumerator IEnumerable.GetEnumerator()
public class LogicalGroup: ITabularNamedObject, ITabularObjectContainer, IDynamicPropertyObject
{


public const string TABLES = "Tables";
public const string ROLES = "Roles";
public const string PERSPECTIVES = "Perspectives";
public const string TRANSLATIONS = "Translations";
public const string RELATIONSHIPS = "Relationships";
public const string DATASOURCES = "Data Sources";
public const string TABLEPARTITIONS = "Table Partitions";

[ReadOnly(true)]
public string Name { get; set; }
public TranslationIndexer TranslatedNames { get { return null; } }
Expand All @@ -72,13 +74,14 @@ public IEnumerable<ITabularNamedObject> GetChildren()
{
switch (Name)
{
case TABLES: return Model.Tables;
case ROLES: return Model.Roles;
case PERSPECTIVES: return Model.Perspectives;
case TRANSLATIONS: return Model.Cultures;
case RELATIONSHIPS: return Model.Relationships;
case DATASOURCES: return Model.DataSources;
case TABLEPARTITIONS: return Model.Tables.Where(t => !(t is CalculatedTable)).Select(t => t.PartitionViewTable);
case LogicalGroups.TABLES: return Model.Tables;
case LogicalGroups.ROLES: return Model.Roles;
case LogicalGroups.EXPRESSIONS: return Model.Expressions;
case LogicalGroups.PERSPECTIVES: return Model.Perspectives;
case LogicalGroups.TRANSLATIONS: return Model.Cultures;
case LogicalGroups.RELATIONSHIPS: return Model.Relationships;
case LogicalGroups.DATASOURCES: return Model.DataSources;
case LogicalGroups.TABLEPARTITIONS: return Model.Tables.Where(t => !(t is CalculatedTable)).Select(t => t.PartitionViewTable);
}
return Enumerable.Empty<TabularNamedObject>();
}
Expand Down Expand Up @@ -114,9 +117,9 @@ public bool Browsable(string propertyName)
{
switch(Name)
{
case PERSPECTIVES: return propertyName == "Perspectives";
case TRANSLATIONS: return propertyName == "Cultures";
case ROLES: return propertyName == "Roles";
case LogicalGroups.PERSPECTIVES: return propertyName == "Perspectives";
case LogicalGroups.TRANSLATIONS: return propertyName == "Cultures";
case LogicalGroups.ROLES: return propertyName == "Roles";
default:
return propertyName == "Name"; // For all other groups, only show the name.
}
Expand Down
22 changes: 17 additions & 5 deletions TOMWrapper/TOMWrapper/Model.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,26 @@ partial class Model: ITabularObjectContainer
public Perspective AddPerspective(string name = null)
{
#if CL1400
if (Handler.UsePowerBIGovernance && !PowerBI.PowerBIGovernance.AllowCreate(typeof(DataColumn))) return null;
if (Handler.UsePowerBIGovernance && !PowerBI.PowerBIGovernance.AllowCreate(typeof(Perspective))) return null;
#endif
Handler.BeginUpdate("add perspective");
var perspective = Perspective.CreateNew(this, name);
Handler.EndUpdate();
return perspective;
}

[IntelliSense("Adds a new Named Expression to the model.")]
public NamedExpression AddExpression(string name = null, string expression = null)
{
#if CL1400
if (Handler.UsePowerBIGovernance && !PowerBI.PowerBIGovernance.AllowCreate(typeof(NamedExpression))) return null;
#endif
Handler.BeginUpdate("add shared expression");
var expr = NamedExpression.CreateNew(this, name);
Handler.EndUpdate();
return expr;
}

[IntelliSense("Adds a new calculated table to the model.")]
public CalculatedTable AddCalculatedTable(string name = null, string expression = null)
{
Expand All @@ -40,7 +52,7 @@ public CalculatedTable AddCalculatedTable(string name = null, string expression
public Table AddTable(string name = null)
{
#if CL1400
if (Handler.UsePowerBIGovernance && !PowerBI.PowerBIGovernance.AllowCreate(typeof(DataColumn))) return null;
if (Handler.UsePowerBIGovernance && !PowerBI.PowerBIGovernance.AllowCreate(typeof(Table))) return null;
#endif
Handler.BeginUpdate("add table");
var t = Table.CreateNew(this, name);
Expand All @@ -63,7 +75,7 @@ public SingleColumnRelationship AddRelationship()
public Culture AddTranslation(string cultureId)
{
#if CL1400
if (Handler.UsePowerBIGovernance && !PowerBI.PowerBIGovernance.AllowCreate(typeof(DataColumn))) return null;
if (Handler.UsePowerBIGovernance && !PowerBI.PowerBIGovernance.AllowCreate(typeof(Culture))) return null;
#endif
Handler.BeginUpdate("add translation");
var culture = TOMWrapper.Culture.CreateNew(cultureId);
Expand All @@ -86,7 +98,7 @@ public ModelRole AddRole(string name = null)
public ProviderDataSource AddDataSource(string name = null)
{
#if CL1400
if (Handler.UsePowerBIGovernance && !PowerBI.PowerBIGovernance.AllowCreate(typeof(DataSource))) return null;
if (Handler.UsePowerBIGovernance && !PowerBI.PowerBIGovernance.AllowCreate(typeof(ProviderDataSource))) return null;
#endif
Handler.BeginUpdate("add data source");

Expand All @@ -99,7 +111,7 @@ public ProviderDataSource AddDataSource(string name = null)
[IntelliSense("Adds a new strucured data source to the model.")]
public StructuredDataSource AddStructuredDataSource(string name = null)
{
if (Handler.UsePowerBIGovernance && !PowerBI.PowerBIGovernance.AllowCreate(typeof(DataColumn))) return null;
if (Handler.UsePowerBIGovernance && !PowerBI.PowerBIGovernance.AllowCreate(typeof(StructuredDataSource))) return null;

Handler.BeginUpdate("add data source");
var ds = StructuredDataSource.CreateNew(this, name);
Expand Down
13 changes: 13 additions & 0 deletions TOMWrapper/TOMWrapper/NamedExpression.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TabularEditor.TOMWrapper
{
public partial class NamedExpression: IExpressionObject
{

}
}
10 changes: 7 additions & 3 deletions TOMWrapper/TOMWrapper/PowerBI/PowerBIGovernance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ public static bool AllowGroup(string groupName)
{
switch(groupName)
{
case LogicalGroup.RELATIONSHIPS:
case LogicalGroup.ROLES:
case LogicalGroup.TABLES:
case LogicalGroups.RELATIONSHIPS:
case LogicalGroups.ROLES:
case LogicalGroups.TABLES:
case LogicalGroups.EXPRESSIONS:
return true;

//case LogicalGroup.DATASOURCES:
Expand All @@ -72,6 +73,9 @@ public static bool AllowProperty(ObjectType type, string property)
case Properties.SOURCEPROVIDERTYPE:
case Properties.CULTURES:
return false;
case Properties.EXPRESSION:
// Only allow editing Expressions for Measures, Calc Columns and Calc Tables:
return type == ObjectType.Measure || type == ObjectType.Table || type == ObjectType.Column;
}

return true;
Expand Down
1 change: 1 addition & 0 deletions TOMWrapper/TOMWrapper/TabularCommonActions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ public List<TabularObject> InsertObjects(ObjectJsonContainer objectContainer, IT
foreach (var obj in objectContainer[typeof(CalculatedTable)]) inserted.Add(Serializer.DeserializeCalculatedTable(obj, Handler.Model));
foreach (var obj in objectContainer[typeof(Table)]) inserted.Add(Serializer.DeserializeTable(obj, Handler.Model));

foreach (var obj in objectContainer[typeof(NamedExpression)]) inserted.Add(Serializer.DeserializeNamedExpression(obj, Handler.Model));
foreach (var obj in objectContainer[typeof(ModelRole)]) inserted.Add(Serializer.DeserializeModelRole(obj, Handler.Model));
foreach (var obj in objectContainer[typeof(ProviderDataSource)]) inserted.Add(Serializer.DeserializeProviderDataSource(obj, Handler.Model));
foreach (var obj in objectContainer[typeof(SingleColumnRelationship)]) inserted.Add(Serializer.DeserializeSingleColumnRelationship(obj, Handler.Model));
Expand Down
11 changes: 11 additions & 0 deletions TOMWrapper/Utils/Serializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,17 @@ public static SingleColumnRelationship DeserializeSingleColumnRelationship(JObje
return relationship;
}

public static NamedExpression DeserializeNamedExpression(JObject json, Model model)
{
var tom = TOM.JsonSerializer.DeserializeObject<TOM.NamedExpression>(json.ToString());
tom.Name = model.Expressions.GetNewName(tom.Name);

var expr = NamedExpression.CreateFromMetadata(tom, false);
model.Expressions.Add(expr);
expr.InitFromMetadata();

return expr;
}
public static ModelRole DeserializeModelRole(JObject json, Model model)
{
var tom = TOM.JsonSerializer.DeserializeObject<TOM.ModelRole>(json.ToString());
Expand Down
3 changes: 3 additions & 0 deletions TabularEditor/BestPracticeAnalyzer/BestPracticeRule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ public class BestPracticeRule

[JsonConverter(typeof(RuleScopeConverter))]
public RuleScope Scope { get; set; }

[JsonIgnore]
public string ScopeString
{
get {
Expand All @@ -133,6 +135,7 @@ public string ScopeString
public string FixExpression { get; set; }
public HashSet<int> Compatibility { get; set; }

[JsonIgnore]
public bool IsValid { get; }
}

Expand Down
Loading

0 comments on commit ef66314

Please sign in to comment.