Exemplo n.º 1
0
        private static CmdletParameter CreateEntityParameter(
            OdcmProperty property,
            Type powerShellType,
            bool markAsPowerShellParameter,
            bool isBaseType,
            string entityTypeFullName,
            bool isReadOnly = false,
            bool allowPipelineInputByName   = true,
            IEnumerable <string> enumValues = null)
        {
            var result = new CmdletParameter(property.Name, powerShellType)
            {
                Mandatory                       = property.IsRequired,
                IsPowerShellParameter           = markAsPowerShellParameter && !isReadOnly,
                ValueFromPipelineByPropertyName = allowPipelineInputByName,
                DerivedTypeName                 = markAsPowerShellParameter || isBaseType
                                ? null
                                : entityTypeFullName,
                IsExpandable  = property.IsExpandable(),
                IsSortable    = !markAsPowerShellParameter && !property.IsCollection,
                Documentation = new CmdletParameterDocumentation()
                {
                    Descriptions = new string[] {
                        $"The \"{property.Name}\" property, of type \"{property.Type.FullName}\".",
                        $"This property is on the \"{entityTypeFullName}\" type.",
                        property.Description,
                    },
                    ValidValues = enumValues,
                }
            };

            return(result);
        }
Exemplo n.º 2
0
 protected ConcreteNavigationProperty(OdcmProperty odcmProperty) : base(odcmProperty)
 {
     FieldName  = NamesService.GetPropertyFieldName(odcmProperty);
     FieldType  = NamesService.GetConcreteTypeName(odcmProperty.Type);
     Type       = new Type(NamesService.GetConcreteInterfaceName(odcmProperty.Type));
     PrivateSet = true;
 }
Exemplo n.º 3
0
            private void WriteProperty(OdcmClass odcmClass, IEdmProperty property)
            {
                var odcmType     = ResolveType(property.Type);
                var odcmProperty = new OdcmProperty(property.Name)
                {
                    Class          = odcmClass,
                    IsNullable     = property.Type.IsNullable,
                    IsCollection   = property.Type.IsCollection(),
                    ContainsTarget =
                        property is IEdmNavigationProperty && ((IEdmNavigationProperty)property).ContainsTarget,
                    IsLink       = property is IEdmNavigationProperty,
                    DefaultValue =
                        property is IEdmStructuralProperty ?
                        ((IEdmStructuralProperty)property).DefaultValueString :
                        null
                };

                odcmProperty.Projection = new OdcmProjection
                {
                    Type     = odcmType,
                    BackLink = odcmProperty
                };


                _propertyCapabilitiesCache.Add(odcmProperty, OdcmCapability.DefaultPropertyCapabilities);

                AddVocabularyAnnotations(odcmProperty, property);

                odcmClass.Properties.Add(odcmProperty);
            }
Exemplo n.º 4
0
        public Given_an_OdcmClass_Entity_Property_forced_to_pascal_case()
        {
            SetConfiguration(new CSharpWriterSettings
            {
                ForcePropertyPascalCasing = true
            });

            Init(m =>
            {
                var originalProperty = Class.Properties.Where(p => !p.IsCollection).RandomElement();

                var camelCasedName = Any.Char('a', 'z') + originalProperty.Name;

                _property = originalProperty.Rename(camelCasedName);

                originalProperty = Class.NavigationProperties().Where(p => p.IsCollection).RandomElement();

                camelCasedName = Any.Char('a', 'z') + originalProperty.Name;

                _collectionProperty = originalProperty.Rename(camelCasedName);
            });

            _propertyType = Proxy.GetClass(_property.Type.Namespace, _property.Type.Name);

            _collectionPropertyType = Proxy.GetClass(_collectionProperty.Type.Namespace, _collectionProperty.Type.Name);
            _collectionPropertyType = typeof(IList <>).MakeGenericType(_collectionPropertyType);
        }
        public static string GetToLowerImport(this OdcmProperty property)
        {
            var type  = property.Projection.Type;
            var index = type.Name.LastIndexOf('.');

            return(type.Name.Substring(0, index).ToLower() + type.Name.Substring(index));
        }
Exemplo n.º 6
0
        /// <summary>
        /// This method takes a specific property and determines whether its could be referenced in the navigation property of another type.
        /// The navigation property must also come from chain where the containTarget=true from the root Service class to prove that we can reference it.
        /// Ideally we should call this function if GetServiceCollectionNavigationPropertyForPropertyType returns null
        /// </summary>
        /// <param name="odcmProperty">The property to check</param>
        /// <param name="model">The model to use</param>
        /// <returns></returns>
        public static bool IsPropertyChainedToContainedServiceNavigationProperty(this OdcmProperty odcmProperty, OdcmModel model)
        {
            // keep track of the types we've traversed to avoid circular references
            var navigatedTypes       = new HashSet <string>();
            var matchingRootProperty = GetOdcmNamespaces(model)
                                       .SelectMany(
                @namespace =>
                @namespace
                .Classes
                .FirstOrDefault(odcmClass => odcmClass.Kind == OdcmClassKind.Service)                       // find the root service class
                ?.Properties
                ?.Where(serviceProperty => serviceProperty.GetType() == typeof(OdcmSingleton))              // find the singleton properties
                ?.Where(singleton =>
                        singleton.
                        Type.AsOdcmClass()
                        ?.Properties
                        ?.Where(property => property.ContainsTarget)                                 // find singleton type properties that are self contained
                        ?.Any(property => property.IsPropertyTypeChainedContainedNavigationProperty( //  keep following the containsTarget=True to find if we can use a reference
                                  odcmProperty,
                                  navigatedTypes,
                                  property.IsCollection
                                                                                    ? $"{singleton.Name}/{property.Name}/{{id}}"
                                                                                    : $"{singleton.Name}/{property.Name}")
                              ) ?? false
                        ) ?? Array.Empty <OdcmProperty>()
                ).FirstOrDefault();

            return(matchingRootProperty != null);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Generates the OData route string with ID and typecast placeholders.
        /// It will have neither a leading slash nor trailing slash.
        /// </summary>
        /// <param name="includeEntityIdAndTypeCast">Whether or not to include the entity ID and typecast placeholders if required</param>
        /// <returns>The OData route.</returns>
        public string ToODataRouteString(bool includeEntityIdAndTypeCast = true)
        {
            IList <string> segments    = new List <string>();
            OdcmProperty   lastSegment = this.Segments.LastOrDefault();

            foreach (OdcmProperty property in this.Segments)
            {
                // Add this node to the route
                segments.Add(property.Name);

                // Add the ID and typecast after the final segment only if the caller wants to include them
                if (property != lastSegment || includeEntityIdAndTypeCast)
                {
                    // If this segment requires an ID, add it to the route
                    if (this._idParameters.TryGetValue(property, out string idParameterName))
                    {
                        segments.Add($"{{{idParameterName}}}");
                    }

                    // If this segment requires a typecast, add it to the route
                    if (this._typeCastParameters.TryGetValue(property, out string typeCastParameterName))
                    {
                        segments.Add($"{{{typeCastParameterName}}}");
                    }
                }
            }

            return(string.Join("/", segments));
        }
Exemplo n.º 8
0
        public static OdcmProperty Rename(this OdcmProperty originalProperty, string newName)
        {
            var index = originalProperty.Class.Properties.IndexOf(originalProperty);

            originalProperty.Class.Properties[index] =
                new OdcmProperty(newName)
            {
                Class          = originalProperty.Class,
                ReadOnly       = originalProperty.ReadOnly,
                Projection     = originalProperty.Type.DefaultProjection,
                ContainsTarget = originalProperty.ContainsTarget,
                IsCollection   = originalProperty.IsCollection,
                IsLink         = originalProperty.IsLink,
                IsNullable     = originalProperty.IsNullable,
                IsRequired     = originalProperty.IsRequired
            };

            if (originalProperty.Class is OdcmEntityClass && ((OdcmEntityClass)originalProperty.Class).Key.Contains(originalProperty))
            {
                var keyIndex = ((OdcmEntityClass)originalProperty.Class).Key.IndexOf(originalProperty);
                ((OdcmEntityClass)originalProperty.Class).Key[keyIndex] = originalProperty.Class.Properties[index];
            }

            return(originalProperty.Class.Properties[index]);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Sanitizes a property name for the following conditions:
        /// 1) a property has the same name as a C# keyword. Prefix @ to the property name to make it valid.
        /// 2) a property has the same name as the class. First we'll try to change the property name to the
        /// return type name. If the return type name is the same as the class name, then we'll append
        /// "Property" to the property name.
        /// </summary>
        /// <param name="property">The string that called this extension.</param>
        /// <param name="odcmProperty">An OdcmProperty. Use the property that you want to sanitize.</param>
        /// <param name="prefix">The prefix to use on this property.</param>
        /// <returns></returns>
        public static string GetSanitizedPropertyName(this string property, OdcmProperty odcmProperty, string prefix = null)
        {
            if (GetReservedNames().Contains(property))
            {
                var reservedPrefix = string.IsNullOrEmpty(prefix) ? DefaultReservedPrefix : prefix;

                logger.Info("Property \"{0}\" is a reserved word in .NET. Converting to \"{1}{0}\"", property.ToUpperFirstChar(), reservedPrefix);
                return(string.Concat(reservedPrefix, property.ToUpperFirstChar()));
            }

            // Check whether the propertyObject is null (means they called the extension from a string).
            // Check whether the property name is the same as the class name.
            // Only constructor members may be named the same as the class name.
            if (odcmProperty != null && property == odcmProperty.Class.Name.ToUpperFirstChar())
            {
                // Check whether the property type is the same as the class name.
                if (odcmProperty.Projection.Type.Name.ToUpperFirstChar() == odcmProperty.Class.Name.ToUpperFirstChar())
                {
                    // Name the property: {metadataName} + "Property"
                    logger.Info("Property type \"{0}\" has the same name as the class. Converting to \"{0}Property\"", property);
                    return(string.Concat(property, "Property"));
                }

                // Name the property by its type. Sanitize it in case the type is a reserved name.
                return(odcmProperty.Projection.Type.Name.ToUpperFirstChar().GetSanitizedPropertyName());
            }

            return(property);
        }
        /// <summary>
        /// Expands a node into child nodes.
        /// </summary>
        /// <param name="node">The node to expand</param>
        /// <param name="model">The ODCM model</param>
        /// <returns>The child nodes if the node can be expanded, otherwise an empty list.</returns>
        private static IEnumerable <OdcmNode> CreateChildNodes(this OdcmNode node, OdcmModel model)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }

            // Identify the kind of ODCM element this node represents and expand it if we need to
            OdcmProperty obj = node.OdcmProperty;
            IEnumerable <OdcmProperty> childObjects = obj.Type.GetChildObjects(model);

            // Don't allow loops in the list of ODCM nodes
            ICollection <string> parents     = new HashSet <string>();
            OdcmNode             currentNode = node;

            while (currentNode != null)
            {
                parents.Add(currentNode.OdcmProperty.CanonicalName());
                currentNode = currentNode.Parent;
            }

            return(childObjects
                   // Filter out the children we've already seen so we can avoid loops
                   .Where(child => !parents.Contains(child.CanonicalName()))
                   // Add the child nodes to the current node
                   .Select(child => node.CreateChildNode(child)));
        }
Exemplo n.º 11
0
 protected FetcherNavigationProperty(OdcmProperty odcmProperty) : base(odcmProperty)
 {
     FieldName    = NamesService.GetFetcherFieldName(odcmProperty);
     InstanceType = NamesService.GetFetcherTypeName(odcmProperty.Type);
     PrivateSet   = true;
     Type         = new Type(NamesService.GetFetcherInterfaceName(odcmProperty.Type));
 }
Exemplo n.º 12
0
        /// <summary>
        /// This method takes in a property and looks through to see if the given testProperty could be contained in it through its contained navigation properties or
        /// its nested contained navigation properties.
        /// </summary>
        /// <param name="odcmRootProperty">The property to start the search from</param>
        /// <param name="testProperty">The property to find in the from the root type</param>
        /// <param name="navigatedTypes">The types already navigated to prevent circular references</param>
        /// <param name="route">The route followed to get here</param>
        /// <returns></returns>
        private static bool IsPropertyTypeChainedContainedNavigationProperty(this OdcmProperty odcmRootProperty, OdcmProperty testProperty, HashSet <string> navigatedTypes, string route)
        {
            // check if the property already matches the type.
            if (odcmRootProperty.Type.FullName.Equals(testProperty.Type.FullName, StringComparison.OrdinalIgnoreCase))
            {
                logger.Info("Property \"{0}\" matches self contained navigation property \"{1}\" of type \"{2}\"", testProperty.Name, odcmRootProperty.Name, odcmRootProperty.Type.FullName);
                logger.Info("Possible route from service class is: {0}{1}{1}", route, Environment.NewLine);
                return(true);
            }

            // check if the base class is referenced instead.
            if (odcmRootProperty.AsOdcmClass()?.IsAncestorOfType(testProperty.AsOdcmClass() ?? null) ?? false)
            {
                logger.Info("Property \"{0}\" of type \"{1}\" matches self contained navigation property \"{2}\" of Base type \"{3}\"", testProperty.Name, testProperty.Type.FullName, odcmRootProperty.Name, odcmRootProperty.Type.FullName);
                logger.Info("Possible route from service class is: {0}{1}{1}", route, Environment.NewLine);
                return(true);
            }

            // its not this type so lets add it to the exclusion list
            navigatedTypes.Add(odcmRootProperty.Type.FullName);

            // The current type does not match. So, we get the list of contained nav properties from the given type and recursively subject it to the same test
            var matchingProperty = odcmRootProperty.Type.AsOdcmClass()?
                                   .Properties
                                   .Where(prop => prop.ContainsTarget)                          // the nave properties with containsTarget
                                   .Where(prop => !navigatedTypes.Contains(prop.Type.FullName)) // prevent any cycle business
                                   .FirstOrDefault(prop => prop.IsPropertyTypeChainedContainedNavigationProperty(testProperty, navigatedTypes, prop.IsCollection ? $"{route}/{prop.Name}/{{id}}" : $"{route}/{prop.Name}")
                                                   );

            return(matchingProperty != null);
        }
 protected ConcreteNavigationAccessorProperty(OdcmProperty odcmProperty) : base(odcmProperty)
 {
     FieldName    = NamesService.GetPropertyFieldName(odcmProperty);
     InstanceType = NamesService.GetFetcherTypeName(odcmProperty.Type);
     FieldType    = NamesService.GetConcreteTypeName(odcmProperty.Type);
     Type         = new Type(NamesService.GetConcreteTypeName(odcmProperty.Type));
 }
Exemplo n.º 14
0
        private static string ToEdmx(this OdcmProperty odcmProperty)
        {
            var tagName           = "Property";
            var typeAttributeName = "Type";
            var edmType           = odcmProperty.Type.FullName;

            if (odcmProperty.Class.Kind == OdcmClassKind.Service)
            {
                if (odcmProperty.IsCollection)
                {
                    tagName           = "EntitySet";
                    typeAttributeName = "EntityType";
                }
                else
                {
                    tagName = "Singleton";
                }
            }
            else if (odcmProperty.Class.Kind == OdcmClassKind.Entity)
            {
                if (odcmProperty.Type is OdcmClass && ((OdcmClass)odcmProperty.Type).Kind == OdcmClassKind.Entity)
                {
                    tagName = "NavigationProperty";

                    if (odcmProperty.IsCollection)
                    {
                        edmType = String.Format("Collection({0})", edmType);
                    }
                }
            }

            return(String.Format("<{0} Name=\"{1}\" {2}=\"{3}\" />", tagName, odcmProperty.Name, typeAttributeName, edmType));
        }
Exemplo n.º 15
0
 public ObsoletedNavigationProperty(OdcmProperty odcmProperty) : base(odcmProperty)
 {
     Type = odcmProperty.IsCollection
         ? new Type(new Identifier("global::System.Collections.Generic", "IList"),
                    new Type(NamesService.GetConcreteTypeName(odcmProperty.Type)))
         : new Type(NamesService.GetConcreteTypeName(odcmProperty.Type));
 }
Exemplo n.º 16
0
 public static FetcherNavigationProperty ForConcrete(OdcmProperty odcmProperty)
 {
     return(new FetcherNavigationProperty(odcmProperty)
     {
         DefiningInterface = NamesService.GetFetcherInterfaceName(odcmProperty.Class)
     });
 }
Exemplo n.º 17
0
 public new static ConcreteNavigationProperty ForConcrete(OdcmProperty odcmProperty)
 {
     return(new ConcreteNavigationCollectionProperty(odcmProperty)
     {
         DefiningInterface = NamesService.GetConcreteInterfaceName(odcmProperty.Class),
     });
 }
Exemplo n.º 18
0
        /// <summary>
        /// Adds a property line inside an entity or complex type object
        /// </summary>
        /// <param name="prop">property</param>
        private void AddProperties(OdcmProperty prop)
        {
            if (prop.LongDescription != null || prop.Description != null)
            {
                List <string> multiLineDescriptions = SplitString(prop.GetSanitizedLongDescription());
                if (multiLineDescriptions.Count() == 1)
                {
                    sb.AppendLine($"{NamespaceIndent}{TabSpace}// {multiLineDescriptions.First()}");
                }
                else
                {
                    sb.AppendLine($"{NamespaceIndent}{TabSpace}/**");
                    foreach (var descriptionLine in multiLineDescriptions)
                    {
                        sb.AppendLine($"{NamespaceIndent}{TabSpace} * {descriptionLine}");
                    }

                    sb.AppendLine($"{NamespaceIndent}{TabSpace} */");
                }
            }

            var typeName = GetFullyQualifiedTypeScriptTypeName(prop.GetTypeString(), prop.Projection.Type.Namespace.GetNamespaceName());

            if (prop.IsNullable)
            {
                typeName = $"NullableOption<{typeName}>";
            }

            sb.AppendLine($"{NamespaceIndent}{TabSpace}{prop.Name}?: {typeName};");
        }
Exemplo n.º 19
0
 private ConcreteNavigationCollectionProperty(OdcmProperty odcmProperty) : base(odcmProperty)
 {
     FieldName  = NamesService.GetConcreteFieldName(odcmProperty);
     OdcmType   = odcmProperty.Type;
     PrivateSet = true;
     Type       = new Type(new Identifier("global::System.Collections.Generic", "IList"),
                           new Type(NamesService.GetConcreteInterfaceName(odcmProperty.Type)));
 }
Exemplo n.º 20
0
 public static string GetSanitizedLongDescription(this OdcmProperty property)
 {
     if (property.LongDescription != null)
     {
         return(property.LongDescription.Replace("<", "&lt;").Replace(">", "&gt;").Replace("&", "&amp;"));
     }
     return(null);
 }
 private ConcreteNavigationCollectionAccessorProperty(OdcmProperty odcmProperty) : base(odcmProperty)
 {
     CollectionType = new Type(NamesService.GetCollectionTypeName((OdcmClass)odcmProperty.Type));
     FieldName      = NamesService.GetConcreteFieldName(odcmProperty);
     InstanceType   = NamesService.GetConcreteTypeName(odcmProperty.Type);
     Type           = new Type(new Identifier("global::System.Collections.Generic", "IList"),
                               new Type(NamesService.GetConcreteTypeName(odcmProperty.Type)));
 }
Exemplo n.º 22
0
 private ConcreteNavigationCollectionProperty(OdcmProperty odcmProperty) : base(odcmProperty)
 {
     FieldName  = NamesService.GetConcreteFieldName(odcmProperty);
     OdcmType   = odcmProperty.Type;
     PrivateSet = true;
     Type       = new Type(NamesService.GetExtensionTypeName("IPagedCollection"),
                           new Type(NamesService.GetConcreteInterfaceName(odcmProperty.Type)));
 }
Exemplo n.º 23
0
 public static Parameter FromProperty(OdcmProperty arg)
 {
     return(new Parameter
     {
         Name = arg.Name.ToLowerCamelCase(),
         Type = new Type(NamesService.GetConcreteTypeName(arg.Type))
     });
 }
Exemplo n.º 24
0
 public static Field ForNavigationProperty(OdcmProperty property)
 {
     return(new Field
     {
         Name = NamesService.GetPropertyFieldName(property),
         Type = new Type(NamesService.GetConcreteTypeName(property.Type))
     });
 }
 protected FetcherNavigationCollectionProperty(OdcmProperty odcmProperty)
     : base(odcmProperty)
 {
     CollectionType = new Type(NamesService.GetCollectionTypeName((OdcmClass)odcmProperty.Type));
     FieldName      = NamesService.GetFetcherCollectionFieldName(odcmProperty);
     InstanceType   = NamesService.GetFetcherTypeName(odcmProperty.Type);
     Type           = new Type(NamesService.GetCollectionInterfaceName((OdcmClass)odcmProperty.Type));
 }
 public static string SanitizePropertyName(this OdcmProperty property)
 {
     if (ReservedNames.Contains(property.Name.ToLower()))
     {
         return(property.Class.Name.ToLowerFirstChar() + property.Name.ToUpperFirstChar());
     }
     return(property.Name);
 }
Exemplo n.º 27
0
 public static Field ForFetcherNavigationCollectionProperty(OdcmProperty property)
 {
     return(new Field
     {
         Name = NamesService.GetFetcherCollectionFieldName(property),
         Type = new Type(NamesService.GetCollectionTypeName((OdcmClass)property.Type))
     });
 }
Exemplo n.º 28
0
 public static string SanitizePropertyName(this OdcmProperty property)
 {
     if (ReservedNames.Contains(property.Name.ToLower()))
     {
         return(ReservedPrefix + property.Name);
     }
     return(property.Name);
 }
Exemplo n.º 29
0
 public static Field ForNavigationConcreteProperty(OdcmProperty property)
 {
     return(new Field
     {
         Name = NamesService.GetConcreteFieldName(property),
         Type = new Type(NamesService.GetExtensionTypeName("EntityCollectionImpl"), new Type(NamesService.GetConcreteTypeName((OdcmClass)property.Type)))
     });
 }
Exemplo n.º 30
0
 public ObsoletedProperty(OdcmProperty odcmProperty) : base(odcmProperty)
 {
     Type = odcmProperty.IsCollection
         ? new Type(new Identifier("global::System.Collections.Generic", "IList"),
                    TypeService.GetPropertyType(odcmProperty))
         : TypeService.GetPropertyType(odcmProperty);
     UpdatedName = Name;
     Name        = NamesService.GetModelPropertyName(odcmProperty);
 }