Skip to content

Commit

Permalink
Update to Code Gen
Browse files Browse the repository at this point in the history
Added additional model properties to reflect changes in the Core
  • Loading branch information
Josh Einhorn committed Feb 12, 2015
1 parent 1545db9 commit 1d335a9
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 34 deletions.
32 changes: 29 additions & 3 deletions DVM4T.Core/Attributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public override object GetPropertyValue(IViewModel model, Type propertyType, IVi
object result = null;
if (model != null)
{
var fields = IsMetadata ? model.ModelData.MetadataFields : model.ModelData.Fields;
var fields = IsMetadata ? model.ModelData.Metadata : model.ModelData.Content;
if (fields != null && fields.ContainsKey(FieldName))
{
result = this.GetFieldValue(fields[FieldName], propertyType, model.ModelData.ComponentTemplate, builder);
Expand Down Expand Up @@ -114,7 +114,9 @@ public bool IsMetadata
set { isMetadata = value; }
}
}

/// <summary>
/// Base class for Property Attributes using Component Data
/// </summary>
public abstract class ComponentAttributeBase : ModelPropertyAttributeBase, IComponentAttribute
{
public override object GetPropertyValue(IViewModel model, Type propertyType, IViewModelBuilder builder = null)
Expand All @@ -134,6 +136,9 @@ public override object GetPropertyValue(IViewModel model, Type propertyType, IVi
public abstract object GetPropertyValue(IComponentData component, Type propertyType, IComponentTemplateData template, IViewModelBuilder builder = null);
}

/// <summary>
/// Base class for Property Attributes using Component Template Data
/// </summary>
public abstract class ComponentTemplateAttributeBase : ModelPropertyAttributeBase, IComponentTemplateAttribute
{
public abstract object GetPropertyValue(IComponentTemplateData template, Type propertyType, IViewModelBuilder builder = null);
Expand All @@ -150,7 +155,28 @@ public override object GetPropertyValue(IViewModel model, Type propertyType, IVi
}

/// <summary>
/// A View Model.
/// Base class for Property Attributes using Component Template Metadata Fields Data
/// </summary>
public abstract class TemplateMetadataFieldAttributeBase : FieldAttributeBase
{
public TemplateMetadataFieldAttributeBase(string fieldName) : base(fieldName) { }
public override object GetPropertyValue(IViewModel model, Type propertyType, IViewModelBuilder builder = null)
{
object result = null;
if (model != null && model.ModelData != null && model.ModelData.ComponentTemplate != null)
{
var fields = model.ModelData.ComponentTemplate.MetadataFields;
if (fields != null && fields.ContainsKey(FieldName))
{
result = this.GetFieldValue(fields[FieldName], propertyType, model.ModelData.ComponentTemplate, builder);
}
}
return result;
}
}

/// <summary>
/// Attribute for a View Model. Required for DVM4T Framework to build a Model.
/// </summary>
public class ViewModelAttribute : Attribute, IViewModelAttribute
{
Expand Down
2 changes: 2 additions & 0 deletions DVM4T.Core/BaseClasses.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,6 @@ public IViewModelData ModelData
set;
}
}


}
20 changes: 14 additions & 6 deletions DVM4T.Core/Contracts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,10 @@ public interface ICanUseXpm
}
public interface IFieldData : ICanUseXpm, IHaveData
{
//The object Value is the most powerful thing about this entire framework -- this object will be retrieved based on the FieldAttribute's overrided method. Question is, should it be implemented here.
IEnumerable Values { get; } //can/should I do this?
//The object Value is an important part of this framework -- this object will be retrieved based on the FieldAttribute's overriden method. Implementer could alternatively use the BaseData object to circumvent
IEnumerable Values { get; } //should this be object or is it ok as Enumerable?
ISchemaData EmbeddedSchema { get; }
string FieldTypeString { get; } //maybe make an enum?? meh
string FieldTypeString { get; } //maybe make an enum?? This would prescribe the implementation though -- could use object to make it really generic
}
#endregion

Expand All @@ -119,14 +119,14 @@ public interface IViewModel
IViewModelData ModelData { get; set; }
}

public interface IViewModelData //Should this extend IHaveData?
public interface IViewModelData //Should this extend IHaveData? I don't think so at this time because each piece i.e. Content, MetadataFields has their own BaseData object
{
/// <summary>
/// The underlying data object that the View Model represents
/// </summary>
IViewModelBuilder Builder { get; }
IFieldsData Fields { get; }
IFieldsData MetadataFields { get; }
IFieldsData Content { get; }
IFieldsData Metadata { get; }
IComponentTemplateData ComponentTemplate { get; } //we required Component Template here in order to generate Site Edit markup for any linked components in the embedded fields
/// <summary>
/// Publication ID of the underlying Tridion item
Expand All @@ -138,6 +138,14 @@ public interface IComponentPresentationViewModel : IViewModel
{
IComponentPresentationData ComponentPresentation { get; set; }
}

//Consider use cases for this interface -- is it worth separating from ComponentPresentationViewModel?
//Multimedia... could use CP instead, not technically correct but it's close
public interface IComponentViewModel : IViewModel
{
IComponentData Component { get; set; }
}

//TODO: Consider removing this interface, holding on to template is not actually necessary after building is done
public interface IEmbeddedSchemaViewModel : IViewModel
{
Expand Down
12 changes: 6 additions & 6 deletions DVM4T.Core/Core.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,16 @@ public class ViewModelData : IViewModelData
public ViewModelData(IComponentPresentationData cpData, IViewModelBuilder builder)
{
Builder = builder;
Fields = cpData.Component.Fields;
MetadataFields = cpData.Component.MetadataFields;
Content = cpData.Component.Fields;
Metadata = cpData.Component.MetadataFields;
ComponentTemplate = cpData.ComponentTemplate;
PublicationId = cpData.Component.PublicationId;
}
public ViewModelData(IFieldsData fields, IComponentTemplateData template, IViewModelBuilder builder)
{
Builder = builder;
Fields = fields;
MetadataFields = null;
Content = fields;
Metadata = null;
ComponentTemplate = template;
PublicationId = template.PublicationId;
}
Expand All @@ -99,13 +99,13 @@ public IViewModelBuilder Builder
private set;
}

public IFieldsData Fields
public IFieldsData Content
{
get;
private set;
}

public IFieldsData MetadataFields
public IFieldsData Metadata
{
get;
private set;
Expand Down
8 changes: 4 additions & 4 deletions DVM4T.Core/XpmRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public HtmlString XpmEditableField<TProp>(Expression<Func<TModel, TProp>> proper
if (modelProp.PropertyAttribute is IFieldAttribute)
{
var fieldProp = modelProp.PropertyAttribute as IFieldAttribute;
var fields = fieldProp.IsMetadata ? model.ModelData.MetadataFields : model.ModelData.Fields;
var fields = fieldProp.IsMetadata ? model.ModelData.Metadata : model.ModelData.Content;
result = SiteEditable<TProp>(model, fields, modelProp, index);
}
return result;
Expand Down Expand Up @@ -78,7 +78,7 @@ public HtmlString XpmEditableField<TProp, TItem>(Expression<Func<TModel, TProp>>
if (modelProp.PropertyAttribute is IFieldAttribute)
{
var fieldProp = modelProp.PropertyAttribute as IFieldAttribute;
var fields = fieldProp.IsMetadata ? model.ModelData.MetadataFields : model.ModelData.Fields;
var fields = fieldProp.IsMetadata ? model.ModelData.Metadata : model.ModelData.Content;
int index = IndexOf(modelProp, model, item);
result = SiteEditable<TProp>(model, fields, modelProp, index);
}
Expand All @@ -103,7 +103,7 @@ public HtmlString XpmMarkupFor<TProp>(Expression<Func<TModel, TProp>> propertyLa
if (modelProp.PropertyAttribute is IFieldAttribute)
{
var fieldProp = modelProp.PropertyAttribute as IFieldAttribute;
var fields = fieldProp.IsMetadata ? model.ModelData.MetadataFields : model.ModelData.Fields;
var fields = fieldProp.IsMetadata ? model.ModelData.Metadata : model.ModelData.Content;
result = XpmMarkupFor(fields, modelProp, index);
}
}
Expand Down Expand Up @@ -136,7 +136,7 @@ public HtmlString XpmMarkupFor<TProp, TItem>(Expression<Func<TModel, TProp>> pro
if (modelProp.PropertyAttribute is IFieldAttribute)
{
var fieldProp = modelProp.PropertyAttribute as IFieldAttribute;
var fields = fieldProp.IsMetadata ? model.ModelData.MetadataFields : model.ModelData.Fields;
var fields = fieldProp.IsMetadata ? model.ModelData.Metadata : model.ModelData.Content;
int index = IndexOf(modelProp, model, item);
result = XpmMarkupFor(fields, modelProp, index);
}
Expand Down
10 changes: 7 additions & 3 deletions DVM4T.ModelGen/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,19 @@ namespace DVM4T.ModelGen
public interface ICodeGenConfiguration
{
IDictionary<FieldType, IFieldAttributeDef> FieldAttributeTypes { get; }
IDictionary<ModelType, IAttributeDef[]> ModelAttributeTypes { get; }
string[] Namespaces { get; }
string EmbeddedSchemaTypeAttributeParameterName { get; }
string LinkedComponentTypesAttributeParameterName { get; }
}

public interface IFieldAttributeDef
public interface IAttributeDef
{
string Name { get; set; }
string SingleExpectedReturnTypeName { get; set; }
string ReturnTypeName { get; set; }
string DefaultPropertyName { get; set; }
}
public interface IFieldAttributeDef : IAttributeDef
{
string MultiExpectedReturnTypeName { get; set; }
}
}
14 changes: 12 additions & 2 deletions DVM4T.ModelGen/Data Structures.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,27 @@ public ViewModel()
public string Name { get; set; }
public string SchemaName { get; set; }
public IList<FieldProperty> FieldProperties { get; set; }
public IList<PropertyAttribute> OtherProperties { get; set; }
public Type BaseClass { get; set; }
public string ContainingFolder { get; set; }
public ModelType ModelType { get; set; }
}
public enum ModelType
{
ComponentPresentation, MultimediaComponent, EmbeddedSchemaFields
}
public class PropertyAttribute
{
public string Name { get; set; }
public string PropertyName { get; set; }
}

public class FieldProperty
{
public FieldProperty()
{
LinkedComponentTypeNames = new List<string>();
}
public string Name { get; set; }
public string PropertyName { get; set; }
public string FieldName { get; set; }
public FieldType FieldType { get; set; }
public bool IsMultiValue { get; set; }
Expand Down
19 changes: 17 additions & 2 deletions DVM4T.ModelGen/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,29 @@ public void GenerateModelCode(ViewModel model, DirectoryInfo saveDir)
new CodePrimitiveExpression(true)));
}
//Create and populate the model Property
CodeMemberField property = new CodeMemberField { Name = field.Name }; //Use CodeMemberField as a hack to add a blank getter/setter
CodeMemberField property = new CodeMemberField { Name = field.PropertyName }; //Use CodeMemberField as a hack to add a blank getter/setter
property.Attributes = MemberAttributes.Public;
property.Type = GetPropertyType(model.BaseClass, field);
property.CustomAttributes.Add(fieldAttribute); //Add the Field Attribute
property.Name += " { get; set; }"; //Hack to add empty get/set
modelClass.Members.Add(property);
}
}
if (configuration.ModelAttributeTypes.ContainsKey(model.ModelType))
{
var attrs = configuration.ModelAttributeTypes[model.ModelType];
//loop through all the "extra" model properties in the config that don't necessarily have a direct link to the Schema i.e. multimedia
foreach (var attr in attrs)
{
CodeAttributeDeclaration modelAttribute = new CodeAttributeDeclaration(attr.Name); //Field Attribute Name
CodeMemberField property = new CodeMemberField { Name = attr.DefaultPropertyName }; //Use CodeMemberField as a hack to add a blank getter/setter
property.Attributes = MemberAttributes.Public;
property.Type = new CodeTypeReference(attr.ReturnTypeName);
property.CustomAttributes.Add(modelAttribute); //Add the Field Attribute
property.Name += " { get; set; }"; //Hack to add empty get/set
modelClass.Members.Add(property);
}
}
var ns = new CodeNamespace(namespaceName);
ns.Types.Add(modelClass);
compileUnit.Namespaces.Add(ns);
Expand Down Expand Up @@ -136,7 +151,7 @@ private CodeTypeReference GetPropertyType(Type baseType, FieldProperty fieldProp
var config = configuration.FieldAttributeTypes[fieldProp.FieldType];
//return new CodeTypeReference(fieldProp.IsMultiValue ? config.MultiExpectedReturnTypeName : config.SingleExpectedReturnTypeName);

CodeTypeReference singleType = new CodeTypeReference(config.SingleExpectedReturnTypeName);
CodeTypeReference singleType = new CodeTypeReference(config.ReturnTypeName);
CodeTypeReference result;
if (fieldProp.FieldType == FieldType.Embedded)
{
Expand Down
5 changes: 5 additions & 0 deletions DVM4T.ModelGeneratorApp/DD4TConfig.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
<FieldAttribute fieldType="Text" name="TextField" singleType="String" multiType="IList&lt;String&gt;"/>
<FieldAttribute fieldType="ExternalLink" name="TextField" singleType="String" multiType="IList&lt;String&gt;"/>
</FieldAttributeTypes>
<ModelAttributeTypes>
<ModelAttributes modelType="MultimediaComponent">
<Attribute name="MultimediaUrl" returnType="String" propertyName="Url"/>
</ModelAttributes>
</ModelAttributeTypes>
<Namespaces>
<Namespace value="System"/>
<Namespace value="System.Web.Mvc"/>
Expand Down
6 changes: 4 additions & 2 deletions DVM4T.ModelGeneratorApp/Tridion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,19 +92,21 @@ private ViewModel CoreCreateModel(SchemaData schema, SessionAwareCoreServiceClie
Console.WriteLine("\nTitle:" + schema.Title + ", Schema Purpose: " + schema.Purpose);
IList<FieldProperty> modelProperties = new List<FieldProperty>();
ViewModel model = new ViewModel();
//TODO - Why is schema.Purpose always null?! Documentation indicates it should contain the type of Schema
switch (schema.Purpose)
{
case SchemaPurpose.Embedded:
model.BaseClass = typeof(EmbeddedSchemaViewModelBase);
model.ModelType = ModelType.EmbeddedSchemaFields;
break;
case SchemaPurpose.Component:
model.BaseClass = typeof(ComponentPresentationViewModelBase);
model.ModelType = ModelType.ComponentPresentation;
break;
case SchemaPurpose.Metadata:
return null;
case SchemaPurpose.Multimedia:
model.BaseClass = typeof(ComponentPresentationViewModelBase); //testing
model.ModelType = ModelType.MultimediaComponent;
break;
case SchemaPurpose.Protocol:
return null;
Expand Down Expand Up @@ -144,7 +146,7 @@ private static void ProcessFields(ItemFieldDefinitionData[] fields, bool isMetad
fieldProp.IsMultiValue = field.MaxOccurs != 1;
fieldProp.IsMetadata = isMetadata;
fieldProp.FieldName = field.Name;
fieldProp.Name = field.Name.ResolvePropertyName();
fieldProp.PropertyName = field.Name.ResolvePropertyName();
if (field is ComponentLinkFieldDefinitionData)
{
//Linked component
Expand Down
Loading

0 comments on commit 1d335a9

Please sign in to comment.