/*
Copyright 2015 CrushPaper.com.
This file is part of CrushPaper.
CrushPaper is free software: you can redistribute it and/or modify
it under the terms of version 3 of the GNU Affero General Public
License as published by the Free Software Foundation.
CrushPaper is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with CrushPaper. If not, see <http://www.gnu.org/licenses/>.
*/
package com.crushpaper;
import java.util.HashMap;
/**
* Represents a set of entries in the db. Part of the unit testing scaffolding,
* but this is not a mock or a fake. Don't put null values or null entries in
* this set. The code won't crash, but comparisons wouldn't work intuitively.
* This is OK, because TestEntries are only trying to model Entries from
* DbLogic, which can not be null, and whose values can be empty, but not null.
* Order does not matter for the top level entries, but it does matter for every
* other entry.
*/
public class TestEntrySet {
private final TestEntry[] entries;
private final HashMap<String, TestEntry> entriesByValue = new HashMap<String, TestEntry>();
private final HashMap<String, TestEntry> entriesById = new HashMap<String, TestEntry>();
private boolean wasValidityOfValuesAlreadyChecked = false;
private boolean areValuesValid = false;
private boolean wasValidityOfIdsAlreadyChecked = false;
private boolean areIdsValid = false;
TestEntrySet(TestEntry[] entries) {
this.entries = entries;
}
public TestEntry[] getRootEntries() {
return entries;
}
public TestEntry getRootEntryByValue(String value) {
if (entries != null) {
for (final TestEntry entry : entries) {
if (value == null) {
if (entry != null && value == entry.getValue()) {
return entry;
}
} else if (entry != null && value.equals(entry.getValue())) {
return entry;
}
}
}
return null;
}
public boolean compare(TestEntrySet other) {
if ((other.entries == null) != (entries == null)) {
return false;
}
if (entries != null && other.entries.length != entries.length) {
return false;
}
if (entries != null) {
for (final TestEntry entry : entries) {
final TestEntry fromOther = other
.getRootEntryByValue(entry != null ? entry.getValue()
: null);
if ((entry == null) != (fromOther == null)) {
return false;
}
if (entry != null && !entry.compare(fromOther)) {
return false;
}
}
}
return true;
}
public boolean doIdsMatch(TestEntrySet other) {
other.areIdsValid();
areIdsValid();
for (final HashMap.Entry<String, TestEntry> entry : entriesByValue
.entrySet()) {
final String otherId = other.getIdForValue(entry.getKey());
// Only check the values that are present in both.
if (otherId != null && !otherId.equals(entry.getValue().getId())) {
return false;
}
}
return true;
}
public String getIdForValue(String value) {
final TestEntry testEntry = entriesByValue.get(value);
if (testEntry == null) {
return null;
}
return testEntry.getId();
}
public boolean areValuesValid() {
if (wasValidityOfValuesAlreadyChecked) {
return areValuesValid;
}
wasValidityOfValuesAlreadyChecked = true;
return areValuesValid = areValuesValidHelper();
}
public boolean areValuesValidHelper() {
if (entries == null) {
return false;
}
for (final TestEntry entry : entries) {
if (entry == null) {
return false;
}
if (!areValuesValid(entry)) {
return false;
}
}
return true;
}
private boolean areValuesValid(TestEntry entry) {
if (entry.getValue() == null) {
return false;
}
if (entriesByValue.put(entry.getValue(), entry) != null) {
return false;
}
if (entry.getChildren() != null) {
for (final TestEntry child : entry.getChildren()) {
if (child == null) {
return false;
}
if (!areValuesValid(child)) {
return false;
}
}
}
return true;
}
public boolean areIdsValid() {
if (wasValidityOfIdsAlreadyChecked) {
return areIdsValid;
}
wasValidityOfIdsAlreadyChecked = true;
return areIdsValid = areIdsValidHelper();
}
public boolean areIdsValidHelper() {
if (entries == null) {
return false;
}
for (final TestEntry entry : entries) {
if (entry == null) {
return false;
}
if (!areIdsValid(entry)) {
return false;
}
}
return true;
}
private boolean areIdsValid(TestEntry entry) {
if (entry.getId() == null
|| entriesById.put(entry.getId(), entry) != null) {
return false;
}
if (entry.getChildren() != null) {
for (final TestEntry child : entry.getChildren()) {
if (child == null) {
return false;
}
if (!areIdsValid(child)) {
return false;
}
}
}
return true;
}
}