public void GetOutputStructure_Correct1Superset1SubsetExpr_SupersetModified(params TestExprType[] types)
        {
            foreach (string opSymbol in this._operators)
            {
                IExpression arithmeticExpr = TestExprFactory.GetExpression(types);
                arithmeticExpr.OperatorDefinition = ModelResolvers.OperatorResolver(opSymbol);

                arithmeticExpr.Operands["ds_1"].Structure.Identifiers.Add(new StructureComponent(BasicDataType.Integer, "Id2"));

                IDataStructure expectedStructure = arithmeticExpr.Operands[$"ds_1"].Structure.GetCopy();
                for (int i = 0; i < expectedStructure.Measures.Count; i++)
                {
                    BasicDataType dataType = arithmeticExpr.Operands[$"ds_2"].Structure.Measures[i].ValueDomain.DataType;
                    if (dataType == BasicDataType.Number)
                    {
                        expectedStructure.Measures[i].ValueDomain = new ValueDomain(dataType);
                    }
                    if (expectedStructure.Measures[i].ValueDomain.DataType == BasicDataType.None)
                    {
                        expectedStructure.Measures[i].ValueDomain = new ValueDomain(BasicDataType.Integer);
                    }
                }

                IDataStructure dataStructure = arithmeticExpr.OperatorDefinition.GetOutputStructure(arithmeticExpr);

                Assert.True(expectedStructure.EqualsObj(dataStructure));
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="DataStructure"/> class <b>for a single component structure.</b>.
        /// </summary>
        /// <param name="compName">The name of the component.</param>
        /// <param name="compType">The component type.</param>
        /// <param name="dataType">The data type of the component.</param>
        /// <param name="logger">The errors logger.</param>
        public DataStructure(string compName, ComponentType compType, BasicDataType dataType, ILogger <IDataStructure> logger = null)
            : this(logger)
        {
            switch (compType)
            {
            case ComponentType.Identifier: this.identifiers = new List <StructureComponent>()
            {
                    new StructureComponent(dataType, compName)
            }; break;

            case ComponentType.Measure: this.measures = new List <StructureComponent>()
            {
                    new StructureComponent(dataType, compName)
            }; break;

            case ComponentType.NonViralAttribute: this.nonViralAttributes = new List <StructureComponent>()
            {
                    new StructureComponent(dataType, compName)
            }; break;

            case ComponentType.ViralAttribute: this.viralAttributes = new List <StructureComponent>()
            {
                    new StructureComponent(dataType, compName)
            }; break;

            default: throw new ArgumentOutOfRangeException("compType", "Wrong component type.");
            }
        }
        /// <summary>
        /// Gets the variable name of a basic data type.
        /// </summary>
        /// <param name="instance">The basic data type to get a variable name from.</param>
        /// <returns>The variable name of a basic data type.</returns>
        public static string GetVariableName(this BasicDataType instance)
        {
            switch (instance)
            {
            case BasicDataType.Integer: return("int_var");

            case BasicDataType.Number: return("num_var");

            case BasicDataType.String: return("string_var");

            case BasicDataType.Boolean: return("bool_var");

            case BasicDataType.Time: return("time_var");

            case BasicDataType.Date: return("date_var");

            case BasicDataType.TimePeriod: return("period_var");

            case BasicDataType.Duration: return("duration_var");

            case BasicDataType.None: return("NULL");

            default: throw new ArgumentOutOfRangeException("instance", "Unknown data type.");
            }
        }
Example #4
0
        /// <summary>
        /// Maps a SDMX text data type to a VTL 2.0 data type.
        /// </summary>
        /// <param name="type">The type of the SDMX text data.</param>
        /// <returns>The basic VTL 2.0 data type.</returns>
        private BasicDataType mappingSDMX(TextEnumType type)
        {
            BasicDataType basicDataType = type switch
            {
                TextEnumType.Null => BasicDataType.None,
                TextEnumType.Alpha => BasicDataType.String,
                TextEnumType.Alphanumeric => BasicDataType.String,
                TextEnumType.AttachmentConstraintReference => BasicDataType.None,
                TextEnumType.BasicTimePeriod => BasicDataType.Date,
                TextEnumType.String => BasicDataType.String,
                TextEnumType.BigInteger => BasicDataType.Integer,
                TextEnumType.Integer => BasicDataType.Integer,
                TextEnumType.Long => BasicDataType.Integer,
                TextEnumType.Short => BasicDataType.Integer,
                TextEnumType.Decimal => BasicDataType.Number,
                TextEnumType.Float => BasicDataType.Number,
                TextEnumType.Double => BasicDataType.Number,
                TextEnumType.Boolean => BasicDataType.Boolean,
                TextEnumType.DateTime => BasicDataType.Date,
                TextEnumType.Date => BasicDataType.Date,
                TextEnumType.Time => BasicDataType.String,
                TextEnumType.Year => BasicDataType.String,
                TextEnumType.Month => BasicDataType.String,
                TextEnumType.Numeric => BasicDataType.String,
                TextEnumType.Day => BasicDataType.String,
                TextEnumType.MonthDay => BasicDataType.String,
                TextEnumType.YearMonth => BasicDataType.String,
                TextEnumType.Duration => BasicDataType.Duration,
                TextEnumType.Uri => BasicDataType.String,
                TextEnumType.Timespan => BasicDataType.String,
                TextEnumType.Count => BasicDataType.Integer,
                TextEnumType.DataSetReference => BasicDataType.None,
                TextEnumType.InclusiveValueRange => BasicDataType.Number,
                TextEnumType.ExclusiveValueRange => BasicDataType.Number,
                TextEnumType.Incremental => BasicDataType.Number,
                TextEnumType.ObservationalTimePeriod => BasicDataType.Time,
                TextEnumType.KeyValues => BasicDataType.None,
                TextEnumType.TimePeriod => BasicDataType.TimePeriod,
                TextEnumType.GregorianDay => BasicDataType.Date,
                TextEnumType.GregorianTimePeriod => BasicDataType.Date,
                TextEnumType.GregorianYear => BasicDataType.Date,
                TextEnumType.GregorianYearMonth => BasicDataType.Date,
                TextEnumType.ReportingDay => BasicDataType.TimePeriod,
                TextEnumType.ReportingMonth => BasicDataType.TimePeriod,
                TextEnumType.ReportingQuarter => BasicDataType.TimePeriod,
                TextEnumType.ReportingSemester => BasicDataType.TimePeriod,
                TextEnumType.ReportingTimePeriod => BasicDataType.TimePeriod,
                TextEnumType.ReportingTrimester => BasicDataType.TimePeriod,
                TextEnumType.ReportingWeek => BasicDataType.TimePeriod,
                TextEnumType.ReportingYear => BasicDataType.TimePeriod,
                TextEnumType.StandardTimePeriod => BasicDataType.Time,
                TextEnumType.TimesRange => BasicDataType.Time,
                TextEnumType.IdentifiableReference => BasicDataType.None,
                TextEnumType.Xhtml => BasicDataType.None,
                _ => throw new ArgumentOutOfRangeException("type")
            };

            return(basicDataType);
        }
    }
 /// <summary>
 /// Initializes a new instance of the <see cref="ValueDomain"/> class.
 /// </summary>
 /// <param name="dataType">The type of the data.</param>
 /// <param name="signature">The domain signature.</param>
 public ValueDomain(BasicDataType dataType, string signature = null)
 {
     this.DataType  = dataType;
     this.Signature = signature ?? $"{dataType.GetName().ToLower()}_default";
     if (this.Signature == "none")
     {
         this.Signature = "null_default";
     }
 }
Example #6
0
        public string Render(IExpression expr, StructureComponent component = null)
        {
            BasicDataType type = expr.Structure.Components[0].ValueDomain.DataType;

            if (type == BasicDataType.None)
            {
                return("NULL");
            }

            if (type == BasicDataType.String)
            {
                string str = expr.ExpressionText;

                if (str.First() == '"' && str.Last() == '"' && str.Length >= 2)
                {
                    str = str.Remove(str.Length - 1).Remove(0, 1);
                    str = str.Replace("'", "''");

                    //TODO: replacement of '"'

                    return($"'{str}'");
                }
            }

            if (type.In(BasicDataType.Time, BasicDataType.Date, BasicDataType.TimePeriod, BasicDataType.Duration))
            {
                string str = expr.ExpressionText;

                if (str.Length >= 3 && str[0] == 't' && str[1] == '"' && str.Last() == '"')
                {
                    str = str.Remove(str.Length - 1).Remove(0, 2);
                    str = str.Replace("'", "''");

                    //TODO: replacement of '"'

                    return($"'{str}'");
                }
            }

            if (type == BasicDataType.Boolean)
            {
                if (expr.ExpressionText == "true")
                {
                    return("1");
                }
                return("0");
            }

            return(expr.ExpressionText);
        }
        /// <summary>
        /// Checks if the data type is equal to another.
        /// </summary>
        /// <param name="instance">The compared data type.</param>
        /// <param name="dataType">The data type to compare.</param>
        /// <param name="allNumsEqual">Specifies if an integer data type is equal to a number data type.</param>
        /// <param name="allEqualsToNull">Specifies if a none data type is equal to other.</param>
        /// <returns>Value specyfing equality.</returns>
        public static bool EqualsObj(this BasicDataType instance, BasicDataType dataType, bool allNumsEqual = true, bool allEqualsToNull = true)
        {
            if (instance != dataType &&
                (!allNumsEqual || (
                     !(instance == BasicDataType.Integer && dataType == BasicDataType.Number) &&
                     !(instance == BasicDataType.Number && dataType == BasicDataType.Integer))) &&
                (!allEqualsToNull || (instance != BasicDataType.None && dataType != BasicDataType.None))
                )
            {
                return(false);
            }

            return(true);
        }
Example #8
0
        public void InferStructure()
        {
            this.Structure = this._dsResolver();
            if (this.Variables.Count > 0)
            {
                foreach (string variableName in this.Variables.Keys)
                {
                    IEnumerable <StructureComponent> comps = this.RulesCollection.SelectMany(rule => this.GetComponentsFromDescendantExprs(rule, variableName));
                    BasicDataType dataType = comps.FirstOrDefault(comp => comp.ValueDomain.DataType != BasicDataType.None)?.ValueDomain.DataType ?? BasicDataType.None;
                    foreach (StructureComponent comp in comps)
                    {
                        if (comp.ValueDomain.DataType != dataType)
                        {
                            if (dataType == BasicDataType.Integer && comp.ValueDomain.DataType == BasicDataType.Number)
                            {
                                comp.ValueDomain = new ValueDomain(dataType);
                            }
                            else if (comp.ValueDomain.DataType == BasicDataType.None)
                            {
                                comp.ValueDomain = new ValueDomain(dataType);
                            }
                            else if (dataType == BasicDataType.None)
                            {
                                dataType = comp.ValueDomain.DataType;
                            }
                            else
                            {
                                throw new InvalidOperationException($"Something went wrong during a types inference of ruleset {this.Name}.");
                            }
                        }
                    }

                    this.Structure.Measures.Add(comps.First());
                }
            }
            else
            {
                foreach (string valueDomainName in this.ValueDomains.Keys)
                {
                    IEnumerable <StructureComponent> comps = this.RulesCollection.SelectMany(rule => this.GetComponentsFromDescendantExprs(rule, valueDomainName));
                    this.Structure.Measures.Add(comps.First());
                }
            }
        }
Example #9
0
        public override IDataStructure GetDatasetStructure(string datasetName)
        {
            string @namespace;

            this.SplitDatasetName(datasetName, out @namespace, out datasetName);

            if (@namespace != this.Namespace)
            {
                return(null);
            }

            ISet <IMaintainableObject> maintainable = this.GetMaintainableObjects();

            DataStructureObjectCore datastructure = (DataStructureObjectCore)maintainable.SingleOrDefault(m => m.StructureType.StructureType == "Data Structure Definition" && m.Id == datasetName);

            if (datastructure == null)
            {
                return(null);
            }

            DataStructure dataStructure = new DataStructure();

            foreach (IDimension dimension in datastructure.DimensionList.Dimensions)
            {
                BasicDataType type = dimension.Representation?.TextFormat != null?this.mappingSDMX(dimension.Representation.TextFormat.TextType.EnumType) : BasicDataType.String;

                dataStructure.Identifiers.Add(new StructureComponent(type, dimension.Id, ComponentType.Identifier));
            }

            IPrimaryMeasure primaryMeasure = datastructure.PrimaryMeasure;
            BasicDataType   measureType    = primaryMeasure.Representation?.TextFormat != null?this.mappingSDMX(primaryMeasure.Representation.TextFormat.TextType.EnumType) : BasicDataType.Number;

            dataStructure.Measures.Add(new StructureComponent(measureType, primaryMeasure.Id, ComponentType.Measure));

            foreach (IAttributeObject attribute in datastructure.AttributeList.Attributes)
            {
                BasicDataType type = attribute.Representation?.TextFormat != null?this.mappingSDMX(attribute.Representation.TextFormat.TextType.EnumType) : BasicDataType.String;

                dataStructure.ViralAttributes.Add(new StructureComponent(type, attribute.Id, ComponentType.ViralAttribute));
            }

            return(dataStructure);
        }
Example #10
0
        public void GetOutputStructure_WrongNoParamDatasetClauseExpr_ThrowsException(BasicDataType type)
        {
            foreach (string name in DatasetClauseOperator.ClauseNames)
            {
                IExpression datasetClauseExpr   = ModelResolvers.ExprResolver();
                IExpression datasetExpr         = ModelResolvers.ExprResolver();
                IExpression clauseExpr          = TestExprFactory.GetExpression(name, ExpressionFactoryNameTarget.ResultName);
                IExpression periodIndicatorExpr = TestExprFactory.GetExpression("period_indicator", ExpressionFactoryNameTarget.OperatorSymbol);

                datasetClauseExpr.AddOperand("ds_1", datasetExpr);
                datasetClauseExpr.AddOperand("ds_2", clauseExpr);
                clauseExpr.AddOperand("ds_1", periodIndicatorExpr);

                datasetExpr.Structure = ModelResolvers.DsResolver();
                datasetExpr.Structure.Identifiers.Add(new StructureComponent(BasicDataType.Integer, "Id1"));
                datasetExpr.Structure.Identifiers.Add(new StructureComponent(type, "Id2"));
                datasetExpr.Structure.Measures.Add(new StructureComponent(BasicDataType.String, "Me1"));

                Assert.ThrowsAny <VtlOperatorError>(() => { periodIndicatorExpr.OperatorDefinition.GetOutputStructure(periodIndicatorExpr); });
            }
        }
        private void StartTest(bool arg2_isComp, string opSymbol, ComponentType compType, TestExprType[] dataTypes)
        {
            IExpression expr1 = TestExprFactory.GetExpression(dataTypes[0]);
            IExpression expr2 = TestExprFactory.GetExpression(dataTypes[1]);

            expr1.ExpressionText     = expr1.Structure.Components[0].ComponentName = "Component";
            expr1.OperatorDefinition = ModelResolvers.OperatorResolver("comp");

            if (arg2_isComp)
            {
                expr2.ExpressionText     = expr2.Structure.Components[0].ComponentName = "Component";
                expr2.OperatorDefinition = ModelResolvers.OperatorResolver("comp");
            }

            IExpression compCreateExpr = TestExprFactory.FoldExpression(expr1, expr2);

            compCreateExpr.OperatorDefinition = ModelResolvers.OperatorResolver(opSymbol);

            compCreateExpr.OperatorDefinition.Keyword = this.GetKeywordByCompType(compType);
            compCreateExpr.Structure = compCreateExpr.OperatorDefinition.GetOutputStructure(compCreateExpr);
            StructureComponent[] components = this.GetComponentsByCompType(compCreateExpr.Structure, compType);

            for (int i = 0; i < compCreateExpr.Structure.Components.Count; i++)
            {
                Assert.True(compCreateExpr.Structure.Components[i].ComponentName == expr1.Structure.Components[i].ComponentName);
            }

            BasicDataType type = expr2.Structure.Components[0].ValueDomain.DataType;

            if (type == BasicDataType.None || (type == BasicDataType.Integer && expr1.Structure.Components[0].ValueDomain.DataType == BasicDataType.Number))
            {
                type = expr1.Structure.Components[0].ValueDomain.DataType;
            }

            Assert.Equal(components.Length, expr2.Structure.Components.Count);
            Assert.Equal(components[0].ValueDomain.DataType, type);
        }
Example #12
0
        public void GetOutputStructure_1TimeIdentifierExpr_DataStructure(string symbol, BasicDataType timeType)
        {
            IExpression timeExpr = ModelResolvers.ExprResolver();

            timeExpr.OperatorDefinition = ModelResolvers.OperatorResolver(symbol);

            IExpression timeDsExpr = ModelResolvers.ExprResolver();

            timeDsExpr.Structure = ModelResolvers.DsResolver("Id1", ComponentType.Identifier, timeType);
            timeDsExpr.Structure.Identifiers.Add(new StructureComponent(BasicDataType.Integer, "Id2"));

            timeExpr.AddOperand("ds_1", timeDsExpr);

            IDataStructure dataStructure = timeExpr.OperatorDefinition.GetOutputStructure(timeExpr);

            Assert.True(timeDsExpr.Structure.EqualsObj(dataStructure));
        }
Example #13
0
        public IDataStructure GetOutputStructure(IExpression expression)
        {
            if (expression.IsApplyComponent)
            {
                return(this._joinApplyMeasuresOp.GetMeasuresStructure(expression));
            }

            IExpression    expr1 = expression.OperandsCollection.ToArray()[0];
            IExpression    expr2 = expression.OperandsCollection.ToArray()[1];
            IExpression    expr3 = expression.OperandsCollection.ToArray()[2];
            IDataStructure structure;

            if (!expr2.IsScalar)
            {
                throw new VtlOperatorError(expression, this.Name, "Second parameter must be scalar expression.");
            }
            if (!expr3.IsScalar)
            {
                throw new VtlOperatorError(expression, this.Name, "Third parameter must be scalar expression.");
            }

            BasicDataType type = expr2.Structure.Components[0].ValueDomain.DataType;

            if (type == BasicDataType.None)
            {
                type = expr3.Structure.Components[0].ValueDomain.DataType;
            }

            if (!expr3.Structure.Components[0].ValueDomain.DataType.EqualsObj(type) &&
                !BasicDataType.None.In(expr3.Structure.Components[0].ValueDomain.DataType, type))
            {
                throw new VtlOperatorError(expression, this.Name, "Second and third parameter must have the same data types.");
            }

            if (expr1.IsScalar)
            {
                if (!expr1.Structure.Components[0].ValueDomain.DataType.EqualsObj(type) &&
                    !BasicDataType.None.In(expr1.Structure.Components[0].ValueDomain.DataType, type))
                {
                    throw new VtlOperatorError(expression, this.Name, "First parameter must have the same data type as second and third parameter.");
                }

                return(this._dsResolver("bool_var", ComponentType.Measure, BasicDataType.Boolean));
            }
            else
            {
                if (expr1.Structure.Measures.Count > 1)
                {
                    throw new VtlOperatorError(expression, this.Name, "Expected structure with only one measure.");
                }
                if (!expr1.Structure.Measures[0].ValueDomain.DataType.EqualsObj(type) &&
                    !BasicDataType.None.In(expr1.Structure.Measures[0].ValueDomain.DataType, type))
                {
                    throw new VtlOperatorError(expression, this.Name, "First parameter must have the same data type as second and third parameter.");
                }
            }

            structure = expr1.Structure.GetCopy();
            structure.Measures[0].ComponentName = "bool_var";
            structure.Measures[0].ValueDomain   = new ValueDomain(BasicDataType.Boolean);

            return(structure);
        }
 /// <summary>
 /// Initialises a new instance of the <see cref="StructureComponent"/> class.
 /// </summary>
 /// <param name="dataType">The data type.</param>
 /// <param name="name">The component name.</param>
 /// <param name="compType">The component type.</param>
 public StructureComponent(BasicDataType dataType, string name = "VALUE", ComponentType compType = ComponentType.Measure)
     : this(new ValueDomain(dataType), name, compType)
 {
 }
Example #15
0
        /// <summary>
        /// Gets the structure of the resulting operator parameter for specified operands.
        /// </summary>
        /// <param name="expression">The expression.</param>
        /// <returns>A dynamically defined structure of the output parameter for the given input parameters.</returns>
        public IDataStructure GetOutputStructure(IExpression expression)
        {
            IExpression   expr1 = expression.Operands["ds_1"];
            IExpression   expr2 = expression.Operands["ds_2"];
            BasicDataType type1 = expr1.Structure.Components[0].ValueDomain.DataType;
            BasicDataType type2 = expr2.Structure.Components[0].ValueDomain.DataType;

            if (!expr1.IsScalar || expr1.OperatorSymbol != "comp")
            {
                throw new VtlOperatorError(expression, this._name, "Expected component operator expression as the first parameter.");
            }

            if (!expr2.IsScalar)
            {
                throw new VtlOperatorError(expression, this._name, "Expected scalar expression as the second parameter.");
            }

            if (expr1.Structure.Identifiers.Count != 0 && expr1.Structure.Identifiers[0].ValueDomain.DataType != BasicDataType.None)
            {
                throw new VtlOperatorError(expression, this._name, "Identifier of any dataset can not be modify.");
            }

            if (!type1.EqualsObj(type2))
            {
                throw new VtlOperatorError(expression, this._name, "Types of parameters don't match.");
            }

            BasicDataType type = type2;

            if (type == BasicDataType.None || (type2 == BasicDataType.Integer && type1 == BasicDataType.Number))
            {
                type = type1;
            }

            IDataStructure dataStructure = this._dsResolver();

            switch (this.Keyword)
            {
            case "identifier":
                if (this.AreNullValues(expr2))
                {
                    throw new VtlOperatorError(expression, this._name, "Possible putting null values into an identifier component.");
                }
                dataStructure.Identifiers.Add(
                    new StructureComponent(type, expr1.ExpressionText));
                break;

            case "measure":
                dataStructure.Measures.Add(
                    new StructureComponent(type, expr1.ExpressionText));
                break;

            case "viral attribute":
                dataStructure.ViralAttributes.Add(
                    new StructureComponent(type, expr1.ExpressionText));
                break;

            case "attribute":
                dataStructure.NonViralAttributes.Add(
                    new StructureComponent(type, expr1.ExpressionText));
                break;

            default: throw new VtlOperatorError(expression, this._name, $"Unknown keyword of an operator: {this.Keyword}");
            }

            return(dataStructure);
        }
Example #16
0
        public void GetOutputStructure_NoTimeIdentifiersExpr_ThrowsException(string symbol, BasicDataType type)
        {
            IExpression timeExpr = ModelResolvers.ExprResolver();

            timeExpr.OperatorDefinition = ModelResolvers.OperatorResolver(symbol);

            IExpression timeDsExpr = ModelResolvers.ExprResolver();

            timeDsExpr.Structure = ModelResolvers.DsResolver("Id1", ComponentType.Identifier, type);
            timeDsExpr.Structure.Identifiers.Add(new StructureComponent(BasicDataType.Integer, "Id2"));

            timeExpr.AddOperand("ds_1", timeDsExpr);

            Assert.ThrowsAny <VtlOperatorError>(() => { timeExpr.OperatorDefinition.GetOutputStructure(timeExpr); });
        }
        public IDataStructure GetOutputStructure(IExpression expression)
        {
            IDataStructure structure  = this._dsResolver();
            IExpression    parentExpr = expression.ParentExpression;

            if (parentExpr.OperatorSymbol == "#")
            {
                StructureComponent component = parentExpr.Operands["ds_1"].Structure.Components.FirstOrDefault(comp => comp.ComponentName.GetNameWithoutAlias() == expression.ExpressionText);
                if (component == null)
                {
                    throw new VtlOperatorError(expression, this.Name, $"Component {expression.ExpressionText} has been not found in dataset {parentExpr.Operands["ds_1"].ExpressionText}.");
                }

                structure = this._dsResolver(component.ComponentName.GetNameWithoutAlias(), component.ComponentType, component.ValueDomain.DataType);
            }
            else if (parentExpr.OperatorSymbol == "unpivot")
            {
                if (expression.ParamSignature == "ds_1")
                {
                    structure = this._dsResolver(expression.ExpressionText, ComponentType.Identifier, BasicDataType.String); //string as nominal data
                }
                else
                {
                    // unpivot > datasetClause > dataset
                    if (parentExpr.ParentExpression?.Operands["ds_1"]?.Structure?.Measures.First() != null)
                    {
                        BasicDataType type = parentExpr.ParentExpression.Operands["ds_1"].Structure.Measures.First().ValueDomain.DataType;
                        structure = this._dsResolver(expression.ExpressionText, ComponentType.Measure, type);
                    }
                    else
                    {
                        structure = this._dsResolver(expression.ExpressionText, ComponentType.Measure, BasicDataType.None);
                    }
                }
            }
            else if ((parentExpr.OperatorSymbol != "calcExpr" || parentExpr.Operands["ds_1"] != expression) &&
                     (parentExpr.OperatorSymbol != "renameExpr" || parentExpr.Operands["ds_2"] != expression))
            {
                this._compTypeInference.InferTypeOfComponent(expression);
                structure = expression.Structure.GetCopy();
            }
            else
            {
                BasicDataType dataType;
                ComponentType compType;
                if (parentExpr.OperatorSymbol == "calcExpr")
                {
                    dataType = BasicDataType.None;
                    switch (parentExpr.OperatorDefinition.Keyword)
                    {
                    case "identifier": compType = ComponentType.Identifier; break;

                    case "measure": compType = ComponentType.Measure; break;

                    case "attribute": compType = ComponentType.NonViralAttribute; break;

                    case "viral attribute": compType = ComponentType.ViralAttribute; break;

                    default: throw new VtlOperatorError(expression, this.Name, $"Unknown operator keyword: {parentExpr.OperatorDefinition.Keyword}");
                    }

                    structure = this._dsResolver(expression.ExpressionText, compType, dataType);
                }
                else if (parentExpr.OperatorSymbol == "renameExpr")
                {
                    StructureComponent baseComp = parentExpr.Operands["ds_1"].Structure.Components[0];
                    dataType = baseComp.ValueDomain.DataType;
                    compType = baseComp.ComponentType;

                    structure = this._dsResolver(expression.ExpressionText, compType, dataType);
                }
                else
                {
                    throw new VtlOperatorError(expression, this.Symbol, "Unknown component type.");
                }
            }

            IRuleset ruleset = expression.ContainingSchema?.Rulesets.FirstOrDefault(ruleset => ruleset.RulesCollection.Contains(expression.GetFirstAncestorExpr() ?? expression));

            if (ruleset != null)
            {
                if (ruleset.Variables.Count > 0)
                {
                    structure.Components[0].BaseComponentName = ruleset.Variables[structure.Components[0].ComponentName];
                }
                else
                {
                    structure.Components[0].BaseComponentName = ruleset.ValueDomains[structure.Components[0].ComponentName].Signature;
                }
            }

            return(structure);
        }
        public IDataStructure GetOutputStructure(IExpression expression)
        {
            if (expression.IsApplyComponent)
            {
                expression.Operands["if"].Structure   = expression.Operands["if"].Operands["ds_1"].Structure.GetCopy();
                expression.Operands["then"].Structure = expression.Operands["then"].Operands["ds_1"].Structure.GetCopy();
                expression.Operands["else"].Structure = expression.Operands["else"].Operands["ds_1"].Structure.GetCopy();
                return(this._joinApplyMeasuresOp.GetMeasuresStructure(expression));
            }

            IDataStructure dataStructure = null;
            IExpression    ifExpr        = expression.Operands["if"];
            IExpression    thenExpr      = expression.Operands["then"];
            IExpression    elseExpr      = expression.Operands["else"];

            ifExpr.Structure   = ifExpr.OperandsCollection.First().Structure.GetCopy();
            thenExpr.Structure = thenExpr.OperandsCollection.First().Structure.GetCopy();
            elseExpr.Structure = elseExpr.OperandsCollection.First().Structure.GetCopy();

            if (ifExpr.IsScalar && ifExpr.Structure.Components[0].ValueDomain.DataType != BasicDataType.Boolean)
            {
                throw new VtlOperatorError(expression, this.Name, "Expected boolean value in condition expression.");
            }
            else if (!ifExpr.IsScalar)
            {
                if (ifExpr.Structure.Measures.Count != 1)
                {
                    throw new VtlOperatorError(expression, this.Name, "Expected single measure expression as condition.");
                }

                if (ifExpr.Structure.Measures[0].ValueDomain.DataType != BasicDataType.Boolean)
                {
                    throw new VtlOperatorError(expression, this.Name, "Expected boolean measure in condition expression.");
                }
            }

            if (!thenExpr.IsScalar)
            {
                if (elseExpr.IsScalar)
                {
                    dataStructure = thenExpr.Structure.GetCopy().WithAttributesOf(ifExpr.Structure);
                    if (thenExpr.Structure.Measures.FirstOrDefault(me => !me.ValueDomain.DataType.EqualsObj(elseExpr.Structure.Components[0].ValueDomain.DataType)) != null)
                    {
                        throw new VtlOperatorError(expression, this.Name, "All measures of thenClause data structure must have elseClause's scalar data type.");
                    }

                    // Remove none and replace ints to numbers data types when possible:
                    foreach (StructureComponent measure in dataStructure.Measures)
                    {
                        if (measure.ValueDomain.DataType.In(BasicDataType.None, BasicDataType.Integer) && elseExpr.Structure.Components[0].ValueDomain.DataType != BasicDataType.None)
                        {
                            measure.ValueDomain = new ValueDomain(elseExpr.Structure.Components[0].ValueDomain.DataType);
                        }
                    }
                }

                if (!ifExpr.IsScalar && !ifExpr.Structure.IsSupersetOf(thenExpr.Structure))
                {
                    throw new VtlOperatorError(expression, this.Name, "Datasets don't fit");
                }
            }

            if (!elseExpr.IsScalar)
            {
                if (thenExpr.IsScalar)
                {
                    dataStructure = elseExpr.Structure.GetCopy().WithAttributesOf(ifExpr.Structure);
                    if (elseExpr.Structure.Measures.FirstOrDefault(me => !me.ValueDomain.DataType.EqualsObj(thenExpr.Structure.Components[0].ValueDomain.DataType)) != null)
                    {
                        throw new VtlOperatorError(expression, this.Name, "All measures of elseClause data structure must have thenClause's scalar data type.");
                    }

                    // Remove none and replace ints to numbers data types when possible:
                    foreach (StructureComponent measure in dataStructure.Measures)
                    {
                        if (measure.ValueDomain.DataType.In(BasicDataType.None, BasicDataType.Integer) && thenExpr.Structure.Components[0].ValueDomain.DataType != BasicDataType.None)
                        {
                            measure.ValueDomain = new ValueDomain(thenExpr.Structure.Components[0].ValueDomain.DataType);
                        }
                    }
                }

                if (!ifExpr.IsScalar && !ifExpr.Structure.IsSupersetOf(elseExpr.Structure))
                {
                    throw new VtlOperatorError(expression, this.Name, "Datasets don't fit");
                }
            }

            if (!thenExpr.IsScalar && !elseExpr.IsScalar)
            {
                bool thenStructure = thenExpr.Structure.IsSupersetOf(elseExpr.Structure, true, false, true);

                if (thenStructure)
                {
                    dataStructure = thenExpr.Structure.GetCopy().WithAttributesOf(ifExpr.Structure).WithAttributesOf(elseExpr.Structure);
                }
                else if (elseExpr.Structure.IsSupersetOf(thenExpr.Structure, true, false, true))
                {
                    dataStructure = elseExpr.Structure.GetCopy().WithAttributesOf(ifExpr.Structure).WithAttributesOf(thenExpr.Structure);
                }
                else
                {
                    throw new VtlOperatorError(expression, this.Name, "Datasets don't fit");
                }

                // Remove none and replace ints to numbers data types when possible:
                for (int i = 0; i < dataStructure.Measures.Count; i++)
                {
                    StructureComponent measure = dataStructure.Measures[i];
                    if (measure.ValueDomain.DataType.In(BasicDataType.None, BasicDataType.Integer))
                    {
                        if (thenStructure && elseExpr.Structure.Measures[i].ValueDomain.DataType != BasicDataType.None)
                        {
                            measure.ValueDomain = new ValueDomain(elseExpr.Structure.Measures[i].ValueDomain.DataType);
                        }
                        else if (thenExpr.Structure.Measures[i].ValueDomain.DataType != BasicDataType.None)
                        {
                            measure.ValueDomain = new ValueDomain(thenExpr.Structure.Measures[i].ValueDomain.DataType);
                        }
                    }
                }
            }
            else if (thenExpr.IsScalar && elseExpr.IsScalar &&
                     !thenExpr.Structure.Components[0].ValueDomain.DataType.EqualsObj(elseExpr.Structure.Components[0].ValueDomain.DataType))
            {
                throw new VtlOperatorError(expression, this.Name, "ThenClause and ElseClause scalar data types are not the same.");
            }

            if (dataStructure != null)
            {
                return(dataStructure);
            }
            else if (!ifExpr.IsScalar)
            {
                if (thenExpr.Structure.Components[0].ValueDomain.DataType != BasicDataType.Boolean ||
                    elseExpr.Structure.Components[0].ValueDomain.DataType != BasicDataType.Boolean)
                {
                    throw new VtlOperatorError(expression, this.Name, "Expected boolean values in thenClause and elseClause.");
                }

                return(ifExpr.Structure.GetCopy());
            }

            BasicDataType type = thenExpr.Structure.Components[0].ValueDomain.DataType;

            if (type.In(BasicDataType.Integer, BasicDataType.None) && elseExpr.Structure.Components[0].ValueDomain.DataType != BasicDataType.None)
            {
                type = elseExpr.Structure.Components[0].ValueDomain.DataType;
            }
            return(this._dsResolver(type.GetVariableName(), ComponentType.Measure, type));
        }
        public IDataStructure GetOutputStructure(IExpression expression)
        {
            if (expression.IsApplyComponent)
            {
                return(this._joinApplyMeasuresOp.GetMeasuresStructure(expression));
            }

            IDataStructure structure;
            IDataStructure ds1 = expression.OperandsCollection.ToArray()[0].Structure.GetCopy();
            IDataStructure ds2 = expression.OperandsCollection.ToArray()[1].Structure.GetCopy();

            if (!ds1.IsSingleComponent && ds1.Measures.Count > 1)
            {
                throw new VtlOperatorError(expression, this.Name, "Expected single measure structure.");
            }
            if (!ds2.IsSingleComponent && ds2.Measures.Count > 1)
            {
                throw new VtlOperatorError(expression, this.Name, "Expected single measure structure.");
            }
            if (!ds1.IsSingleComponent && !ds2.IsSingleComponent)
            {
                if (!ds1.IsSupersetOf(ds2, true, false, true) && !ds2.IsSupersetOf(ds1, true, false, true))
                {
                    throw new VtlOperatorError(expression, this.Name, "Datasets doesn't fit.");
                }

                if (!ds1.Measures[0].ValueDomain.DataType.In(BasicDataType.None, BasicDataType.Integer) || ds2.Measures[0].ValueDomain.DataType == BasicDataType.None)
                {
                    structure = ds1.WithAttributesOf(ds2);
                }
                else
                {
                    structure = ds2.WithAttributesOf(ds1);
                }

                return(structure);
            }

            if (!ds1.IsSingleComponent || !ds2.IsSingleComponent)
            {
                structure = ds1.GetCopy().WithAttributesOf(ds2);
                BasicDataType scalarType = ds2.Components[0].ValueDomain.DataType;
                if (!ds2.IsSingleComponent)
                {
                    structure  = ds2.GetCopy().WithAttributesOf(ds1);
                    scalarType = ds1.Components[0].ValueDomain.DataType;
                }

                if (!structure.Measures[0].ValueDomain.DataType.EqualsObj(scalarType))
                {
                    throw new VtlOperatorError(expression, this.Name, "Data types of parameters are not equal.");
                }

                if (structure.Measures[0].ValueDomain.DataType.In(BasicDataType.None, BasicDataType.Integer) && scalarType != BasicDataType.None)
                {
                    structure.Measures[0].ValueDomain = new ValueDomain(scalarType);
                }
                return(structure);
            }

            if (!ds1.Components[0].ValueDomain.DataType.EqualsObj(ds2.Components[0].ValueDomain.DataType))
            {
                throw new VtlOperatorError(expression, this.Name, "Data types of parameters are not equal.");
            }

            if (!ds1.Components[0].ValueDomain.DataType.In(BasicDataType.None, BasicDataType.Integer) || ds2.Components[0].ValueDomain.DataType == BasicDataType.None)
            {
                structure = ds1.WithAttributesOf(ds2);
            }
            else
            {
                structure = ds2.WithAttributesOf(ds1);
            }

            return(structure);
        }