public IDataStructure GetOutputStructure(IExpression expression)
        {
            if (expression.IsApplyComponent)
            {
                return(this._joinApplyMeasuresOp.GetMeasuresStructure(expression));
            }

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

            if (!ds1.IsNumericStructure(true) || !ds2.IsNumericStructure(true))
            {
                throw new VtlOperatorError(expression, this.Name, "Expected numeric components.");
            }

            if (!ds1.IsSingleComponent && ds2.IsSingleComponent)
            {
                return(NumericStructure.GetDatasetScalarMixedStructure(ds1, ds2));
            }
            else if (ds1.IsSingleComponent && !ds2.IsSingleComponent)
            {
                return(NumericStructure.GetDatasetScalarMixedStructure(ds2, ds1));
            }
            else if (!ds1.IsSingleComponent && !ds2.IsSingleComponent)
            {
                IDataStructure structure;

                if (ds1.IsSupersetOf(ds2, true, false, true))
                {
                    structure = NumericStructure.GetDatasetsMixedStructure(ds1.WithAttributesOf(ds2), ds2);
                }
                else if (ds2.IsSupersetOf(ds1, true, false, true))
                {
                    structure = NumericStructure.GetDatasetsMixedStructure(ds2.WithAttributesOf(ds1), ds1);
                }
                else
                {
                    throw new VtlOperatorError(expression, this.Name, "Structures of datasets don't match.");
                }

                return(structure);
            }

            if (!ds1.Components[0].ValueDomain.DataType.In(BasicDataType.Integer, BasicDataType.Number, BasicDataType.None) ||
                !ds2.Components[0].ValueDomain.DataType.In(BasicDataType.Integer, BasicDataType.Number, BasicDataType.None))
            {
                throw new VtlOperatorError(expression, this.Name, "Expected numeric scalar values.");
            }

            if (ds2.Components[0].ValueDomain.DataType == BasicDataType.Number)
            {
                return(ds2.GetCopy());
            }
            return(ds1.GetCopy());
        }
        /// <summary>
        /// Gets a fused structure from a given dataset and a scalar.
        /// </summary>
        /// <param name="dataset">The dataset.</param>
        /// <param name="scalar">The scalar.</param>
        /// <returns>The data structure.</returns>
        public static IDataStructure GetDatasetScalarMixedStructure(IDataStructure dataset, IDataStructure scalar)
        {
            IDataStructure ds = dataset.GetCopy();

            foreach (StructureComponent measure in ds.Measures)
            {
                if (scalar.Components[0].ValueDomain.DataType == BasicDataType.Number)
                {
                    measure.ValueDomain = new ValueDomain(BasicDataType.Number);
                }
                if (measure.ValueDomain.DataType == BasicDataType.None)
                {
                    measure.ValueDomain = new ValueDomain(BasicDataType.Integer);
                }
            }

            return(ds);
        }
        /// <summary>
        /// Gets a fused structure from a given super dataset and a sub dataset.
        /// </summary>
        /// <param name="superset">The super dataset.</param>
        /// <param name="subset">The subset.</param>
        /// <returns>The data structure.</returns>
        public static IDataStructure GetDatasetsMixedStructure(IDataStructure superset, IDataStructure subset)
        {
            IDataStructure result = superset.GetCopy();

            result.Measures.Clear();

            for (int i = 0; i < superset.Measures.Count; i++)
            {
                StructureComponent measure = new StructureComponent(superset.Measures[i].ValueDomain.DataType, superset.Measures[i].ComponentName);
                result.Measures.Add(measure);
                if (subset.Measures[i].ValueDomain.DataType == BasicDataType.Number)
                {
                    measure.ValueDomain = new ValueDomain(BasicDataType.Number);
                }
                if (measure.ValueDomain.DataType == BasicDataType.None)
                {
                    measure.ValueDomain = new ValueDomain(BasicDataType.Integer);
                }
            }

            return(result);
        }
        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);
        }