Beispiel #1
0
        public override Value GetTag(string tag, bool inherit = true)
        {
            Value value = base.GetTag(tag, inherit);

            if (!Value.IsNullOrEmpty(value))
            {
                return(value);
            }

            if (inherit && Xact != null)
            {
                return(Xact.GetTag(tag));
            }

            return(Value.Empty);
        }
Beispiel #2
0
        public bool AddXact(Xact xact)
        {
            if (xact == null)
            {
                throw new ArgumentNullException("xact");
            }

            xact.Journal = this;

            if (!xact.FinalizeXact())
            {
                xact.Journal = null;
                return(false);
            }

            ExtendXact(xact);
            CheckAllMetadata(xact);

            foreach (Post post in xact.Posts)
            {
                Post.ExtendPost(post, this);
                CheckAllMetadata(post);
            }

            // If a transaction with this UUID has already been seen, simply do
            // not add this one to the journal.  However, all automated checks
            // will have been performed by extend_xact, so asserts can still be
            // applied to it.
            Value refVal = xact.GetTag("UUID");

            if (!Value.IsNullOrEmpty(refVal))
            {
                string uuid = refVal.AsString;
                if (ChecksumMapping.ContainsKey(uuid))
                {
                    // This UUID has been seen before; apply any postings which the
                    // earlier version may have deferred.
                    foreach (Post post in xact.Posts)
                    {
                        Account            acct          = post.Account;
                        IEnumerable <Post> deferredPosts = acct.GetDeferredPosts(uuid);
                        if (deferredPosts != null)
                        {
                            foreach (Post rpost in deferredPosts)
                            {
                                if (acct == rpost.Account)
                                {
                                    acct.AddPost(rpost);
                                }
                            }
                            acct.DeleteDeferredPosts(uuid);
                        }
                    }

                    Xact other = ChecksumMapping[uuid];

                    // Copy the two lists of postings (which should be relatively
                    // short), and make sure that the intersection is the empty set
                    // (i.e., that they are the same list).
                    IEnumerable <Post> thisPosts  = xact.Posts.OrderBy(p => p.Account.FullName);
                    IEnumerable <Post> otherPosts = other.Posts.OrderBy(p => p.Account.FullName);
                    bool match = !thisPosts.Except(otherPosts, EquivalentPostingComparer.Current).Any();
                    if (!match || thisPosts.Count() != otherPosts.Count())
                    {
                        ErrorContext.Current.AddErrorContext("While comparing this previously seen transaction:");
                        ErrorContext.Current.AddErrorContext(ErrorContext.SourceContext(other.Pos.PathName, other.Pos.BegPos, other.Pos.EndPos, "> "));
                        ErrorContext.Current.AddErrorContext("to this later transaction:");
                        ErrorContext.Current.AddErrorContext(ErrorContext.SourceContext(xact.Pos.PathName, xact.Pos.BegPos, xact.Pos.EndPos, "> "));
                        throw new RuntimeError(RuntimeError.ErrorMessageTransactionsWithTheSameUUIDmustHaveEquivalentPostings);
                    }

                    xact.Journal = null;
                    return(false);
                }
                else
                {
                    ChecksumMapping.Add(uuid, xact);
                }
            }

            Xacts.Add(xact);
            return(true);
        }