11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2008 The Guava Authors 31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); 51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License. 61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at 71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software 111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS, 121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and 141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License. 151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.collect; 181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 193ecfa412eddc4b084663f38d562537b86b9734d5Paul Duffinimport static com.google.common.truth.Truth.assertThat; 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible; 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtIncompatible; 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Objects; 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.testing.EqualsTester; 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.testing.NullPointerTester; 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.TestCase; 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/** 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Test cases for {@link Table} read operations. 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Jared Levy 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible(emulated = true) 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic abstract class AbstractTableReadTest extends TestCase { 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected Table<String, Integer, Character> table; 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Creates a table with the specified data. 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param data the table data, repeating the sequence row key, column key, 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * value once per mapping 431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws IllegalArgumentException if the size of {@code data} isn't a 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * multiple of 3 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws ClassCastException if a data element has the wrong type 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected abstract Table<String, Integer, Character> 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert create(Object... data); 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected void assertSize(int expectedSize) { 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(expectedSize, table.size()); 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public void setUp() throws Exception { 551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert super.setUp(); 561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table = create(); 571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testContains() { 601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c'); 611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(table.contains("foo", 1)); 621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(table.contains("bar", 1)); 631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(table.contains("foo", 3)); 641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(table.contains("foo", 2)); 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(table.contains("bar", 3)); 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(table.contains("cat", 1)); 671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(table.contains("foo", null)); 681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(table.contains(null, 1)); 691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(table.contains(null, null)); 701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testContainsRow() { 731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c'); 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(table.containsRow("foo")); 751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(table.containsRow("bar")); 761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(table.containsRow("cat")); 771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(table.containsRow(null)); 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testContainsColumn() { 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c'); 821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(table.containsColumn(1)); 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(table.containsColumn(3)); 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(table.containsColumn(2)); 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(table.containsColumn(null)); 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testContainsValue() { 891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c'); 901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(table.containsValue('a')); 911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(table.containsValue('b')); 921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(table.containsValue('c')); 931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(table.containsValue('x')); 941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(table.containsValue(null)); 951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testGet() { 981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c'); 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals((Character) 'a', table.get("foo", 1)); 1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals((Character) 'b', table.get("bar", 1)); 1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals((Character) 'c', table.get("foo", 3)); 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertNull(table.get("foo", 2)); 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertNull(table.get("bar", 3)); 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertNull(table.get("cat", 1)); 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertNull(table.get("foo", null)); 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertNull(table.get(null, 1)); 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertNull(table.get(null, null)); 1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testIsEmpty() { 1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(table.isEmpty()); 1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c'); 1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(table.isEmpty()); 1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testSize() { 1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertSize(0); 1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c'); 1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertSize(3); 1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testEquals() { 1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c'); 1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Table<String, Integer, Character> hashCopy = HashBasedTable.create(table); 1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Table<String, Integer, Character> reordered 1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert = create("foo", 3, 'c', "foo", 1, 'a', "bar", 1, 'b'); 1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Table<String, Integer, Character> smaller 1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert = create("foo", 1, 'a', "bar", 1, 'b'); 1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Table<String, Integer, Character> swapOuter 1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert = create("bar", 1, 'a', "foo", 1, 'b', "bar", 3, 'c'); 1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Table<String, Integer, Character> swapValues 1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert = create("foo", 1, 'c', "bar", 1, 'b', "foo", 3, 'a'); 1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert new EqualsTester() 1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert .addEqualityGroup(table, hashCopy, reordered) 1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert .addEqualityGroup(smaller) 1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert .addEqualityGroup(swapOuter) 1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert .addEqualityGroup(swapValues) 1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert .testEquals(); 1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testHashCode() { 1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c'); 1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int expected = Objects.hashCode("foo", 1, 'a') 1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert + Objects.hashCode("bar", 1, 'b') 1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert + Objects.hashCode("foo", 3, 'c'); 1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(expected, table.hashCode()); 1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testToStringSize1() { 1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table = create("foo", 1, 'a'); 1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals("{foo={1=a}}", table.toString()); 1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testRow() { 1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c'); 1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(ImmutableMap.of(1, 'a', 3, 'c'), table.row("foo")); 1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // This test assumes that the implementation does not support null keys. 1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testRowNull() { 1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c'); 1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table.row(null); 1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail(); 1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (NullPointerException expected) {} 1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testColumn() { 1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c'); 1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(ImmutableMap.of("foo", 'a', "bar", 'b'), table.column(1)); 1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // This test assumes that the implementation does not support null keys. 1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testColumnNull() { 1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table = create("foo", 1, 'a', "bar", 1, 'b', "foo", 3, 'c'); 1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table.column(null); 1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail(); 1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (NullPointerException expected) {} 1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testColumnSetPartialOverlap() { 1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table = create( 1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert "foo", 1, 'a', "bar", 1, 'b', "foo", 2, 'c', "bar", 3, 'd'); 1863ecfa412eddc4b084663f38d562537b86b9734d5Paul Duffin assertThat(table.columnKeySet()).has().exactly(1, 2, 3); 1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @GwtIncompatible("NullPointerTester") 1907dd252788645e940eada959bdde927426e2531c9Paul Duffin public void testNullPointerInstance() { 1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table = create( 1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert "foo", 1, 'a', "bar", 1, 'b', "foo", 2, 'c', "bar", 3, 'd'); 1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert new NullPointerTester().testAllPublicInstanceMethods(table); 1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 196