/* * 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. * * Other licenses: * ----------------------------------------------------------------------------- * Commercial licenses for this work are available. These replace the above * ASL 2.0 and offer limited warranties, support, maintenance, and commercial * database integrations. * * For more information, please visit: http://www.jooq.org/licenses * * * * * * * * * * * * * */ package org.jooq.impl; import java.util.AbstractMap; import java.util.AbstractSet; import java.util.Collections; import java.util.EnumMap; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.jooq.Scope; import org.jooq.impl.Tools.DataKey; /** * The {@link Map} implementation for use with {@link Scope#data()}. * * @author Lukas Eder */ final class DataMap extends AbstractMap<Object, Object> { final EnumMap<DataKey, Object> internal; Map<Object, Object> external; final Set<Entry<Object, Object>> entrySet; DataMap() { internal = new EnumMap<DataKey, Object>(DataKey.class); entrySet = new EntrySet(); } @Override public final int size() { return internal().size() + external(false).size(); } @Override public final boolean isEmpty() { return internal().isEmpty() && external(false).isEmpty(); } @Override public final boolean containsKey(Object key) { return delegate(key, false).containsKey(key); } @Override public final boolean containsValue(Object value) { return internal().containsValue(value) || external(false).containsValue(value); } @Override public final Object get(Object key) { return delegate(key, false).get(key); } @Override public final Object put(Object key, Object value) { return delegate(key, true).put(key, value); } @Override public final Object remove(Object key) { return delegate(key, true).remove(key); } @Override public final void clear() { internal().clear(); external(true).clear(); } @Override public final Set<Entry<Object, Object>> entrySet() { return entrySet; } @SuppressWarnings({ "rawtypes", "unchecked" }) private final Map<Object, Object> internal() { return (Map) internal; } private final Map<Object, Object> external(boolean initialise) { if (external == null) { if (initialise) external = new HashMap<Object, Object>(); else return Collections.emptyMap(); } return external; } @SuppressWarnings({ "unchecked", "rawtypes" }) private final Map<Object, Object> delegate(Object key, boolean initialise) { return key instanceof DataKey ? (Map) internal() : external(initialise); } private class EntrySet extends AbstractSet<Entry<Object, Object>> { @Override public final Iterator<Entry<Object, Object>> iterator() { return new Iterator<Entry<Object, Object>>() { final Iterator<Entry<Object, Object>> internalIterator = internal().entrySet().iterator(); final Iterator<Entry<Object, Object>> externalIterator = external(false).entrySet().iterator(); @Override public final boolean hasNext() { return internalIterator.hasNext() || externalIterator.hasNext(); } @Override public final Entry<Object, Object> next() { return internalIterator.hasNext() ? internalIterator.next() : externalIterator.next(); } @Override public final void remove() { throw new UnsupportedOperationException(); } }; } @Override public final int size() { return DataMap.this.size(); } } }