Пример #1
0
        public void ProcessEquity( string dateFormat, string equityMembersXml, ITraceMessenger messenger )
        {
            //we can't create the special equity layout without both beginning and ending balances
            //if there are none, exit early.
            XmlDocument membersXDoc;
            ValidateEquityStructure( equityMembersXml, out membersXDoc );

            //ensure that all rows/columns/cells are in sync
            this.SynchronizeGrid();

            /**
             * Consider the possible SQL statement as a model for this process:
             *
             * SELECT [Element values by Segment]
             * FROM [Equity Statement]
             * GROUP BY [Reporting Period]
             * ORDER BY [Element Presentation Id]
             *
             **/
            EquityDataSet dataSet = new EquityDataSet( membersXDoc );

            //#1 - this will be our X axis - a set of unique segments and scenarios, minus adjustments and previously reported
            dataSet.LoadSegmentScenarioColumns( this );

            //#2 - this will be the GROUPING for our Y axis - a set of unique calendars
            dataSet.LoadCalendarColumns( this );

            //#3 - Get each type of row role so that we can control the position
            dataSet.LoadRowTypes( this );

            if( !dataSet.PopulateEquityReport( this ) )
                throw new IncompleteEquityException( IncompleteEquityException.ErrorType.Incomplete );

            //ensure that all rows/columns/cells are in sync
            dataSet.EquityCandidate.SynchronizeGrid();
            dataSet.CleanupEquityColumns();
            dataSet.CleanupEquityRows( dateFormat, membersXDoc );

            //repair any elements or segments which might not fit the preferred rendering
            dataSet.EquityCandidate.SynchronizeGrid();
            dataSet.AdjustEquityPeriods( this );
            if( dataSet.EquityCandidate.Columns.Count == 0 || dataSet.EquityCandidate.Rows.Count == 0 )
                throw new IncompleteEquityException( IncompleteEquityException.ErrorType.Incomplete );

            this.Columns.Clear();
            this.Columns.AddRange( dataSet.EquityCandidate.Columns );

            this.Rows.Clear();
            this.Rows.AddRange( dataSet.EquityCandidate.Rows );

            this.Footnotes.Clear();
            this.Footnotes.AddRange( dataSet.EquityCandidate.Footnotes );

            //ensure that all rows/columns/cells are in sync
            this.SynchronizeGrid();

            this.PromoteCurrencyCode();
        }
Пример #2
0
        private void ProcessRoundingLevel(ITraceMessenger messenger)
        {
            bool isRuleEnabled = this.FireRuleProcessing(RulesEngineUtils.ROUNDING_RULE);

            if (isRuleEnabled)
            {
                Dictionary <string, object> contextObjects = new Dictionary <string, object>();
                contextObjects.Add("InstanceReport", this);
                contextObjects.Add("messenger", messenger);
                builderRules.ProcessRule(RulesEngineUtils.ROUNDING_RULE, contextObjects);

                this.FireRuleProcessed(RulesEngineUtils.ROUNDING_RULE);
            }
        }
Пример #3
0
        private bool ProcessEquitySegments(ITraceMessenger messenger)
        {
            bool isRuleEnabled = this.FireRuleProcessing(RulesEngineUtils.EQUITY_STATEMENT_RULE);

            if (isRuleEnabled)
            {
                Dictionary <string, object> contextObjects = new Dictionary <string, object>();
                contextObjects.Add("InstanceReport", this);
                contextObjects.Add("messenger", messenger);

                IBRERuleResult ruleResult;
                builderRules.ProcessRule(RulesEngineUtils.EQUITY_STATEMENT_RULE, contextObjects, out ruleResult);
                this.FireRuleProcessed(RulesEngineUtils.EQUITY_STATEMENT_RULE);

                Exception outerException = ruleResult.Result as Exception;
                if (outerException != null)
                {
                    IncompleteEquityException equityEx = outerException.InnerException as IncompleteEquityException;
                    if (equityEx != null && messenger != null)
                    {
                        switch (equityEx.Type)
                        {
                        case IncompleteEquityException.ErrorType.Incomplete:
                            messenger.TraceError("Error: The equity rendering routine did not create any data for " + this.ReportLongName + "." +
                                                 Environment.NewLine + "The equity statement will use the basic rendering.");
                            break;

                        case IncompleteEquityException.ErrorType.MissingBeginningBalance:
                            messenger.TraceWarning("Warning: The equity rendering routine was not applied to " + this.ReportLongName + "." +
                                                   Environment.NewLine + "None of the elements feature the 'periodStartLabel' preferred label role.");
                            break;

                        case IncompleteEquityException.ErrorType.MissingEndingBalance:
                            messenger.TraceWarning("Warning: The equity rendering routine was not applied to " + this.ReportLongName + "." +
                                                   Environment.NewLine + "None of the elements feature the 'periodEndLabel' preferred label role.");
                            break;
                        }
                    }

                    return(false);
                }
            }

            return(true);
        }
Пример #4
0
        private void ProcessRounding(ITraceMessenger messenger)
        {
            ProcessRoundingLevel(messenger);

            bool hasMonetary = this.MonetaryRoundingLevel > RoundingLevel.NoRounding;
            bool hasShares   = this.SharesRoundingLevel > RoundingLevel.NoRounding;
            bool hasPerShare = this.PerShareRoundingLevel > RoundingLevel.NoRounding;

            if (hasMonetary || hasShares || hasPerShare)
            {
                decimal monetaryDivisor     = GetRoundingDivisor(this.MonetaryRoundingLevel);
                decimal sharesDivisor       = GetRoundingDivisor(this.SharesRoundingLevel);
                decimal perSharesDivisor    = GetRoundingDivisor(this.PerShareRoundingLevel);
                decimal exchangeRateDivisor = GetRoundingDivisor(this.ExchangeRateRoundingLevel);

                //Process rounded values - monetary
                this.Rows.FindAll(row => row.IsMonetary).ForEach(
                    row => row.ApplyRounding(monetaryDivisor));

                //Process rounded values - shares
                this.Rows.FindAll(row => row.IsShares).ForEach(
                    row => row.ApplyRounding(sharesDivisor));

                //Process rounded values - EPS
                this.Rows.FindAll(row => row.IsEPS).ForEach(
                    row => row.ApplyRounding(perSharesDivisor));

                //Process rounded values - Exchange rate
                this.Rows.FindAll(row => row.IsExchangeRate).ForEach(
                    row => row.ApplyRounding(exchangeRateDivisor));

                this.Rows.FindAll(row => row.Unit == 0 || row.Unit > UnitType.StandardUnits).ForEach(
                    row => row.ApplyRounding(1));
            }
            else
            {
                this.Rows.ForEach(
                    row => row.Cells.ForEach(
                        cell => cell.RoundedNumericAmount = cell.NumericAmount.ToString()
                        )
                    );
            }
        }
Пример #5
0
        private bool ProcessEquitySegments( ITraceMessenger messenger )
        {
            bool isRuleEnabled = this.FireRuleProcessing( RulesEngineUtils.EQUITY_STATEMENT_RULE );
            if( isRuleEnabled )
            {
                Dictionary<string, object> contextObjects = new Dictionary<string, object>();
                contextObjects.Add( "InstanceReport", this );
                contextObjects.Add( "messenger", messenger );

                IBRERuleResult ruleResult;
                builderRules.ProcessRule( RulesEngineUtils.EQUITY_STATEMENT_RULE, contextObjects, out ruleResult );
                this.FireRuleProcessed( RulesEngineUtils.EQUITY_STATEMENT_RULE );

                Exception outerException = ruleResult.Result as Exception;
                if( outerException != null )
                {
                    IncompleteEquityException equityEx = outerException.InnerException as IncompleteEquityException;
                    if( equityEx != null && messenger != null )
                    {
                        switch( equityEx.Type )
                        {
                            case IncompleteEquityException.ErrorType.Incomplete:
                                messenger.TraceError( "Error: The equity rendering routine did not create any data for " + this.ReportLongName + "." +
                                    Environment.NewLine + "The equity statement will use the basic rendering." );
                                break;
                            case IncompleteEquityException.ErrorType.MissingBeginningBalance:
                                messenger.TraceWarning( "Warning: The equity rendering routine was not applied to " + this.ReportLongName + "." +
                                    Environment.NewLine + "None of the elements feature the 'periodStartLabel' preferred label role." );
                                break;
                            case IncompleteEquityException.ErrorType.MissingEndingBalance:
                                messenger.TraceWarning( "Warning: The equity rendering routine was not applied to " + this.ReportLongName + "." +
                                    Environment.NewLine + "None of the elements feature the 'periodEndLabel' preferred label role." );
                                break;
                        }
                    }

                    return false;
                }
            }

            return true;
        }
        public void EvaluateRoundingLevels( ITraceMessenger messenger )
        {
            this.HasCustomUnits = false;
            Dictionary<UnitType, RoundingLevel> selectedRounding = new Dictionary<UnitType, RoundingLevel>();
            foreach( int unit in this.UnitDictionary.Keys )
            {
                UnitType ut = (UnitType)unit;
                selectedRounding[ ut ] = RoundingLevel.UnKnown;

                List<InstanceReportRow> unitRows = this.Rows.FindAll( row => row.Unit == ut );
                if( unitRows.Count == 0 )
                    continue;

                if( !this.HasCustomUnits )
                {
                    switch( ut )
                    {
                        case UnitType.EPS:
                        case UnitType.ExchangeRate:
                        case UnitType.Monetary:
                        case UnitType.Shares:
                            break;
                        default:
                            this.HasCustomUnits = true;
                            break;
                    }
                }

                foreach( InstanceReportRow row in unitRows )
                {
                    if( row.MyPrecision == null )
                        continue;

                    //Numeric data that is Nill for all values will not have a precision
                    //defined, so we don't want to include these rows in our processing logic
                    if( row.IsNumericDataNil() )
                        continue;

                    RoundingLevel currentRounding = InstanceUtils.GetRoundingLevelFromPrecision( row.MyPrecision );
                    selectedRounding[ ut ] = this.SelectRoundingLevel( row.Unit, selectedRounding[ row.Unit ], currentRounding, row.ElementName, messenger );

                    if( selectedRounding[ ut ] > RoundingLevel.NoRounding )
                    {
                        double factor = Math.Pow( 10, row.MyPrecision.NumberOfDigits * -1 );
                        foreach( Cell cell in row.Cells )
                        {
                            if( cell.IsNil )
                                continue;

                            if( !cell.HasData || cell.NumericAmount == 0 )
                                continue;

                            if( Math.Abs( (double)cell.NumericAmount ) < factor )
                            {
                                selectedRounding[ row.Unit ] = RoundingLevel.NoRounding;
                                break;
                            }
                        }
                    }

                    if( selectedRounding[ row.Unit ] == RoundingLevel.NoRounding )
                        break;
                }
            }

            this.MonetaryRoundingLevel = RoundingLevel.UnKnown;
            if( selectedRounding.ContainsKey( UnitType.Monetary ) )
                this.MonetaryRoundingLevel = selectedRounding[ UnitType.Monetary ];

            this.SharesRoundingLevel = RoundingLevel.UnKnown;
            if( selectedRounding.ContainsKey( UnitType.Shares ) )
                this.SharesRoundingLevel = selectedRounding[ UnitType.Shares ];

            this.PerShareRoundingLevel = RoundingLevel.UnKnown;
            if( selectedRounding.ContainsKey( UnitType.EPS ) )
                this.PerShareRoundingLevel = selectedRounding[ UnitType.EPS ];

            this.ExchangeRateRoundingLevel = RoundingLevel.UnKnown;
            if( selectedRounding.ContainsKey( UnitType.ExchangeRate ) )
                this.ExchangeRateRoundingLevel = selectedRounding[ UnitType.ExchangeRate ];
        }
        private RoundingLevel SelectRoundingLevel( UnitType unitType, RoundingLevel unitTypeRounding, RoundingLevel elementRounding, string elementName, ITraceMessenger messenger )
        {
            string typeName = string.Empty;
            switch( unitType )
            {
                case UnitType.Monetary:
                    typeName = "Monetary";
                    break;
                case UnitType.Shares:
                    typeName = "Shares";
                    break;
                case UnitType.EPS:
                    typeName = "Per Share";
                    break;
                case UnitType.ExchangeRate:
                    typeName = "Exchange Rate";
                    break;
            }

            if( unitTypeRounding == RoundingLevel.UnKnown )
            {
                //If sharesRounding has not been set yet then set the value equal to the
                //value of the current row
                return elementRounding;
            }
            else if( !AreRoundingLevelsEquivalent( unitTypeRounding, elementRounding ) )
            {
                if( messenger != null )
                {
                    string info = "'" + typeName + "' elements on report '" + this.ReportLongName + "' had a mix of different decimal attribute values.";
                    messenger.TraceInformation( info );
                }

                //Make sure the rounding level on the current row matches
                //the rounding of the previous rows
                return RoundingLevel.NoRounding;
            }
            else if( elementRounding < unitTypeRounding )
            {
                if( elementRounding == RoundingLevel.NoRounding || elementRounding == RoundingLevel.UnKnown )
                {
                    if( messenger != null )
                    {
                        string info = "'" + typeName + "' elements on report '" + this.ReportLongName + "' had a mix of different decimal attribute values.";
                        messenger.TraceInformation( info );
                    }
                }

                //The rounding levels are equivalent, now make sure we use the
                //"Lowest" equivalent RoundingLevel
                return elementRounding;
            }

            return unitTypeRounding;
        }
        private void ProcessRoundingLevel( ITraceMessenger messenger )
        {
            bool isRuleEnabled = this.FireRuleProcessing( RulesEngineUtils.ROUNDING_RULE );
            if( isRuleEnabled )
            {
                Dictionary<string, object> contextObjects = new Dictionary<string, object>();
                contextObjects.Add( "InstanceReport", this );
                contextObjects.Add( "messenger", messenger );
                builderRules.ProcessRule( RulesEngineUtils.ROUNDING_RULE, contextObjects );

                this.FireRuleProcessed( RulesEngineUtils.ROUNDING_RULE );
            }
        }
        private void ProcessRounding( ITraceMessenger messenger )
        {
            ProcessRoundingLevel( messenger );

            bool hasMonetary = this.MonetaryRoundingLevel > RoundingLevel.NoRounding;
            bool hasShares = this.SharesRoundingLevel > RoundingLevel.NoRounding;
            bool hasPerShare = this.PerShareRoundingLevel > RoundingLevel.NoRounding;

            if( hasMonetary || hasShares || hasPerShare )
            {
                decimal monetaryDivisor = GetRoundingDivisor( this.MonetaryRoundingLevel );
                decimal sharesDivisor = GetRoundingDivisor( this.SharesRoundingLevel );
                decimal perSharesDivisor = GetRoundingDivisor( this.PerShareRoundingLevel );
                decimal exchangeRateDivisor = GetRoundingDivisor( this.ExchangeRateRoundingLevel );

                //Process rounded values - monetary
                this.Rows.FindAll( row => row.IsMonetary ).ForEach(
                    row => row.ApplyRounding( monetaryDivisor ) );

                //Process rounded values - shares
                this.Rows.FindAll( row => row.IsShares ).ForEach(
                    row => row.ApplyRounding( sharesDivisor ) );

                //Process rounded values - EPS
                this.Rows.FindAll( row => row.IsEPS ).ForEach(
                    row => row.ApplyRounding( perSharesDivisor ) );

                //Process rounded values - Exchange rate
                this.Rows.FindAll( row => row.IsExchangeRate ).ForEach(
                    row => row.ApplyRounding( exchangeRateDivisor ) );

                this.Rows.FindAll( row => row.Unit == 0 || row.Unit > UnitType.StandardUnits ).ForEach(
                    row => row.ApplyRounding( 1 ) );
            }
            else
            {
                this.Rows.ForEach(
                    row => row.Cells.ForEach(
                        cell => cell.RoundedNumericAmount = cell.NumericAmount.ToString()
                    )
                );
            }
        }
Пример #10
0
        private bool ApplyRowStylesHierarchically( int depth, ref int r,
			LinkedListNode<CommandIterator> iteratorNode, Stack<CommandIterator> iteratorHierarchy,
			bool hasUnitCell, ITraceMessenger messenger )
        {
            if( iteratorNode == null )
            {
                InstanceReportRow row = this.Rows[ r ];
                row.Level = depth;

                foreach( CommandIterator ci in iteratorHierarchy )
                {
                    if( ci.Style == CommandIterator.StyleType.Grouped )
                    {
                        row.EmbedRequirements.HideLabel( ci, ci.SelectionString );
                    }
                }
                row.GenerateEmbedLabel();

                if( row.Label.Trim() == string.Empty )
                    ShowLastNonDefaultLabel( depth, iteratorHierarchy, row );

                //if( row.Label.Trim() == string.Empty )
                //{
                //    InstanceReportRow prevRow = null;
                //    for( int pr = r - 1; pr > 0; pr-- )
                //    {
                //        prevRow = this.Rows[ pr ];
                //        if( IsMemberGroupRow( prevRow ) )
                //        {
                //            ShowLastNonDefaultLabel( depth, iteratorHierarchy, row );
                //            break;
                //        }
                //    }
                //}

                return true;
            }

            CommandIterator iterator = iteratorNode.Value;
            if( iterator.Style != CommandIterator.StyleType.Grouped ||
                iterator.Selection != CommandIterator.SelectionType.Axis )
            {
                return this.ApplyRowStylesHierarchically( depth, ref r, iteratorNode.Next, iteratorHierarchy, hasUnitCell, messenger );
            }

            Segment defaultMember = this.AxisMemberDefaults.ContainsKey( iterator.AxisName ) ?
                this.AxisMemberDefaults[ iterator.AxisName ] : null;
            if( defaultMember == null )
            {
                if( messenger != null )
                {
                    //Keyword ‘grouped’ has [...] no impact on a ‘primary’ axis
                    //Keyword ‘grouped’ reverts to the same treatment as ‘compact’ when its axis has no default member.
                    messenger.TraceWarning( "Warning: Default member is missing for '" + iterator.AxisName + "'." + Environment.NewLine + "The keyword ‘grouped’ reverts to the same treatment as ‘compact’ when its axis has no default member." );
                }

                return this.ApplyRowStylesHierarchically( depth, ref r, iteratorNode.Next, iteratorHierarchy, hasUnitCell, messenger );
            }

            KeyValuePair<string, object> memberGroupValue = new KeyValuePair<string, object>();
            Dictionary<string, object> matchValues = CreateHierarchicalDictionary( this.Rows[ r ], iteratorHierarchy );
            for( ; r < this.Rows.Count; )
            {
                InstanceReportRow row = this.Rows[ r ];
                row.Level = depth;

                KeyValuePair<string, object> member = row.EmbedRequirements.GetMemberKeyValue( iterator );
                if( !RowMatchesHierarchy( row, iteratorHierarchy, matchValues ) )
                    return false;

                int cmp = Comparer<object>.Default.Compare( memberGroupValue.Value, member.Value );
                if( cmp != 0 )
                {
                    memberGroupValue = member;
                    InstanceReportRow memberRow = this.CreateStyleRow( depth, iterator, member.Value );
                    this.Rows.Insert( r++, memberRow );
                }

                iteratorHierarchy.Push( iterator );

                if( this.ApplyRowStylesHierarchically( depth + 1, ref r, iteratorNode.Next, iteratorHierarchy, hasUnitCell, messenger ) )
                    r++;

                iteratorHierarchy.Pop();
            }

            return true;
        }
Пример #11
0
 private void ApplyRowStyles( CommandIterator[] rowIterators, ITraceMessenger messenger )
 {
     int r = 0;
     int depth = 0;
     Stack<CommandIterator> iteratorHierarchy = new Stack<CommandIterator>();
     LinkedList<CommandIterator> iterators = new LinkedList<CommandIterator>( rowIterators );
     bool hasUnitCell = Array.Exists( rowIterators, itr => itr.Style == CommandIterator.StyleType.UnitCell );
     this.ApplyRowStylesHierarchically( depth, ref r, iterators.First, iteratorHierarchy, hasUnitCell, messenger );
 }
Пример #12
0
        //TODO make private
        public void ProcessIteratorsHierarchically(LinkedList <CommandIterator> iterators, ITraceMessenger messenger)
        {
            Stack <CommandIterator> iteratorHierarchy = new Stack <CommandIterator>();

            ProcessIteratorsHierarchically(iterators.First, iteratorHierarchy, messenger);
        }
Пример #13
0
        private RoundingLevel SelectRoundingLevel(UnitType unitType, RoundingLevel unitTypeRounding, RoundingLevel elementRounding, string elementName, ITraceMessenger messenger)
        {
            string typeName = string.Empty;

            switch (unitType)
            {
            case UnitType.Monetary:
                typeName = "Monetary";
                break;

            case UnitType.Shares:
                typeName = "Shares";
                break;

            case UnitType.EPS:
                typeName = "Per Share";
                break;

            case UnitType.ExchangeRate:
                typeName = "Exchange Rate";
                break;
            }

            if (unitTypeRounding == RoundingLevel.UnKnown)
            {
                //If sharesRounding has not been set yet then set the value equal to the
                //value of the current row
                return(elementRounding);
            }
            else if (!AreRoundingLevelsEquivalent(unitTypeRounding, elementRounding))
            {
                if (messenger != null)
                {
                    string info = "'" + typeName + "' elements on report '" + this.ReportLongName + "' had a mix of different decimal attribute values.";
                    messenger.TraceInformation(info);
                }

                //Make sure the rounding level on the current row matches
                //the rounding of the previous rows
                return(RoundingLevel.NoRounding);
            }
            else if (elementRounding < unitTypeRounding)
            {
                if (elementRounding == RoundingLevel.NoRounding || elementRounding == RoundingLevel.UnKnown)
                {
                    if (messenger != null)
                    {
                        string info = "'" + typeName + "' elements on report '" + this.ReportLongName + "' had a mix of different decimal attribute values.";
                        messenger.TraceInformation(info);
                    }
                }

                //The rounding levels are equivalent, now make sure we use the
                //"Lowest" equivalent RoundingLevel
                return(elementRounding);
            }

            return(unitTypeRounding);
        }
Пример #14
0
        public void EvaluateRoundingLevels(ITraceMessenger messenger)
        {
            this.HasCustomUnits = false;
            Dictionary <UnitType, RoundingLevel> selectedRounding = new Dictionary <UnitType, RoundingLevel>();

            foreach (int unit in this.UnitDictionary.Keys)
            {
                UnitType ut = (UnitType)unit;
                selectedRounding[ut] = RoundingLevel.UnKnown;

                List <InstanceReportRow> unitRows = this.Rows.FindAll(row => row.Unit == ut);
                if (unitRows.Count == 0)
                {
                    continue;
                }

                if (!this.HasCustomUnits)
                {
                    switch (ut)
                    {
                    case UnitType.EPS:
                    case UnitType.ExchangeRate:
                    case UnitType.Monetary:
                    case UnitType.Shares:
                        break;

                    default:
                        this.HasCustomUnits = true;
                        break;
                    }
                }

                foreach (InstanceReportRow row in unitRows)
                {
                    if (row.MyPrecision == null)
                    {
                        continue;
                    }

                    //Numeric data that is Nill for all values will not have a precision
                    //defined, so we don't want to include these rows in our processing logic
                    if (row.IsNumericDataNil())
                    {
                        continue;
                    }

                    RoundingLevel currentRounding = InstanceUtils.GetRoundingLevelFromPrecision(row.MyPrecision);
                    selectedRounding[ut] = this.SelectRoundingLevel(row.Unit, selectedRounding[row.Unit], currentRounding, row.ElementName, messenger);

                    if (selectedRounding[ut] > RoundingLevel.NoRounding)
                    {
                        double factor = Math.Pow(10, row.MyPrecision.NumberOfDigits * -1);
                        foreach (Cell cell in row.Cells)
                        {
                            if (cell.IsNil)
                            {
                                continue;
                            }

                            if (!cell.HasData || cell.NumericAmount == 0)
                            {
                                continue;
                            }

                            if (Math.Abs((double)cell.NumericAmount) < factor)
                            {
                                selectedRounding[row.Unit] = RoundingLevel.NoRounding;
                                break;
                            }
                        }
                    }

                    if (selectedRounding[row.Unit] == RoundingLevel.NoRounding)
                    {
                        break;
                    }
                }
            }

            this.MonetaryRoundingLevel = RoundingLevel.UnKnown;
            if (selectedRounding.ContainsKey(UnitType.Monetary))
            {
                this.MonetaryRoundingLevel = selectedRounding[UnitType.Monetary];
            }

            this.SharesRoundingLevel = RoundingLevel.UnKnown;
            if (selectedRounding.ContainsKey(UnitType.Shares))
            {
                this.SharesRoundingLevel = selectedRounding[UnitType.Shares];
            }

            this.PerShareRoundingLevel = RoundingLevel.UnKnown;
            if (selectedRounding.ContainsKey(UnitType.EPS))
            {
                this.PerShareRoundingLevel = selectedRounding[UnitType.EPS];
            }

            this.ExchangeRateRoundingLevel = RoundingLevel.UnKnown;
            if (selectedRounding.ContainsKey(UnitType.ExchangeRate))
            {
                this.ExchangeRateRoundingLevel = selectedRounding[UnitType.ExchangeRate];
            }
        }
Пример #15
0
        private void ProcessIteratorsHierarchically(LinkedListNode <CommandIterator> iterator, Stack <CommandIterator> iteratorHierarchy, ITraceMessenger messenger)
        {
            if (iterator == null)
            {
                this.selectionCount++;

                Dictionary <CommandIterator.IteratorType, List <CommandIterator> > itrs = new Dictionary <CommandIterator.IteratorType, List <CommandIterator> >();
                itrs[CommandIterator.IteratorType.Column] = new List <CommandIterator>();
                itrs[CommandIterator.IteratorType.Row]    = new List <CommandIterator>();

                Dictionary <CommandIterator.IteratorType, ColumnRowRequirement> reqs = new Dictionary <CommandIterator.IteratorType, ColumnRowRequirement>();
                reqs[CommandIterator.IteratorType.Column] = new ColumnRowRequirement();
                reqs[CommandIterator.IteratorType.Row]    = new ColumnRowRequirement();

                List <CommandIterator> iterators = new List <CommandIterator>(iteratorHierarchy);
                iterators.Reverse();

                foreach (CommandIterator iMember in iterators)
                {
                    itrs[iMember.Type].Add(iMember);

                    switch (iMember.Selection)
                    {
                    case CommandIterator.SelectionType.Axis:
                        reqs[iMember.Type].Segments.Add((Segment)iMember.TempCurrentMemberValue);
                        break;

                    case CommandIterator.SelectionType.Element:
                        reqs[iMember.Type].ElementRow = (InstanceReportRow)iMember.TempCurrentMemberValue;
                        break;

                    case CommandIterator.SelectionType.Period:
                        reqs[iMember.Type].Period = (CalendarPeriod)iMember.TempCurrentMemberValue;
                        break;

                    case CommandIterator.SelectionType.Unit:
                        reqs[iMember.Type].Unit = (EmbeddedUnitWrapper)iMember.TempCurrentMemberValue;
                        break;
                    }
                }


                //if either the rows or columns are missing, this intersection cannot be created - skip it.
                if (itrs[CommandIterator.IteratorType.Column].Count == 0 || itrs[CommandIterator.IteratorType.Row].Count == 0)
                {
                    return;
                }

                //write the column
                {
                    ColumnRowRequirement colReqs = reqs[CommandIterator.IteratorType.Column];
                    colReqs.EmbedCommands = itrs[CommandIterator.IteratorType.Column].ToArray();

                    bool areSame = false;
                    //Check if the previous column matches this one - this only works because column iterators are first
                    if (this.InstanceReport.Columns.Count > 0)
                    {
                        InstanceReportColumn prevCol = this.InstanceReport.Columns[this.InstanceReport.Columns.Count - 1];
                        areSame = ColumnRowRequirement.AreSameExceptCurrency(prevCol.EmbedRequirements, colReqs);

                        if (areSame)
                        {
                            //the previous check doesn't check currency - check it here
                            areSame = string.Equals(prevCol.EmbedRequirements.UnitCode, colReqs.UnitCode);
                        }
                    }

                    //If they are the same, skip the new one - we don't want or need duplicates
                    if (!areSame)
                    {
                        InstanceReportColumn col = new InstanceReportColumn();
                        col.EmbedRequirements = colReqs;
                        col.HasMultiCurrency  = this.hasMultiCurrency;

                        if (col.EmbedRequirements.HasSelectionType(CommandIterator.SelectionType.Period))
                        {
                            col.MCU = new MergedContextUnitsWrapper();
                            col.MCU.CurrencyCode   = string.Empty;
                            col.MCU.CurrencySymbol = string.Empty;
                            col.MCU.contextRef     = new ContextProperty();

                            if (col.EmbedRequirements.Period.PeriodType == Element.PeriodType.instant)
                            {
                                col.MCU.contextRef.PeriodType      = Element.PeriodType.instant;
                                col.MCU.contextRef.PeriodStartDate = col.EmbedRequirements.Period.StartDate;
                            }
                            else if (col.EmbedRequirements.Period.PeriodType == Element.PeriodType.duration)
                            {
                                col.MCU.contextRef.PeriodType      = Element.PeriodType.duration;
                                col.MCU.contextRef.PeriodStartDate = col.EmbedRequirements.Period.StartDate;
                                col.MCU.contextRef.PeriodEndDate   = col.EmbedRequirements.Period.EndDate;
                            }
                        }

                        this.InstanceReport.Columns.Add(col);
                    }
                }


                //write the row
                {
                    ColumnRowRequirement rowReqs = reqs[CommandIterator.IteratorType.Row];
                    rowReqs.EmbedCommands = itrs[CommandIterator.IteratorType.Row].ToArray();

                    bool areSame = false;
                    //Check if ANY of the previous rows matches this one...
                    if (this.InstanceReport.Rows.Count > 0)
                    {
                        foreach (InstanceReportRow prevRow in this.InstanceReport.Rows)
                        {
                            areSame = ColumnRowRequirement.AreSameExceptCurrency(prevRow.EmbedRequirements, rowReqs);

                            if (areSame)
                            {
                                //the previous check doesn't check currency - check it here
                                areSame = string.Equals(prevRow.EmbedRequirements.UnitCode, rowReqs.UnitCode);
                            }

                            //let `areSame` fall through, and this row will not get picked up
                            if (areSame)
                            {
                                break;
                            }
                        }
                    }

                    //If they are the same, skip the new one - we don't want or need duplicates
                    if (!areSame)
                    {
                        InstanceReportRow row = new InstanceReportRow();
                        row.EmbedRequirements = rowReqs;
                        row.HasMultiCurrency  = this.hasMultiCurrency;

                        if (row.EmbedRequirements.ElementRow != null)
                        {
                            row.EmbedRequirements.ElementRow.ApplyDataTo(row);
                        }

                        this.InstanceReport.Rows.Add(row);
                    }
                }
            }
            else if (iterator.Value.Selection == CommandIterator.SelectionType.Separator)
            {
                iteratorHierarchy.Push(iterator.Value);
                ProcessIteratorsHierarchically(iterator.Next, iteratorHierarchy, messenger);
                iteratorHierarchy.Pop();
            }
            else
            {
                bool hasDefaultMember;
                Dictionary <string, object> memberValues = this.GetSelectionMembers(iteratorHierarchy, iterator.Value, out hasDefaultMember);
                if (memberValues.Count == 0)
                {
                    if (messenger != null)
                    {
                        messenger.TraceWarning("Warning: The selection of the following command, '" + iterator.Value.SelectionString + "', did not match any values available on this report:" +
                                               Environment.NewLine + iterator.Value.ToString());
                    }
                    return;
                }

                switch (iterator.Value.Selection)
                {
                case CommandIterator.SelectionType.Axis:
                    if (!hasDefaultMember)
                    {
                        iterator.Value.Style = CommandIterator.StyleType.Compact;
                    }
                    break;

                case CommandIterator.SelectionType.Unit:
                    if (memberValues.Count > 1)
                    {
                        if (memberValues.ContainsKey(string.Empty) && memberValues.Count == 2)
                        {
                            this.hasMultiCurrency = false;
                        }
                        else
                        {
                            this.hasMultiCurrency = true;
                        }
                    }
                    break;
                }

                int valuesFound = 0;
                foreach (KeyValuePair <string, object> member in memberValues)
                {
                    if (string.Equals(iterator.Value.Filter, "*") ||
                        string.Equals(iterator.Value.Filter, member.Key, StringComparison.CurrentCultureIgnoreCase))
                    {
                        valuesFound++;

                        iteratorHierarchy.Push(iterator.Value);
                        iterator.Value.TempCurrentMemberKey   = member.Key;
                        iterator.Value.TempCurrentMemberValue = member.Value;

                        ProcessIteratorsHierarchically(iterator.Next, iteratorHierarchy, messenger);

                        iterator.Value.TempCurrentMemberKey   = null;
                        iterator.Value.TempCurrentMemberValue = null;
                        iteratorHierarchy.Pop();
                    }
                }

                if (valuesFound == 0)
                {
                    if (messenger != null)
                    {
                        messenger.TraceWarning("Warning: The filter '" + iterator.Value.Filter + "' of following embed command did not match any values available on this report:" +
                                               Environment.NewLine + iterator.Value.ToString());
                    }
                }
            }
        }
Пример #16
0
        public void PopulateEmbeddedReport( InstanceReport baseReport,
			CommandIterator[] columnIterators, CommandIterator[] rowIterators, ITraceMessenger messenger )
        {
            this.IsMultiCurrency = baseReport.IsMultiCurrency;
            foreach( InstanceReportColumn col in this.Columns )
            {
                col.GenerateEmbedLabel();
            }

            foreach( InstanceReportRow row in this.Rows )
            {
                row.Cells.Clear();
                row.GenerateEmbedLabel();

                for( int c = 0; c < this.Columns.Count; c++ )
                    row.Cells.Add( new Cell() );
            }

            ColumnRowRequirement[,] netCells = new ColumnRowRequirement[ this.Rows.Count, this.Columns.Count ];
            for( int r = 0; r < this.Rows.Count; r++ )
            {
                for( int c = 0; c < this.Columns.Count; c++ )
                {
                    netCells[ r, c ] = BuildNetCell( this.Rows[ r ].EmbedRequirements, this.Columns[ c ].EmbedRequirements );
                }
            }

            for( int r = 0; r < this.Rows.Count; r++ )
            {
                for( int c = 0; c < this.Columns.Count; c++ )
                {
                    List<InstanceReportColumn> baseColumns = FindBaseColumns( netCells[ r, c ], baseReport.Columns );
                    if( baseColumns.Count == 0 )
                        continue;

                    List<InstanceReportRow> baseRows = FindBaseRows( netCells[ r, c ], baseReport.Rows );
                    if( baseRows.Count == 0 )
                        continue;

                    bool found = false;
                    foreach( InstanceReportColumn col in baseColumns )
                    {
                        foreach( InstanceReportRow row in baseRows )
                        {
                            //CEE:  By moving this up, we are using the "strict" logic
                            //Strict:  Instead of seeking to the first populated cell
                            //   the netCell is expected to point to 1 and only 1 cell
                            //found = true;

                            Cell bCell = row.Cells.Find( cell => cell.Id == col.Id );
                            if( bCell != null && bCell.HasData )
                            {
                                Cell clone = (Cell)bCell.Clone();
                                clone.ShowCurrencySymbol = false;

                                if( !this.IsEquityReport && this.IsMultiCurrency && row.IsMonetary )
                                {
                                    clone.CurrencyCode = col.CurrencyCode;
                                    clone.CurrencySymbol = col.CurrencySymbol;
                                    clone.IsMonetary = true;
                                }

                                this.Rows[ r ].Cells.RemoveAt( c );
                                this.Rows[ r ].Cells.Insert( c, clone );

                                //CEE:  By moving this down, we are using the "loose" logic
                                //Loose:  Instead of expecting the netCell to point to
                                //   1 and only 1 cell, we seek to the first populated cell
                                found = true;
                                break;
                            }
                        }

                        if( found )
                            break;
                    }
                }
            }

            //clean up columns
            this.RemoveEmptyColumns();

            if( this.Columns.Count == 0 )
                return;

            //clean up rows
            this.RemoveEmptyRows();

            this.MergeCurrencyDifferences();
            this.CheckAndScrubCurrencies();
            this.ApplyCustomUnitsEmbedded();

            //apply grouped and unitcell
            this.ApplyRowStyles( rowIterators, messenger );

            if( !this.IsEquityReport )
            {
                this.PromoteDefaultMemberGroups();
                this.RemoveDefaultMemberHeaders();
            }

            this.RelabelDefaultTotalRow();
            this.ApplyUnitCell();

            //how many unique periods are on these columns?
            //if 1, remove the label
            this.RemoveSingularPeriod();

            //if a unit occurs on all columns...
            //   remove it from the columns so it can't get promoted as "shared"
            //   save it so it can be added last
            string currencyLabel = this.RemoveSharedCurrency();

            //if a label occurs on all columns, shift it to the header
            this.PromoteSharedLabels();

            //if there is a shared currency label, add it last
            if( !string.IsNullOrEmpty( currencyLabel ) )
                this.ReportName += Environment.NewLine + currencyLabel;

            //copy over the footnotes
            this.PromoteFootnotes( baseReport );

            this.SynchronizeGrid();

            this.ProcessColumnHeaders();
        }
Пример #17
0
        public void ProcessEquity(string dateFormat, string equityMembersXml, ITraceMessenger messenger)
        {
            //we can't create the special equity layout without both beginning and ending balances
            //if there are none, exit early.
            XmlDocument membersXDoc;

            ValidateEquityStructure(equityMembersXml, out membersXDoc);

            //ensure that all rows/columns/cells are in sync
            this.SynchronizeGrid();

            /**
             * Consider the possible SQL statement as a model for this process:
             *
             * SELECT [Element values by Segment]
             * FROM [Equity Statement]
             * GROUP BY [Reporting Period]
             * ORDER BY [Element Presentation Id]
             *
             **/
            EquityDataSet dataSet = new EquityDataSet(membersXDoc);

            //#1 - this will be our X axis - a set of unique segments and scenarios, minus adjustments and previously reported
            dataSet.LoadSegmentScenarioColumns(this);

            //#2 - this will be the GROUPING for our Y axis - a set of unique calendars
            dataSet.LoadCalendarColumns(this);

            //#3 - Get each type of row role so that we can control the position
            dataSet.LoadRowTypes(this);

            if (!dataSet.PopulateEquityReport(this))
            {
                throw new IncompleteEquityException(IncompleteEquityException.ErrorType.Incomplete);
            }

            //ensure that all rows/columns/cells are in sync
            dataSet.EquityCandidate.SynchronizeGrid();
            dataSet.CleanupEquityColumns();
            dataSet.CleanupEquityRows(dateFormat, membersXDoc);

            //repair any elements or segments which might not fit the preferred rendering
            dataSet.EquityCandidate.SynchronizeGrid();
            dataSet.AdjustEquityPeriods(this);
            if (dataSet.EquityCandidate.Columns.Count == 0 || dataSet.EquityCandidate.Rows.Count == 0)
            {
                throw new IncompleteEquityException(IncompleteEquityException.ErrorType.Incomplete);
            }

            this.Columns.Clear();
            this.Columns.AddRange(dataSet.EquityCandidate.Columns);

            this.Rows.Clear();
            this.Rows.AddRange(dataSet.EquityCandidate.Rows);

            this.Footnotes.Clear();
            this.Footnotes.AddRange(dataSet.EquityCandidate.Footnotes);

            //ensure that all rows/columns/cells are in sync
            this.SynchronizeGrid();

            this.PromoteCurrencyCode();
        }
Пример #18
0
        /// <summary>
        /// Process the embed commands within the given <paramref
        /// name="baseReport"/>.
        /// </summary>
        /// <param name="baseReport">The <see cref="InstanceReport"/> in which
        /// to process embed commands.</param>
        /// <param name="messenger">An <see cref="ITraceMessenger"/> on which
        /// to log messages encountered during processing commands.</param>
        /// <returns></returns>
        public bool ProcessEmbedCommands(InstanceReport baseReport, ITraceMessenger messenger)
        {
            //Fill this in in case bar charts need to generate values
            if (this.IsBarChartReport())
            {
                //TODO: audit this...
                foreach (InstanceReportRow row in baseReport.Rows)
                {
                    row.EmbedRequirements = new ColumnRowRequirement
                    {
                        ElementRow = (InstanceReportRow)row.Clone()
                    };
                }
            }

            if (ReportUtils.IsShowElements(baseReport.ReportLongName))
            {
                this.InstanceReport = baseReport;
                return(false);
            }

            try
            {
                this.AddDefaultIterators(baseReport);
                if (this.RowIterators.Length == 0)
                {
                    messenger.TraceWarning("Warning: The embed commands for '" + baseReport.ReportLongName + "' are incomplete." +
                                           Environment.NewLine + "No 'row' commands were found.");
                    this.InstanceReport = baseReport;
                    return(false);
                }

                if (this.ColumnIterators.Length == 0)
                {
                    messenger.TraceWarning("Warning: The embed commands for '" + baseReport.ReportLongName + "' are incomplete." +
                                           Environment.NewLine + "No 'column' commands were found.");
                    this.InstanceReport = baseReport;
                    return(false);
                }


                //Console.WriteLine( "Building Embedded Report: " + baseReport.ReportLongName );
                foreach (CommandIterator itr in this.selections.Values)
                {
                    //Console.WriteLine( "\t"+ itr.ToString() );
                }

                this.IsTransposed = ReportUtils.IsTransposeReport(baseReport.ReportLongName);
                if (this.IsTransposed)
                {
                    this.TransposeIterators();
                }

                this.baseReport = baseReport;

                this.InstanceReport = new InstanceReport();
                this.InstanceReport.AxisByPresentation        = this.baseReport.AxisByPresentation;
                this.InstanceReport.AxisMembersByPresentation = this.baseReport.AxisMembersByPresentation;
                this.InstanceReport.AxisMemberDefaults        = this.baseReport.AxisMemberDefaults;
                this.InstanceReport.IsEquityReport            = this.baseReport.IsEquityReport;

                LinkedList <CommandIterator> iterators = new LinkedList <CommandIterator>(this.ColumnIterators);
                foreach (CommandIterator itr in this.RowIterators)
                {
                    iterators.AddLast(itr);
                }

                DateTime start = DateTime.Now;
                {
                    this.selectionCount = 0;
                    this.ProcessIteratorsHierarchically(iterators, messenger);
                    TimeSpan ts = DateTime.Now - start;
                    //Console.WriteLine( this.selectionCount + " selections performed in " + ts.ToString() );

                    //because the rows might come in out of order, we simply need to correct the order at the last moment.
                    this.SortByCommands(this.RowIterators);
                }

                if (this.InstanceReport.Rows.Count == 0 || this.InstanceReport.Columns.Count == 0)
                {
                    this.InstanceReport = baseReport;
                    return(false);
                }

                this.InstanceReport.PopulateEmbeddedReport(this.baseReport, this.ColumnIterators, this.RowIterators, messenger);
                if (this.InstanceReport.Rows.Count == 0 || this.InstanceReport.Columns.Count == 0)
                {
                    this.InstanceReport = baseReport;
                    this.baseReport     = null;                   //a little cleanup
                    return(false);
                }
                else
                {
                    this.baseReport = null;                       //a little cleanup
                    return(true);
                }
            }
            finally
            {
                this.InstanceReport.ReportLongName   = baseReport.ReportLongName;
                this.InstanceReport.ShowElementNames = ReportUtils.IsShowElements(baseReport.ReportLongName);
                this.InstanceReport.RemoveLabelColumn();
#if DEBUG
                this.InstanceReport.Footnotes.Add(
                    new Footnote(99, this.EmbedInstruction.Replace("<", "&lt;").Replace(">", "&gt;"))
                    );
#endif
            }
        }