/** * Returns the node for the metadata property at the current {@link #nextInAccessor}. * The value of this property is initially {@link #nextValue}, but this may change at * any time if the user modify the underlying metadata object. */ @Override public TreeTable.Node next() { if (hasNext()) { final TreeNode node = childAt(nextInAccessor, subIndex); node.cachedValue = nextValue; previousInAccessor = nextInAccessor; if (subIterator == null) { /* * If we are iterating over the elements in a collection, the PropertyAccessor index * still the same and will be incremented by 'hasNext()' only when the iteration is * over. Otherwise (not iterating in a collection), move to the next property. The * 'hasNext()' method will determine later if this property is non-empty, or if we * need to move forward again. */ nextInAccessor++; } isNextVerified = false; return node; } throw new NoSuchElementException(); }
final int count = childCount(); while (nextInAccessor < count) { if (nextInAccessor != titleProperty) { nextValue = valueAt(nextInAccessor); if (!isSkipped(nextValue)) { if (isCollection(nextInAccessor)) {
/** * Clears all properties in the metadata object. Note that this collection will effectively * by empty after this method call only if the value existence policy is {@code NON_EMPTY}, * which is the default. */ @Override public void clear() { for (int i=childCount(); --i>=0;) { clearAt(i); } }
if (siblings.isCollection(indexInData)) { indexInList = ((Collection<?>) siblings.valueAt(indexInData)).size(); } else { indexInList = -1; if (!siblings.add(indexInData, value)) { throw new IllegalArgumentException(Errors.format(Errors.Keys.ElementAlreadyPresent_1, value)); delegate = siblings.childAt(indexInData, indexInList);
/** * Tests read-only operations on a list of properties for a shallow metadata object without collections. */ @Test public void testReadOnlyWithoutCollections() { final DefaultCitation citation = metadataWithoutCollections(); final TreeNodeChildren children = create(citation, ValueExistencePolicy.NON_EMPTY); final String[] expected = { "Some title", "Some edition", "Some other details" }; assertEquals("titleProperty", -1, children.titleProperty); assertFalse ("isEmpty()", children.isEmpty()); assertEquals("size()", expected.length, children.size()); assertAllNextEqual(expected, children.iterator()); }
toAdd.setValue(TableColumn.IDENTIFIER, "edition"); toAdd.setValue(TableColumn.VALUE, citation.getEdition()); assertFalse("Adding the same value shall be a no-op.", children.add(toAdd)); toAdd.setValue(TableColumn.VALUE, "New edition"); try { children.add(toAdd); fail("Setting a different value shall be refused."); } catch (IllegalStateException e) { assertTrue("Setting a new value shall be a change.", children.add(toAdd)); assertFalse("Adding the same value shall be a no-op.", children.add(toAdd)); toAdd.setValue(TableColumn.VALUE, PresentationForm.IMAGE_DIGITAL); assertTrue("Adding a new value shall be a change.", children.add(toAdd)); assertTrue("Adding a new value shall be a change.", children.add(toAdd)); assertEquals("size()", expected.length, children.size()); assertAllNextEqual(expected, children.iterator());
children = new TreeNodeChildren(this, value, table.standard.getAccessor(new CacheKey(value.getClass(), baseType), true));
/** * Adds the given node to this list. This method fetches the object from {@link TableColumn#VALUE} * and assigns it to the property identified by {@link TableColumn#IDENTIFIER}. All other columns * are ignored. * * <p>If the identified property is a collection, then this method adds the value to that collection. * Otherwise the new value will be set only if the previous value is null, * {@linkplain org.apache.sis.xml.NilObject nil} or empty.</p> * * <p>This method does not iterate explicitly through the children list, because adding a metadata * object implicitly adds all its children.</p> * * @param node the node from which to get the values. * @return {@code true} if the metadata changed as a result of this method call. * @throws NullPointerException if the given node is null. * @throws IllegalArgumentException if this list does not have a property for the node identifier. * @throws IllegalStateException if a value already exists and no more value can be added for the node identifier. * @throws UnmodifiableMetadataException if the property for the node identifier is read-only. * @throws ClassCastException if the node value can not be converted to the expected type. * @throws BackingStoreException if the metadata implementation threw a checked exception. */ @Override public boolean add(final TreeTable.Node node) throws IllegalStateException { final String identifier = node.getValue(TableColumn.IDENTIFIER); if (identifier == null) { throw new IllegalArgumentException(Errors.format( Errors.Keys.MissingValueInColumn_1, TableColumn.IDENTIFIER.getHeader())); } return add(accessor.indexOf(identifier, true), node.getValue(TableColumn.VALUE)); }
} else if (column == TableColumn.TYPE) { final TreeNodeChildren children = getCompactChildren(); if (children == null || (value = children.getParentType()) == null) { value = baseType; final TreeNodeChildren children = getCompactChildren(); if (children != null) { value = children.getParentTitle();
/** * Tests the {@link Iterator#remove()} operation on the given collection of children. * Elements are removed randomly until the collection is empty. After each removal, * the remaining elements are compared with the content of a standard Java collection. * * @param random a random number generator. * @param children the collection from which to remove elements. */ private static void testRemove(final Random random, final TreeNodeChildren children) { final List<TreeTable.Node> reference = new ArrayList<>(children); assertFalse("The collection shall not be initially empty.", reference.isEmpty()); do { final Iterator<TreeTable.Node> rit = reference.iterator(); // The reference iterator. final Iterator<TreeTable.Node> cit = children .iterator(); // The children iterator to be tested. while (rit.hasNext()) { assertTrue(cit.hasNext()); assertSame(rit.next(), cit.next()); if (random.nextInt(3) == 0) { // Remove only 1/3 of entries on each pass. rit.remove(); cit.remove(); assertAllNextEqual(reference.iterator(), children.iterator()); } } } while (!reference.isEmpty()); assertTrue(children.isEmpty()); } }
/** * Tests the {@link TreeNodeChildren#clear()} method. */ @Test public void testClear() { final DefaultCitation citation = metadataWithSingletonInCollections(); final TreeNodeChildren children = create(citation, ValueExistencePolicy.NON_EMPTY); assertEquals("titleProperty", -1, children.titleProperty); assertFalse("isEmpty()", children.isEmpty()); children.clear(); assertTrue("isEmpty()", children.isEmpty()); assertNull(citation.getTitle()); assertTrue(citation.getAlternateTitles().isEmpty()); }
/** * Clears the element returned by the last call to {@link #next()}. * Whether the cleared element is considered removed or not depends * on the value policy and on the element type. With the default * {@code NON_EMPTY} policy, the effect is a removal. */ @Override public void remove() { if (previousInAccessor < 0) { throw new IllegalStateException(); } checkConcurrentModification(); if (subIterator != null) { subIterator.remove(); } else { clearAt(previousInAccessor); previousInAccessor = -1; } modCountCheck = ++modCount; } }
if (siblings.isCollection(indexInData)) { indexInList = ((Collection<?>) siblings.valueAt(indexInData)).size(); } else { indexInList = -1; if (!siblings.add(indexInData, value)) { throw new IllegalArgumentException(Errors.format(Errors.Keys.ElementAlreadyPresent_1, value)); delegate = siblings.childAt(indexInData, indexInList);
/** * Tests read-only operations on a list of properties for a shallow metadata object with more * than one values in collections. */ @Test @DependsOnMethod("testReadOnlyWithSingletonInCollections") public void testReadOnlyWithMultiOccurrences() { final DefaultCitation citation = metadataWithMultiOccurrences(); final TreeNodeChildren children = create(citation, ValueExistencePolicy.NON_EMPTY); final String[] expected = { "Some title", "First alternate title", "Second alternate title", "Some edition", "PresentationForm[MAP_DIGITAL]", "PresentationForm[MAP_HARDCOPY]", "Some other details" }; assertEquals("titleProperty", -1, children.titleProperty); assertFalse ("isEmpty()", children.isEmpty()); assertEquals("size()", expected.length, children.size()); assertAllNextEqual(expected, children.iterator()); }
children = new TreeNodeChildren(this, value, table.standard.getAccessor(new CacheKey(value.getClass(), baseType), true));
/** * Adds the given node to this list. This method fetches the object from {@link TableColumn#VALUE} * and assigns it to the property identified by {@link TableColumn#IDENTIFIER}. All other columns * are ignored. * * <p>If the identified property is a collection, then this method adds the value to that collection. * Otherwise the new value will be set only if the previous value is null, * {@linkplain org.apache.sis.xml.NilObject nil} or empty.</p> * * <p>This method does not iterate explicitly through the children list, because adding a metadata * object implicitly adds all its children.</p> * * @param node the node from which to get the values. * @return {@code true} if the metadata changed as a result of this method call. * @throws NullPointerException if the given node is null. * @throws IllegalArgumentException if this list does not have a property for the node identifier. * @throws IllegalStateException if a value already exists and no more value can be added for the node identifier. * @throws UnmodifiableMetadataException if the property for the node identifier is read-only. * @throws ClassCastException if the node value can not be converted to the expected type. * @throws BackingStoreException if the metadata implementation threw a checked exception. */ @Override public boolean add(final TreeTable.Node node) throws IllegalStateException { final String identifier = node.getValue(TableColumn.IDENTIFIER); if (identifier == null) { throw new IllegalArgumentException(Errors.format( Errors.Keys.MissingValueInColumn_1, TableColumn.IDENTIFIER.getHeader())); } return add(accessor.indexOf(identifier, true), node.getValue(TableColumn.VALUE)); }
} else if (column == TableColumn.TYPE) { final TreeNodeChildren children = getCompactChildren(); if (children == null || (value = children.getParentType()) == null) { value = baseType; final TreeNodeChildren children = getCompactChildren(); if (children != null) { value = children.getParentTitle();
/** * Clears the element returned by the last call to {@link #next()}. * Whether the cleared element is considered removed or not depends * on the value policy and on the element type. With the default * {@code NON_EMPTY} policy, the effect is a removal. */ @Override public void remove() { if (previousInAccessor < 0) { throw new IllegalStateException(); } checkConcurrentModification(); if (subIterator != null) { subIterator.remove(); } else { clearAt(previousInAccessor); previousInAccessor = -1; } modCountCheck = ++modCount; } }
/** * Tests read-only operations on a list of properties for a shallow metadata object with singleton * values in collections. */ @Test @DependsOnMethod("testReadOnlyWithoutCollections") public void testReadOnlyWithSingletonInCollections() { final DefaultCitation citation = metadataWithSingletonInCollections(); final TreeNodeChildren children = create(citation, ValueExistencePolicy.NON_EMPTY); final String[] expected = { "Some title", "First alternate title", "Some edition", "PresentationForm[MAP_DIGITAL]", "Some other details" }; assertEquals("titleProperty", -1, children.titleProperty); assertFalse ("isEmpty()", children.isEmpty()); assertEquals("size()", expected.length, children.size()); assertAllNextEqual(expected, children.iterator()); }
final int count = childCount(); while (nextInAccessor < count) { if (nextInAccessor != titleProperty) { nextValue = valueAt(nextInAccessor); if (!isSkipped(nextValue)) { if (isCollection(nextInAccessor)) {