Java tutorial
/** * Copyright 2017 Open Source Osijek Community * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.blip.workflowengine.transferobject; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import java.time.Instant; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.Predicate; /** * @author Kresimir Popovic * @since 27.11.2016 */ public final class ModifiablePropertyNode implements PropertyNode { private final List<Property> mutablePropertyList; public static ModifiablePropertyNode create() { return new ModifiablePropertyNode(10); } public static ModifiablePropertyNode create(final int initialCapacity) { return new ModifiablePropertyNode(initialCapacity); } @SuppressWarnings(value = "all") private ModifiablePropertyNode() { throw new IllegalStateException("Default constructor not allowed to be used !"); } private ModifiablePropertyNode(final int initialCapacity) { this.mutablePropertyList = new ArrayList<>(initialCapacity); } private ModifiablePropertyNode internalSetValue(final boolean checkNullValue, final int index, final Object value) { if (checkNullValue) { Objects.requireNonNull(value); } final Property currentProperty = mutablePropertyList.get(index); final Value newValue = ImmutableValue.of(value); final Property newProperty = ImmutableProperty.of(currentProperty.key(), newValue); mutablePropertyList.set(index, newProperty); return this; } private ModifiablePropertyNode internalAdd(final boolean checkNullValue, final String key, final Object value, final Attribute[] attributes) { Objects.requireNonNull(key); Objects.requireNonNull(attributes); if (checkNullValue) { Objects.requireNonNull(value); } final boolean hasAttributes = attributes.length > 0; if (value instanceof Value) { final Value theValue = (Value) value; if (hasAttributes) { final Property property = ImmutableProperty.of(key, theValue).withAttributes(attributes); mutablePropertyList.add(property); } else { final Property property = ImmutableProperty.of(key, theValue); mutablePropertyList.add(property); } } else { final Value theValue = ImmutableValue.of(value); if (hasAttributes) { final Property property = ImmutableProperty.of(key, theValue).withAttributes(attributes); mutablePropertyList.add(property); } else { final Property property = ImmutableProperty.of(key, theValue); mutablePropertyList.add(property); } } return this; } @Override public PropertyNode add(final Property property) { mutablePropertyList.add(ImmutableProperty.copyOf(property)); return this; } @Override public PropertyNode add(String key, Boolean value) { return internalAdd(true, key, value, Attribute.empty()); } @Override public PropertyNode add(String key, Boolean value, Attribute[] attributes) { return internalAdd(true, key, value, Attribute.empty()); } @Override public PropertyNode add(String key, Boolean value, Collection<Attribute> attributes) { return internalAdd(true, key, value, Iterables.toArray(attributes, Attribute.class)); } @Override public PropertyNode add(final String key, final Byte value) { return internalAdd(true, key, value, Attribute.empty()); } @Override public PropertyNode add(final String key, final byte[] value) { return internalAdd(true, key, value, Attribute.empty()); } @Override public PropertyNode add(final String key, final Integer value) { return internalAdd(true, key, value, Attribute.empty()); } @Override public PropertyNode add(final String key, final Long value) { return internalAdd(true, key, value, Attribute.empty()); } @Override public PropertyNode add(final String key, final Double value) { return internalAdd(true, key, value, Attribute.empty()); } @Override public PropertyNode add(final String key, final Float value) { return internalAdd(true, key, value, Attribute.empty()); } @Override public PropertyNode add(final String key, final String value) { return internalAdd(true, key, value, Attribute.empty()); } @Override public PropertyNode add(final String key, final Instant value) { return internalAdd(true, key, value, Attribute.empty()); } @Override public PropertyNode add(final String key, final PropertyNode value) { return internalAdd(true, key, value, Attribute.empty()); } @Override public <V> PropertyNode add(final String key, final Collection<? extends V> value) { return internalAdd(true, key, value, Attribute.empty()); } @Override public PropertyNode add(final String key, final Byte value, final Attribute[] attributes) { return internalAdd(true, key, value, attributes); } @Override public PropertyNode add(final String key, final Byte value, final Collection<Attribute> attributes) { return internalAdd(true, key, value, Iterables.toArray(attributes, Attribute.class)); } @Override public PropertyNode add(String key, Short value) { return internalAdd(true, key, value, Attribute.empty()); } @Override public PropertyNode add(String key, Short value, Attribute[] attributes) { return internalAdd(true, key, value, attributes); } @Override public PropertyNode add(String key, Short value, Collection<Attribute> attributes) { return internalAdd(true, key, value, Iterables.toArray(attributes, Attribute.class)); } @Override public PropertyNode add(final String key, final byte[] value, final Attribute[] attributes) { return internalAdd(true, key, value, attributes); } @Override public PropertyNode add(final String key, final byte[] value, final Collection<Attribute> attributes) { return internalAdd(true, key, value, Iterables.toArray(attributes, Attribute.class)); } @Override public PropertyNode add(final String key, final Integer value, final Attribute[] attributes) { return internalAdd(true, key, value, attributes); } @Override public PropertyNode add(final String key, final Integer value, final Collection<Attribute> attributes) { return internalAdd(true, key, value, Iterables.toArray(attributes, Attribute.class)); } @Override public PropertyNode add(final String key, final Long value, final Attribute[] attributes) { return internalAdd(true, key, value, attributes); } @Override public PropertyNode add(final String key, final Long value, final Collection<Attribute> attributes) { return internalAdd(true, key, value, Iterables.toArray(attributes, Attribute.class)); } @Override public PropertyNode add(final String key, final Float value, final Attribute[] attributes) { return internalAdd(true, key, value, attributes); } @Override public PropertyNode add(final String key, final Float value, final Collection<Attribute> attributes) { return internalAdd(true, key, value, Iterables.toArray(attributes, Attribute.class)); } @Override public PropertyNode add(final String key, final Double value, final Attribute[] attributes) { return internalAdd(true, key, value, attributes); } @Override public PropertyNode add(final String key, final Double value, final Collection<Attribute> attributes) { return internalAdd(true, key, value, Iterables.toArray(attributes, Attribute.class)); } @Override public PropertyNode add(final String key, final String value, final Attribute[] attributes) { return internalAdd(true, key, value, attributes); } @Override public PropertyNode add(final String key, final String value, final Collection<Attribute> attributes) { return internalAdd(true, key, value, Iterables.toArray(attributes, Attribute.class)); } @Override public PropertyNode add(final String key, final Instant value, final Attribute[] attributes) { return internalAdd(true, key, value, attributes); } @Override public PropertyNode add(final String key, final Instant value, final Collection<Attribute> attributes) { return internalAdd(true, key, value, Iterables.toArray(attributes, Attribute.class)); } @Override public PropertyNode add(final String key, final PropertyNode value, final Attribute[] attributes) { return internalAdd(true, key, value, attributes); } @Override public PropertyNode add(final String key, final PropertyNode value, final Collection<Attribute> attributes) { return internalAdd(true, key, value, Iterables.toArray(attributes, Attribute.class)); } @Override public <V> PropertyNode add(final String key, final Collection<? extends V> value, final Attribute[] attributes) { return internalAdd(true, key, value, attributes); } @Override public PropertyNode add(final String key, final Collection<Object> value, final Collection<Attribute> attributes) { return internalAdd(true, key, value, Iterables.toArray(attributes, Attribute.class)); } @Override public PropertyNode addNull(final String key) { return internalAdd(false, key, null, Attribute.empty()); } @Override public PropertyNode addNull(final String key, final Attribute[] attributes) { return internalAdd(false, key, null, attributes); } @Override public PropertyNode addNull(final String key, final Collection<Attribute> attributes) { return internalAdd(false, key, null, Iterables.toArray(attributes, Attribute.class)); } @Override public List<Property> properties() { return new ImmutableList.Builder<Property>().addAll(mutablePropertyList).build(); } @Override public boolean containsAll(final Collection<Property> propertyCollection) { return mutablePropertyList.containsAll(propertyCollection); } @Override public PropertyNode set(final int index, final Property property) { mutablePropertyList.set(index, ImmutableProperty.copyOf(property)); return this; } @Override public PropertyNode setAttr(final int index, final Attribute[] attributes) { final Property currentProperty = mutablePropertyList.get(index); final Property newProperty = ImmutableProperty.copyOf(currentProperty).withAttributes(attributes); mutablePropertyList.set(index, newProperty); return this; } @Override public PropertyNode setAttr(final int index, final Collection<Attribute> attributes) { return setAttr(index, Iterables.toArray(attributes, Attribute.class)); } @Override public PropertyNode setKey(final int index, final String key) { final Property currentProperty = mutablePropertyList.get(index); final Property newProperty = ImmutableProperty.copyOf(currentProperty).withKey(key); mutablePropertyList.set(index, newProperty); return this; } @Override public PropertyNode setNull(final int index) { return internalSetValue(false, index, null); } @Override public PropertyNode setValue(int index, Boolean value) { return internalSetValue(false, index, value); } @Override public PropertyNode setValue(final int index, final Byte value) { return internalSetValue(true, index, value); } @Override public PropertyNode setValue(final int index, final byte[] value) { return internalSetValue(true, index, value); } @Override public PropertyNode setValue(final int index, final Short value) { return internalSetValue(true, index, value); } @Override public PropertyNode setValue(final int index, final Integer value) { return internalSetValue(true, index, value); } @Override public PropertyNode setValue(final int index, final Long value) { return internalSetValue(true, index, value); } @Override public PropertyNode setValue(final int index, final Float value) { return internalSetValue(true, index, value); } @Override public PropertyNode setValue(final int index, final Double value) { return internalSetValue(true, index, value); } @Override public PropertyNode setValue(final int index, final String value) { return internalSetValue(true, index, value); } @Override public PropertyNode setValue(final int index, final Instant value) { return internalSetValue(true, index, value); } @Override public <V> PropertyNode setValue(int index, Collection<? extends V> value) { return internalSetValue(true, index, value); } @Override public PropertyNode setValue(final int index, final PropertyNode value) { return internalSetValue(true, index, value); } @Override public PropertyNode removeFirst() { mutablePropertyList.remove(0); return this; } @Override public PropertyNode removeFirst(final String key) { if (hasProperty(key)) { for (final Map.Entry<Integer, Property> zipped : zipWithIndex()) { if (zipped.getValue().key().equals(key)) { mutablePropertyList.remove(zipped.getKey().intValue()); break; } } } else { final String errorText = String.format("Property key=<%s> doesn't exists", key); throw new NoSuchElementException(errorText); } return this; } @Override public PropertyNode removeLast() { mutablePropertyList.remove(size() - 1); return this; } @Override public PropertyNode removeLast(final String key) { final Property propertyToRemove = lastKey(key, null); if (Objects.nonNull(propertyToRemove)) { mutablePropertyList.remove(propertyToRemove); } else { final String errorText = String.format("Property key=<%s> doesn't exists", key); throw new NoSuchElementException(errorText); } return this; } @Override public PropertyNode remove(final int index) { mutablePropertyList.remove(index); return this; } @Override public PropertyNode removeAll(final Collection<Property> propertyCollection) { mutablePropertyList.removeAll(propertyCollection); return this; } @Override public PropertyNode removeAll(final String key) { for (final Property property : toArray()) { if (property.key().equals(key)) { mutablePropertyList.remove(property); } } return this; } @Override public PropertyNode removeAll() { mutablePropertyList.clear(); return this; } @Override public PropertyNode removeRange(final int fromIndex, final int toIndex) { final List<Property> listView = mutablePropertyList.subList(fromIndex, toIndex); mutablePropertyList.removeAll(listView); return this; } @Override public PropertyNode removeIf(final Predicate<? super Property> filter) { Objects.requireNonNull(filter); for (final Property property : toArray()) { if (filter.test(property)) { mutablePropertyList.remove(property); } } return this; } @Override public PropertyNode retainAll(final Collection<Property> propertyCollection) { mutablePropertyList.retainAll(propertyCollection); return this; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } final ModifiablePropertyNode node = (ModifiablePropertyNode) o; return com.google.common.base.Objects.equal(mutablePropertyList, node.mutablePropertyList); } @Override public int hashCode() { return com.google.common.base.Objects.hashCode(mutablePropertyList); } @Override public String toString() { if (isEmpty()) { return "{}"; } final StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("{").append("\n"); for (final Property property : this) { stringBuilder.append(" ").append(property).append("\n"); } stringBuilder.append("}"); return stringBuilder.toString(); } }