/******************************************************************************* * Copyright (c) 2010-present Sonatype, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Stuart McCulloch (Sonatype, Inc.) - initial API and implementation *******************************************************************************/ package org.eclipse.sisu.wire; import java.util.AbstractMap; import java.util.AbstractSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; /** * Delegating {@link Map} that merges a series of {@link Map}s into one consistent view. */ final class MergedProperties extends AbstractMap<Object, Object> { // ---------------------------------------------------------------------- // Implementation fields // ---------------------------------------------------------------------- private transient volatile Set<Entry<Object, Object>> entrySet; final Map<?, ?>[] properties; // ---------------------------------------------------------------------- // Constructors // ---------------------------------------------------------------------- MergedProperties( final List<Map<?, ?>> properties ) { this.properties = properties.toArray( new Map[properties.size()] ); } // ---------------------------------------------------------------------- // Public methods // ---------------------------------------------------------------------- @Override public Object get( final Object key ) { for ( final Map<?, ?> p : properties ) { final Object value = p.get( key ); if ( null != value ) { return value; } } return null; } @Override public boolean containsKey( final Object key ) { for ( final Map<?, ?> p : properties ) { if ( p.containsKey( key ) ) { return true; } } return false; } @Override public Set<Entry<Object, Object>> entrySet() { if ( null == entrySet ) { entrySet = new MergedEntries(); } return entrySet; } // ---------------------------------------------------------------------- // Implementation types // ---------------------------------------------------------------------- final class MergedEntries extends AbstractSet<Entry<Object, Object>> { @Override public Iterator<Entry<Object, Object>> iterator() { return new Iterator<Entry<Object, Object>>() { @SuppressWarnings( "rawtypes" ) private Iterator<? extends Entry> itr; private int index; public boolean hasNext() { while ( null == itr || !itr.hasNext() ) { if ( index >= properties.length ) { return false; } itr = properties[index++].entrySet().iterator(); } return true; } @SuppressWarnings( "unchecked" ) public Entry<Object, Object> next() { if ( hasNext() ) { return itr.next(); } throw new NoSuchElementException(); } public void remove() { throw new UnsupportedOperationException(); } }; } @Override public int size() { int size = 0; for ( final Map<?, ?> p : properties ) { size += p.size(); } return size; } } }