/****************************************************************************** * 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.samples.zipcodes; import static java.nio.charset.StandardCharsets.UTF_8; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.Path; import org.eclipse.sapphire.samples.internal.SapphireSamplesPlugin; import org.eclipse.sapphire.util.EqualsFactory; import org.eclipse.sapphire.util.HashCodeFactory; /** * @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a> */ public final class ZipCodeRepository { private static boolean initialized = false; private static Map<IndexKey,List<ZipCodeRecord>> index = new HashMap<IndexKey,List<ZipCodeRecord>>(); public static SortedSet<String> getZipCodes( final String stateCode, final String city ) { final TreeSet<String> result = new TreeSet<String>(); for( ZipCodeRecord record : find( null, stateCode, city ) ) { result.add( record.getZipCode() ); } return result; } public static SortedSet<String> getStateCodes( final String zipCode, final String city ) { final TreeSet<String> result = new TreeSet<String>(); for( ZipCodeRecord record : find( zipCode, null, city ) ) { result.add( record.getStateCode() ); } return result; } public static SortedSet<String> getCities( final String zipCode, final String stateCode ) { final TreeSet<String> result = new TreeSet<String>(); for( ZipCodeRecord record : find( zipCode, stateCode, null ) ) { result.add( record.getCity() ); } return result; } public static List<ZipCodeRecord> find( final String zipCode, final String stateCode, final String city ) { initialize(); List<ZipCodeRecord> result = index.get( new IndexKey( zipCode, stateCode, city ) ); if( result != null ) { result = Collections.unmodifiableList( result ); } else { result = Collections.emptyList(); } return result; } private static synchronized void initialize() { if( initialized ) { return; } final URL zipCodesRepositoryUrl = FileLocator.find( SapphireSamplesPlugin.getBundle(), new Path( "zipcodes/zipcodes.txt" ), null ); try( BufferedReader r = new BufferedReader( new InputStreamReader( zipCodesRepositoryUrl.openStream(), UTF_8 ) ) ) { for( String line = r.readLine(); line != null; line = r.readLine() ) { final String[] segments = line.split( "\\|\\|" ); if( segments.length == 6 ) { final String zipCode = segments[ 0 ]; final String stateCode = segments[ 3 ]; final String city = segments[ 4 ]; final String county = segments[ 5 ]; final ZipCodeRecord record = new ZipCodeRecord( zipCode, stateCode, county, city ); addToIndex( new IndexKey( null, null, null ), record ); addToIndex( new IndexKey( record.getZipCode(), null, null ), record ); addToIndex( new IndexKey( null, record.getStateCode(), null ), record ); addToIndex( new IndexKey( null, null, record.getCity() ), record ); addToIndex( new IndexKey( record.getZipCode(), record.getStateCode(), null ), record ); addToIndex( new IndexKey( record.getZipCode(), null, record.getCity() ), record ); addToIndex( new IndexKey( null, record.getStateCode(), record.getCity() ), record ); } } } catch( final IOException e ) { SapphireSamplesPlugin.log( e ); } initialized = true; } private static void addToIndex( final IndexKey indexKey, final ZipCodeRecord record ) { List<ZipCodeRecord> list = index.get( indexKey ); if( list == null ) { list = new ArrayList<ZipCodeRecord>(); index.put( indexKey, list ); } list.add( record ); } private static final class IndexKey { private final String zip; private final String state; private final String city; public IndexKey( final String zip, final String state, final String city ) { this.zip = zip; this.state = ( state == null ? null : state.toLowerCase() ); this.city = ( city == null ? null : city.toLowerCase() ); } public boolean equals( final Object obj ) { if( ! ( obj instanceof IndexKey ) ) { return false; } final IndexKey k = (IndexKey) obj; return EqualsFactory .start() .add( this.zip, k.zip ) .add( this.state, k.state ) .add( this.city, k.city ) .result(); } public int hashCode() { return HashCodeFactory .start() .add( this.zip ) .add( this.state ) .add( this.city ) .result(); } } }