/****************************************************************************** * Copyright (c) 2016 Oracle * 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: * Konstantin Komissarchik - initial implementation and ongoing maintenance ******************************************************************************/ package org.eclipse.sapphire.util; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; import org.eclipse.sapphire.Filter; /** * @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a> */ public final class SetFactory<E> { private Filter<E> filter; private E firstElement = null; private Set<E> set = null; private boolean exported = false; private SetFactory() {} public static <E> Set<E> empty() { return Collections.emptySet(); } public static <E> Set<E> singleton( final E element ) { return Collections.singleton( element ); } @SafeVarargs public static <E> Set<E> unmodifiable( final E... elements ) { return SetFactory.<E>start().add( elements ).result(); } public static <E> Set<E> unmodifiable( final Collection<E> elements ) { return SetFactory.<E>start().add( elements ).result(); } public static <E> SetFactory<E> start() { return new SetFactory<E>(); } public SetFactory<E> filter( final Filter<E> filter ) { if( this.exported ) { throw new IllegalStateException(); } this.filter = filter; if( this.filter != null ) { if( this.set != null ) { for( Iterator<E> itr = this.set.iterator(); itr.hasNext(); ) { if( ! this.filter.allows( itr.next() ) ) { itr.remove(); } } final int size = this.set.size(); if( size == 1 ) { this.firstElement = this.set.iterator().next(); this.set = null; } else if( size == 0 ) { this.set = null; } } else if( this.firstElement != null ) { if( ! this.filter.allows( this.firstElement ) ) { this.firstElement = null; } } } return this; } public SetFactory<E> add( final E element ) { if( this.exported ) { throw new IllegalStateException(); } if( element != null && ( this.filter == null || this.filter.allows( element ) ) ) { if( this.set != null ) { this.set.add( element ); } else if( this.firstElement != null ) { this.set = new LinkedHashSet<E>(); this.set.add( this.firstElement ); this.set.add( element ); this.firstElement = null; } else { this.firstElement = element; } } return this; } @SafeVarargs public final SetFactory<E> add( final E... elements ) { if( elements != null ) { for( E element : elements ) { add( element ); } } return this; } public SetFactory<E> add( final Collection<E> elements ) { if( elements != null ) { for( E element : elements ) { add( element ); } } return this; } public boolean remove( final E element ) { boolean removed = false; if( element != null ) { if( this.set != null ) { removed = this.set.remove( element ); if( this.set.size() == 1 ) { this.firstElement = this.set.iterator().next(); this.set = null; } } else if( this.firstElement != null && this.firstElement.equals( element ) ) { removed = true; this.firstElement = null; } } return removed; } public boolean contains( final E element ) { boolean contains = false; if( this.set != null ) { contains = this.set.contains( element ); } else if( this.firstElement != null && this.firstElement.equals( element ) ) { contains = true; } return contains; } public int size() { final int size; if( this.set != null ) { size = this.set.size(); } else if( this.firstElement != null) { size = 1; } else { size = 0; } return size; } public Set<E> result() { if( this.exported ) { throw new IllegalStateException(); } this.exported = true; if( this.set != null ) { return Collections.unmodifiableSet( this.set ); } else if( this.firstElement != null ) { return Collections.singleton( this.firstElement ); } else { return Collections.emptySet(); } } }