root/src/apps/haikudepot/model/ValidationFailure.cpp
/*
 * Copyright 2019-2026, Andrew Lindesay <apl@lindesay.co.nz>.
 *
 * All rights reserved. Distributed under the terms of the MIT License.
 */
#include "ValidationFailure.h"

// These are keys that are used to store this object's data into a BMessage
// instance.

static const char* const kKeyProperty = "property";
static const char* const kKeyPrefixMessage = "message_";
static const char* const kKeyPrefixItem = "item_";


// #pragma mark - Single Validation Failure


ValidationFailure::ValidationFailure(BMessage* from)
{
        from->FindString(kKeyProperty, &fProperty);

        if (fProperty.IsEmpty())
                debugger("illegal state; missing property in message");

        status_t result = B_OK;
        BString name;
        BString message;

        for (int32 i = 0; result == B_OK; i++) {
                name.SetToFormat("%s%" B_PRId32, kKeyPrefixMessage, i);
                result = from->FindString(name, &message);

                if (result == B_OK)
                        AddMessage(message);
        }
}


ValidationFailure::ValidationFailure(const BString& property)
{
        fProperty = property;
}


ValidationFailure::~ValidationFailure()
{
}


const BString&
ValidationFailure::Property() const
{
        return fProperty;
}


const BStringList&
ValidationFailure::Messages() const
{
        return fMessages;
}


bool
ValidationFailure::IsEmpty() const
{
        return fMessages.IsEmpty();
}


bool
ValidationFailure::Contains(const BString& message) const
{
        return fMessages.HasString(message);
}


void
ValidationFailure::AddMessage(const BString& value)
{
        fMessages.Add(value);
}


status_t
ValidationFailure::Archive(BMessage* into, bool deep) const
{
        status_t result = B_OK;
        BString key;
        if (result == B_OK)
                result = into->AddString(kKeyProperty, fProperty);
        for (int32 i = 0; result == B_OK && i < fMessages.CountStrings(); i++) {
                key.SetToFormat("%s%" B_PRId32, kKeyPrefixMessage, i);
                result = into->AddString(key, fMessages.StringAt(i));
        }
        return result;
}


// #pragma mark - Collections of Validation Failures


ValidationFailures::ValidationFailures(BMessage* from)
        :
        fItems(20)
{
        _AddFromMessage(from);
}


ValidationFailures::ValidationFailures()
        :
        fItems(20)
{
}


ValidationFailures::~ValidationFailures()
{
}


void
ValidationFailures::AddFailure(const BString& property, const BString& message)
{
        _GetOrCreateFailure(property)->AddMessage(message);
}


int32
ValidationFailures::CountFailures() const
{
        return fItems.CountItems();
}


bool
ValidationFailures::IsEmpty() const
{
        return fItems.IsEmpty();
}


bool
ValidationFailures::Contains(const BString& property) const
{
        ValidationFailure* failure = _GetFailure(property);
        return failure != NULL && !failure->IsEmpty();
}


bool
ValidationFailures::Contains(const BString& property,
        const BString& message) const
{
        ValidationFailure* failure = _GetFailure(property);
        return failure != NULL && failure->Contains(message);
}


ValidationFailure*
ValidationFailures::FailureAtIndex(int32 index) const
{
        return fItems.ItemAt(index);
}


status_t
ValidationFailures::Archive(BMessage* into, bool deep) const
{
        status_t result = B_OK;
        BString key;

        for (int32 i = 0; i < fItems.CountItems() && result == B_OK; i++) {
                ValidationFailure* item = fItems.ItemAt(i);
                BMessage itemMessage;
                result = item->Archive(&itemMessage);
                if (result == B_OK) {
                        key.SetToFormat("%s%" B_PRId32, kKeyPrefixItem, i);
                        result = into->AddMessage(key, &itemMessage);
                }
        }

        return result;
}


ValidationFailure*
ValidationFailures::_GetFailure(const BString& property) const
{
        for (int32 i = 0; i < fItems.CountItems(); i++) {
                ValidationFailure* item = fItems.ItemAt(i);
                if (item->Property() == property)
                        return item;
        }

        return NULL;
}


ValidationFailure*
ValidationFailures::_GetOrCreateFailure(const BString& property)
{
        ValidationFailure* item = _GetFailure(property);

        if (item == NULL) {
                item = new ValidationFailure(property);
                fItems.AddItem(item);
        }

        return item;
}


void
ValidationFailures::_AddFromMessage(const BMessage* from)
{
        int32 i = 0;
        BString key;

        while (true) {
                BMessage itemMessage;
                key.SetToFormat("%s%" B_PRId32, kKeyPrefixItem, i);
                if (from->FindMessage(key, &itemMessage) != B_OK)
                        return;
                fItems.AddItem(new ValidationFailure(&itemMessage));
                i++;
        }
}