List<GroupExpression> _Items; // list of GroupExpression

        #endregion Fields

        #region Constructors

        internal GroupExpressions(ReportDefn r, ReportLink p, XmlNode xNode)
            : base(r, p)
        {
            GroupExpression g;
            _Items = new List<GroupExpression>();
            // Loop thru all the child nodes
            foreach(XmlNode xNodeLoop in xNode.ChildNodes)
            {
                if (xNodeLoop.NodeType != XmlNodeType.Element)
                    continue;
                switch (xNodeLoop.Name)
                {
                    case "GroupExpression":
                        g = new GroupExpression(r, this, xNodeLoop);
                        break;
                    default:
                        g=null;		// don't know what this is
                        // don't know this element - log it
                        OwnerReport.rl.LogError(4, "Unknown GroupExpressions element '" + xNodeLoop.Name + "' ignored.");
                        break;
                }
                if (g != null)
                    _Items.Add(g);
            }
            if (_Items.Count == 0)
                OwnerReport.rl.LogError(8, "GroupExpressions require at least one GroupExpression be defined.");
            else
                _Items.TrimExcess();
        }
        List <GroupEntry> _NestedGroup;         // group one hierarchy below

        internal GroupEntry(Grouping g, Sorting s, int start)
        {
            _Group       = g;
            _Sort        = s;
            _StartRow    = start;
            _EndRow      = -1;
            _NestedGroup = new List <GroupEntry>();

            // Check to see if grouping and sorting are the same
            if (g == null || s == null)
            {
                return;                                 // nothing to check if either is null
            }
            if (s.Items.Count != g.GroupExpressions.Items.Count)
            {
                return;
            }

            for (int i = 0; i < s.Items.Count; i++)
            {
                SortBy sb = s.Items[i] as SortBy;

                if (sb.Direction == SortDirectionEnum.Descending)
                {
                    return;                                     // TODO we could optimize this
                }
                FunctionField ff = sb.SortExpression.Expr as FunctionField;
                if (ff == null || ff.GetTypeCode() != TypeCode.String)
                {
                    return;
                }

                GroupExpression ge  = g.GroupExpressions.Items[i] as GroupExpression;
                FunctionField   ff2 = ge.Expression.Expr as FunctionField;
                if (ff2 == null || ff.Fld != ff2.Fld)
                {
                    return;
                }
            }
            _Sort = null;                       // we won't need to sort since the groupby will handle it correctly
        }
        List <GroupExpression> _Items;                   // list of GroupExpression

        internal GroupExpressions(ReportDefn r, ReportLink p, XmlNode xNode) : base(r, p)
        {
            GroupExpression g;

            _Items = new List <GroupExpression>();
            // Loop thru all the child nodes
            foreach (XmlNode xNodeLoop in xNode.ChildNodes)
            {
                if (xNodeLoop.NodeType != XmlNodeType.Element)
                {
                    continue;
                }
                switch (xNodeLoop.Name)
                {
                case "GroupExpression":
                    g = new GroupExpression(r, this, xNodeLoop);
                    break;

                default:
                    g = null;                                   // don't know what this is
                    // don't know this element - log it
                    OwnerReport.rl.LogError(4, "Unknown GroupExpressions element '" + xNodeLoop.Name + "' ignored.");
                    break;
                }
                if (g != null)
                {
                    _Items.Add(g);
                }
            }
            if (_Items.Count == 0)
            {
                OwnerReport.rl.LogError(8, "GroupExpressions require at least one GroupExpression be defined.");
            }
            else
            {
                _Items.TrimExcess();
            }
        }
Beispiel #4
0
        private void PrepRecursiveGroup(Report rpt, TableWorkClass wc)
        {
            // Prepare for processing recursive group
            Grouping        g          = wc.RecursiveGroup;
            IExpr           parentExpr = g.ParentGroup;
            GroupExpression gexpr      = g.GroupExpressions.Items[0] as GroupExpression;
            IExpr           groupExpr  = gexpr.Expression;
            TypeCode        tc         = groupExpr.GetTypeCode();
            List <Row>      odata      = new List <Row>(wc.Data.Data);          // this is the old data that we'll recreate using the recursive hierarchy
            List <Row>      newrows    = new List <Row>(odata.Count);

            // For now we assume on a single top of tree (and it must sort first as null)
            //   spec is incomplete: should have ability to specify starting value of tree
            // TODO: pull all of the rows that start with null
            newrows.Add(odata[0]);                                              // add the starting row
            odata.RemoveAt(0);                                                  //   remove olddata

            // we need to build the group entry stack
            // Build the initial one
            wc.Groups = new List <GroupEntry>();
            GroupEntry ge = new GroupEntry(null, null, 0);

            ge.EndRow = odata.Count - 1;
            wc.Groups.Add(ge);                                          // top group

            List <GroupEntry> ges = new List <GroupEntry>();

            ges.Add(ge);

            // loop thru the rows and find their children
            //   we place the children right after the parent
            //   this reorders the rows in the form of the hierarchy
            Row r;
            RecursiveCompare rc = new RecursiveCompare(rpt, parentExpr, tc, groupExpr);

            for (int iRow = 0; iRow < newrows.Count; iRow++)            // go thru the temp rows
            {
                r = newrows[iRow];

                r.GroupEntry        = ge = new GroupEntry(g, null, iRow);               // TODO: sort for this group??
                r.GroupEntry.EndRow = iRow;

                // pull out all the rows that match this value
                int iMainRow = odata.BinarySearch(r, rc);
                if (iMainRow < 0)
                {
                    for (int i = 0; i <= r.Level + 1 && i < ges.Count; i++)
                    {
                        ge = ges[i] as GroupEntry;
                        Row rr = newrows[ge.StartRow];                          // start row has the base level of group
                        if (rr.Level < r.Level)
                        {
                            ge.EndRow = iRow;
                        }
                    }
                    continue;
                }

                // look backward for starting row;
                //   in case of duplicates, BinarySearch can land on any of the rows
                object cmpvalue = groupExpr.Evaluate(rpt, r);

                int sRow = iMainRow - 1;
                while (sRow >= 0)
                {
                    object v = parentExpr.Evaluate(rpt, odata[sRow]);
                    if (Filter.ApplyCompare(tc, cmpvalue, v) != 0)
                    {
                        break;
                    }
                    sRow--;
                }
                sRow++;                         // adjust; since we went just prior it
                // look forward for ending row
                int eRow = iMainRow + 1;
                while (eRow < odata.Count)
                {
                    object v = parentExpr.Evaluate(rpt, odata[eRow]);
                    if (Filter.ApplyCompare(tc, cmpvalue, v) != 0)
                    {
                        break;
                    }
                    eRow++;
                }
                // Build a group entry for this
                GroupEntry ge2 = ges[r.Level] as GroupEntry;
                ge2.NestedGroup.Add(ge);
                if (r.Level + 1 >= ges.Count)                   // ensure we have room in the array (based on level)
                {
                    ges.Add(ge);                                // add to the array
                }
                else
                {
                    ges[r.Level + 1] = ge;                                              // put this in the array
                }

                // add all of them in; want the same order for these rows.
                int offset = 1;
                for (int tRow = sRow; tRow < eRow; tRow++)
                {
                    Row tr = odata[tRow];
                    tr.Level = r.Level + 1;
                    newrows.Insert(iRow + offset, tr);
                    offset++;
                }
                // remove from old data
                odata.RemoveRange(sRow, eRow - sRow);
            }

            // update the groupentries for the very last row
            int lastrow = newrows.Count - 1;

            r = newrows[lastrow];
            for (int i = 0; i < r.Level + 1 && i < ges.Count; i++)
            {
                ge        = ges[i] as GroupEntry;
                ge.EndRow = lastrow;
            }

            wc.Data.Data = newrows;                     // we've completely replaced the rows
            return;
        }