public string Transform(string toTransformFileName)
        {
            FileStream fileToTransformStream;

            try
            {
                var inputFile = new FileInfo(toTransformFileName);
                fileToTransformStream = new FileStream(inputFile.FullName, FileMode.Open);
            }
            catch (Exception e)
            {
                var exceptionMessage = String.Format("Unable to open data file: {0}\n{1}", toTransformFileName, e);
                throw new DataTransformationException(exceptionMessage);
            }

            var entity = new EntityData {
                                            Attributes = _dataMapping.Attributes
                                        };

            using (var input = new StreamReader(fileToTransformStream))
            {
                EvalInputFrom(input, entity);
            }

            SetCategoryAsALastAttribute(entity);

            var fileWithoutExtension = Path.GetFileNameWithoutExtension(toTransformFileName);

            var transformedDataFileName = String.Format("{0}.xml", fileWithoutExtension);
            DataSerializer.Serialize(entity, transformedDataFileName);

            return transformedDataFileName;
        }
        public Outcome Validate(EntityData entityData)
        {
            var outcome = new Outcome
                          {
                              IsFailure = entityData.Attributes.Any(string.IsNullOrEmpty)
                          };

            if (outcome.IsFailure)
            {
                outcome.Message = ArgumentsCannotBeNullOrEmpty;
                return outcome;
            }

            var attributesCount = entityData.Attributes.Count;

            outcome.IsFailure = entityData.Data.Any(d => d.Values.Count != attributesCount);

            if (outcome.IsFailure)
            {
                outcome.Message = string.Format("{0} Attributes count: {1}.", ValuesMustHaveTheSameAmountOfValuesAsTheAttributes,
                                                attributesCount);
                return outcome;
            }

            outcome.IsFailure = entityData.Data.SelectMany(d => d.Values).Any(string.IsNullOrEmpty);
            if (outcome.IsFailure)
            {
                outcome.Message = ValuesCannotBeNullOrEmpty;
                return outcome;
            }

            return outcome;
        }
        private static void EvalInputFrom(EntityData entityData, IDomainTree domainTree)
        {
            foreach (var dataRow in entityData.Data)
            {
                var domainSymbolicAttributes = AttributeSymbolicValues.CreateIt(domainTree.Attributes.Count);

                for (var attributeId = 0; attributeId < domainTree.Attributes.Count; attributeId++)
                    domainSymbolicAttributes.Values[attributeId] = GetSymbolValue(domainTree, attributeId,
                                                                                              dataRow.Values[attributeId]);

                domainTree.Root.Data.Add(domainSymbolicAttributes);
            }
        }
        internal static EntityData GetEntityDataWithEmptyArgument()
        {
            var entityData = new EntityData();

            entityData.Attributes.Add("Span");
            entityData.Attributes.Add("");
            entityData.Attributes.Add("Slab");

            entityData.Data.Add(GetFirstValidRow());
            entityData.Data.Add(GetSecondValidDataRow());
            entityData.Data.Add(GetThirdValidDataRow());
            entityData.Data.Add(GetFourthValidDataRow());

            return entityData;
        }
        // Span;Shape;Slab
        //******************************
        // long;square;waffle
        // long;rectangle;waffle
        // short;square;two-way
        // short;rectangle;one-way
        internal static EntityData GetFullEntityData()
        {
            var entityData = new EntityData();

            entityData.Attributes.Add("Span");
            entityData.Attributes.Add("Shape");
            entityData.Attributes.Add("Slab");

            entityData.Data.Add(GetFirstValidRow());
            entityData.Data.Add(GetSecondValidDataRow());
            entityData.Data.Add(GetThirdValidDataRow());
            entityData.Data.Add(GetFourthValidDataRow());

            return entityData;
        }
        internal static EntityData GetEntityDataWithMismatchCountOfAttributesAndValues()
        {
            var entityData = new EntityData();

            entityData.Attributes.Add("Span");
            entityData.Attributes.Add("Shape");
            entityData.Attributes.Add("Slab");

            entityData.Data.Add(GetFirstValidRow());
            entityData.Data.Add(GetSecondValidDataRow());
            entityData.Data.Add(GetThirdInValidDataRow());
            entityData.Data.Add(GetFourthValidDataRow());

            return entityData;
        }
        public IDomainTree Load(EntityData entityData)
        {
            var outcome = _validator.Validate(entityData);

            if (outcome.IsFailure)
                throw new DataValidationException(outcome.Message);

            IDomainTree domainTree = new DomainTree();

            var domainAttributesCount = entityData.Attributes.Count;

            var attributesBuffer = new string[domainAttributesCount];
            entityData.Attributes.CopyTo(attributesBuffer);
            domainTree.Attributes = new List<string>(attributesBuffer);

            for (var i = 0; i < domainAttributesCount; i++)
                domainTree.Domain.Add(new List<string>());

            EvalInputFrom(entityData, domainTree);

            return domainTree;
        }
        private void EvalInputFrom(TextReader reader, EntityData entity)
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                if (line.StartsWith("//"))
                    continue;
                if (line.Equals(""))
                    continue;

                var values = SplitInput(line);

                if (values.Length != entity.Attributes.Count)
                {
                    var exceptionMessage = String.Format("Read {0} data\nLast line read: {1}\nExpecting {2} attributes", values.Length, line,
                                                         entity.Attributes.Count);

                    throw new DataTransformationException(exceptionMessage);
                }

                var dataRow = new DataRow();

                for (var attributeId = 0; attributeId < entity.Attributes.Count; attributeId++)
                    dataRow.Values.Add(values[attributeId]);

                entity.Data.Add(dataRow);
            }
        }
        private void SetCategoryAsALastAttribute(EntityData entity)
        {
            var indexOfCategory = entity.Attributes.IndexOf(_dataMapping.Category);
            var lastAttributeIndex = entity.Attributes.Count - 1;

            if (indexOfCategory == lastAttributeIndex)
                return;

            ReverseElementsOf(entity.Attributes, indexOfCategory, lastAttributeIndex);

            foreach (var dataRow in entity.Data)
                ReverseElementsOf(dataRow.Values, indexOfCategory, lastAttributeIndex);
        }