All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.commons.collections4.map.AbstractInputCheckedMapDecorator Maven / Gradle / Ivy

Go to download

The Apache Commons Collections package contains types that extend and augment the Java Collections Framework.

There is a newer version: 4.5.0-M1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.commons.collections4.map;

import java.lang.reflect.Array;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections4.iterators.AbstractIteratorDecorator;
import org.apache.commons.collections4.keyvalue.AbstractMapEntryDecorator;
import org.apache.commons.collections4.set.AbstractSetDecorator;

/**
 * An abstract base class that simplifies the task of creating map decorators.
 * 

* The Map API is very difficult to decorate correctly, and involves implementing * lots of different classes. This class exists to provide a simpler API. *

*

* Special hook methods are provided that are called when objects are added to * the map. By overriding these methods, the input can be validated or manipulated. * In addition to the main map methods, the entrySet is also affected, which is * the hardest part of writing map implementations. *

*

* This class is package-scoped, and may be withdrawn or replaced in future * versions of Commons Collections. *

* * @since 3.1 */ abstract class AbstractInputCheckedMapDecorator extends AbstractMapDecorator { /** * Constructor only used in deserialization, do not use otherwise. */ protected AbstractInputCheckedMapDecorator() { super(); } /** * Constructor that wraps (not copies). * * @param map the map to decorate, must not be null * @throws NullPointerException if map is null */ protected AbstractInputCheckedMapDecorator(final Map map) { super(map); } //----------------------------------------------------------------------- /** * Hook method called when a value is being set using setValue. *

* An implementation may validate the value and throw an exception * or it may transform the value into another object. *

*

* This implementation returns the input value. *

* * @param value the value to check * @return the input value * @throws UnsupportedOperationException if the map may not be changed by setValue * @throws IllegalArgumentException if the specified value is invalid * @throws ClassCastException if the class of the specified value is invalid * @throws NullPointerException if the specified value is null and nulls are invalid */ protected abstract V checkSetValue(V value); /** * Hook method called to determine if checkSetValue has any effect. *

* An implementation should return false if the checkSetValue method * has no effect as this optimises the implementation. *

* This implementation returns true. * * @return true always */ protected boolean isSetValueChecking() { return true; } //----------------------------------------------------------------------- @Override public Set> entrySet() { if (isSetValueChecking()) { return new EntrySet(map.entrySet(), this); } return map.entrySet(); } //----------------------------------------------------------------------- /** * Implementation of an entry set that checks additions via setValue. */ private class EntrySet extends AbstractSetDecorator> { /** Generated serial version ID. */ private static final long serialVersionUID = 4354731610923110264L; /** The parent map */ private final AbstractInputCheckedMapDecorator parent; protected EntrySet(final Set> set, final AbstractInputCheckedMapDecorator parent) { super(set); this.parent = parent; } @Override public Iterator> iterator() { return new EntrySetIterator(this.decorated().iterator(), parent); } @Override @SuppressWarnings("unchecked") public Object[] toArray() { final Object[] array = this.decorated().toArray(); for (int i = 0; i < array.length; i++) { array[i] = new MapEntry((Map.Entry) array[i], parent); } return array; } @Override @SuppressWarnings("unchecked") public T[] toArray(final T[] array) { Object[] result = array; if (array.length > 0) { // we must create a new array to handle multi-threaded situations // where another thread could access data before we decorate it result = (Object[]) Array.newInstance(array.getClass().getComponentType(), 0); } result = this.decorated().toArray(result); for (int i = 0; i < result.length; i++) { result[i] = new MapEntry((Map.Entry) result[i], parent); } // check to see if result should be returned straight if (result.length > array.length) { return (T[]) result; } // copy back into input array to fulfil the method contract System.arraycopy(result, 0, array, 0, result.length); if (array.length > result.length) { array[result.length] = null; } return array; } } /** * Implementation of an entry set iterator that checks additions via setValue. */ private class EntrySetIterator extends AbstractIteratorDecorator> { /** The parent map */ private final AbstractInputCheckedMapDecorator parent; protected EntrySetIterator(final Iterator> iterator, final AbstractInputCheckedMapDecorator parent) { super(iterator); this.parent = parent; } @Override public Map.Entry next() { final Map.Entry entry = getIterator().next(); return new MapEntry(entry, parent); } } /** * Implementation of a map entry that checks additions via setValue. */ private class MapEntry extends AbstractMapEntryDecorator { /** The parent map */ private final AbstractInputCheckedMapDecorator parent; protected MapEntry(final Map.Entry entry, final AbstractInputCheckedMapDecorator parent) { super(entry); this.parent = parent; } @Override public V setValue(V value) { value = parent.checkSetValue(value); return getMapEntry().setValue(value); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy