/*
* [PrepareTaxTables.java]
*
* Summary: Prepare district tax info as serialised resource.
*
* Copyright: (c) 1999-2017 Roedy Green, Canadian Mind Products, http://mindprod.com
*
* Licence: This software may be copied and used freely for any purpose but military.
* http://mindprod.com/contact/nonmil.html
*
* Requires: JDK 1.8+
*
* Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/
*
* Version History:
* 1.0 2010-05-09 initial version
*/
package com.mindprod.americantax;
import com.mindprod.common18.Build;
import com.mindprod.csv.CSVReader;
import java.io.BufferedReader;
import java.io.EOFException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.zip.GZIPOutputStream;
import static java.lang.System.*;
/**
* Prepare district tax info as serialised resource.
*
* Generates code for AmericanTax.java table.
*
* @author Roedy Green, Canadian Mind Products
* @version 1.0 2010-05-09 initial version
* @since 2010-05-09
*/
public final class PrepareTaxTables
{
private static final boolean DEBUGGING = false;
/**
* CSV format district tax table file name
*/
private static final String DISTRICT_TAX_FILE = Build.MINDPROD_SOURCE + "/americantax/districttax.csv";
/**
* serialised file to be included as resource
*/
private static final String RESOURCE_FILE = Build.MINDPROD_SOURCE + "/americantax/taxtables.ser";
/**
* CSV format state tax table file name
* http://en.wikipedia.org/wiki/Sales_taxes_in_the_United_States
*/
private static final String STATE_TAX_FILE = Build.MINDPROD_SOURCE + "/americantax/statetax.csv";
/**
* state item objects in order want to see them on screen. We use Vector because that is what JComboBox wants.
*/
private static final ArrayList stateItems = new ArrayList<>( 60 );
/**
* format percentages
*/
private static final DecimalFormat df4 = new DecimalFormat( "#0.0000" );
/**
* look up by key "WA" to get taxRate, state name "Washington" etc. use a prime size for speed
*/
private static final HashMap stateHash =
new HashMap<>( 71 );
/**
* read district tax rates
*/
private static void prepareDistricts()
{
try
{
// state, country, tax rate for county
CSVReader r = new CSVReader( new BufferedReader( new FileReader(
DISTRICT_TAX_FILE ), 8092 ),
',',
'\"',
"#",
true
/* hide comments */,
true
/* trimQuoted */,
true
/* trimUnquoted */,
false
/* no multiline */
);
try
{
while ( true )
{
final String stateAbbr = r.get().intern();
final String countyName = r.get().intern();
final String cityName = r.get().intern();
final double districtPercent = r.getDouble();
r.skipToNextLine();
StateItem stateItem = stateHash.get( stateAbbr );
if ( stateItem == null )
{
err.println( "invalid state " + stateAbbr + " " + countyName + " " + cityName + " " +
districtPercent );
}
else
{
DistrictItem districtItem = new DistrictItem( stateItem,
countyName,
cityName,
districtPercent );
stateItem.add( districtItem );
if ( DEBUGGING )
{
out.println( stateAbbr
+ " dist:"
+ df4.format( districtItem.getDistrictTaxRate() / 10000d )
+ " total:"
+ df4.format( districtItem.getTotalTaxRate() / 10000d )
+ " " + countyName + " " + cityName );
}
}
// no hash, or ArrayList of DistrictItems. They are reached only via corresponding StateItem.
}
}
catch ( EOFException e )
{
r.close();
}
}
catch ( IOException e )
{
err.println( e.getMessage() );
err.println( "can't read " + DISTRICT_TAX_FILE );
}
Comparator displayOrder = new DistrictItem.DisplayOrder();
for ( StateItem stateItem : stateItems )
{
// sort items for each state by city/county
Collections.sort( stateItem.getDistrictItems(), displayOrder );
if ( stateItem.getDistrictItems().size() == 0 )
{
err.println( stateItem.getStateAbbr() + " has no district items" );
}
}
}
/**
* read state tax rates
*/
private static void prepareStates()
{
try
{
// stateabbr, statename,, tax rate for static
CSVReader r = new CSVReader( new BufferedReader( new FileReader(
STATE_TAX_FILE ), 8092 ),
',',
'\"',
"#",
true
/* hide comments */,
true
/* trimQuoted */,
true
/* trimUnquoted */,
false
/* no multiline */
);
try
{
while ( true )
{
final String stateAbbr = r.get().intern(); // want as compact as possible.
final String stateName = r.get().intern();
final double statePercent = r.getDouble();
r.skipToNextLine();
StateItem stateItem = new StateItem( stateAbbr, stateName, statePercent );
stateItems.add( stateItem );
stateHash.put( stateAbbr, stateItem );
}
}
catch ( EOFException e )
{
r.close();
}
}
catch ( IOException e )
{
err.println( e.getMessage() );
err.println( "can't read " + STATE_TAX_FILE );
}
}
/**
* save state and district tax info in a compressed resource.
*/
private static void save()
{
// prune list of districts attached to each state to optimal size.
for ( StateItem state : stateItems )
{
state.trimToSize();
}
try
{
// O P E N
final FileOutputStream fos = new FileOutputStream( RESOURCE_FILE, false /* append */ );
final GZIPOutputStream gzos = new GZIPOutputStream( fos, 4 * 1024 /* buffsize in bytes */ );
final ObjectOutputStream oos = new ObjectOutputStream( gzos );
// W R I T E
// districts will be written too, as attached Vector on each StateItem.
oos.writeObject( stateItems.toArray( new StateItem[ stateItems.size() ] ) );
// C L O S E
oos.close();
}
catch ( IOException e )
{
err.println( "unable to write " + RESOURCE_FILE );
}
}
@SuppressWarnings( { "InfiniteLoopStatement" } )
public static void main( String[] args )
{
prepareStates();
prepareDistricts();
save();
}
}