package com.github.huangzhiyi.shpmdir;

import java.util.BitSet;

/**
 * China Mainland city code set.
 * 
 * @author huangzhiyi
 *
 */
public class CitySet {

	private final static int DEFAULT_END=1000;
	
	private int start=0;
	private int end=DEFAULT_END;
	private BitSet bs=new BitSet(DEFAULT_END);

	/**
	 * Build from binary string like '10100010'
	 * @param bin Binary String
	 * @return
	 */
	public static CitySet ofBinStr(String bin){
		CitySet cs=emptySet();
		if(bin!=null){
			char[] ca=bin.toCharArray();
			int size=Math.min(cs.end, bin.length());
			for(int i=cs.start;i<size;i++){
				if(ca[i]=='1'){
					cs.bs.set(i);
				}
			}
		}
		return cs;
	}
	
	/**
	 * Build with city codes
	 * 
	 * @param cityCodes
	 * @return
	 */
	public static CitySet ofCityCodes(String... cityCodes){
		return emptySet().add(cityCodes);
	}
	
	/**
	 * True if city set contains all the specified city codes.
	 * @param cityCodes
	 * @return
	 */
	public boolean contains(String... cityCodes){
		if(cityCodes==null){
			return false;
		}
		
		for(String cityCode:cityCodes){
			if(!bs.get(Integer.valueOf(cityCode))){
				return false;
			}
		}
		return true;
	}
	
	/**
	 * 
	 * @return An empty set
	 */
	public static CitySet emptySet(){
		return new CitySet();
	}
	
	private CitySet(){
		bs.set(0);//The binary string should be started from 1
	}
	
	/**
	 * Add city code.
	 * @param cityCodes
	 * @return
	 */
	public CitySet add(String... cityCodes){
		for(String cityCode:cityCodes){
			bs.set(Integer.valueOf(cityCode));
		}
		return this;
	}
	
	/**
	 * Convert to binary string.
	 * @return
	 */
	public String toBinStr(){
		StringBuilder b = new StringBuilder();

        int cur = bs.nextSetBit(0);
        if (cur != -1) {
        	int last=cur+1;
            b.append('1');
            for (cur = bs.nextSetBit(cur+1); cur >= 0; cur = bs.nextSetBit(cur+1)) {
                while(last++<cur){
                	b.append('0');
                }
            	
            	int endOfRun = bs.nextClearBit(cur);
                do { b.append('1'); }
                while (++cur < endOfRun);
                last=cur;
            }
        }

        return b.toString();
	}
}

@@ -218,24 +218,30 @@
 %09%0D%0A%09private 
+final 
 int start=0;
@@ -251,16 +251,22 @@
 private 
+final 
 int end=
@@ -1234,24 +1234,227 @@
 %7D%0D%0A%09%0D%0A%09/**%0D%0A
+%09 * Return true if no city code contained.%0D%0A%09 * @return%0D%0A%09 */%0D%0A%09public boolean isEmpty()%7B%0D%0A%09%09return %221%22.equals(this.toBinStr());%0D%0A%09%7D%0D%0A%09%0D%0A%09public boolean isNotEmpty()%7B%0D%0A%09%09return !isEmpty();%0D%0A%09%7D%0D%0A%09%0D%0A%09/**%0D%0A
 %09 * %0D%0A%09 * @r
@@ -1837,32 +1837,358 @@
 n this;%0D%0A%09%7D%0D%0A%09%0D%0A
+%09@Override%0D%0A%09public boolean equals(Object obj)%7B%0D%0A%09%09boolean result=false;%0D%0A%09%09if(obj instanceof CitySet)%7B%0D%0A%09%09%09result=bs.equals(((CitySet) obj).getBs());%0D%0A%09%09%7D%0D%0A%09%09return result;%0D%0A%09%7D%0D%0A%09%0D%0A%09@Override%0D%0A%09public int hashCode()%7B%0D%0A%09%09return bs.hashCode()+23;%0D%0A%09%7D%0D%0A%09%0D%0A%09@Override%0D%0A%09public String toString()%7B%0D%0A%09%09return bs.toString();%0D%0A%09%7D%0D%0A%09%0D%0A
 %09/**%0D%0A%09 * Conver
@@ -2789,24 +2789,24 @@
        %7D%0D%0A%0D%0A
-
         retu
@@ -2826,12 +2826,58 @@
 ();%0D%0A%09%7D%0D
+%0A%0D%0A%09public BitSet getBs() %7B%0D%0A%09%09return bs;%0D%0A%09%7D%0D
 %0A%7D%0D%0A

Add some override methods