Advertisement
Guest User

BedsType.java

a guest
Aug 2nd, 2014
278
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 9.10 KB | None | 0 0
  1. package ps.myhome2.clean;
  2.  
  3. import java.text.NumberFormat;
  4. import java.text.ParseException;
  5. import java.util.ArrayList;
  6. import java.util.HashMap;
  7. import java.util.List;
  8. import java.util.Map;
  9. import java.util.regex.Matcher;
  10. import java.util.regex.Pattern;
  11.  
  12. /**
  13.  * Parse a myhome.ie description string. If the parse succeeds, there are accessors
  14.  * for square footage, sale type (sale or auction), house type (house, apartment, etc.),
  15.  * extended house type (detached, terrace, etc.), number of beds.
  16.  *
  17.  * If the parse did not succeed, getHouseType() will return null.
  18.  *
  19.  * Not thread-safe due to static NumberFormat.
  20.  *
  21.  * LICENSE: Do whatever you like with this. Absolutely no warranty as to fitness
  22.  * for any purpose is expressed or implied.
  23.  *
  24.  * v1.0 02-Aug-2014
  25.  * See http://www.thepropertypin.com/viewtopic.php?f=1&t=62995
  26.  *
  27.  */
  28. public class BedsType {
  29.    
  30.     private String bedsType;
  31.     private int squareFt;
  32.     private SaleType saleType;
  33.     private HouseType houseType;
  34.     private boolean specialTaxTreatment;
  35.     private String houseTypeStr;
  36.     private int numBeds;
  37.    
  38.     static public enum HouseType{House, Apartment, Site, Commercial, Unspecified};
  39.     static public enum SaleType{Sale, Auction, RentToBuy};
  40.  
  41.     /**
  42.      * Constructor.
  43.      * @param strBedsType the myhome.ie description
  44.      */
  45.     public BedsType(String strBedsType) {
  46.  
  47.         bedsType= strBedsType;
  48.  
  49.         // Temporary working strings
  50.         String desc = bedsType;
  51.         String s;
  52.        
  53.         // Remove noise words
  54.         desc = desc.replace('-', ' ');
  55.         desc = desc.replace('/', ' ');
  56.         s = "from ";
  57.         if (desc.contains(s)) {
  58.             desc = removeString(desc, s);
  59.         }
  60.         s = "to ";
  61.         if (desc.contains(s)) {
  62.             desc = removeString(desc, s);
  63.         }
  64.        
  65.         // Check tax
  66.         for (String tax : kTaxTreatments) {
  67.             if (desc.contains(tax)) {
  68.                 specialTaxTreatment = true;
  69.                 desc = removeString(desc, tax);
  70.                 break;
  71.             }
  72.         }
  73.  
  74.         // Compress the remaining string
  75.         desc = compressString(desc);
  76.            
  77.        
  78.         // Check sale/auction
  79.         saleType = SaleType.Sale; // default
  80.         for (Pair<String, SaleType> pair : kSaleTypeList) {
  81.             if (desc.contains(pair.first())) {
  82.                 saleType = pair.second();
  83.                 desc = removeString(desc, pair.first());
  84.                 break;
  85.             }
  86.         }
  87.        
  88.         try {
  89.            
  90.             // Number of beds
  91.             s = " Bed";
  92.             if (desc.contains(s)) {
  93.                 int pos = desc.indexOf(s);
  94.                 String strNumBeds = desc.substring(0, pos);
  95.                 desc = desc.substring(pos + s.length());
  96.                 numBeds = intFormat.parse(compressString(strNumBeds)).intValue();
  97.             }
  98.            
  99.             // Floor area
  100.             desc = doFloorArea(desc);
  101.            
  102.         } catch (ParseException ex) {
  103.             return;
  104.         }
  105.  
  106.         // Residual string contains a valid house type
  107.         // or the whole parse is considered invalid
  108.         houseTypeStr = compressString(desc);
  109.         houseType = houseTypeMap.get(houseTypeStr);
  110.  
  111.     }
  112.  
  113.     /**
  114.      * Compute floor area if present.
  115.      * @param desc the myhome.ie description containing the floor area
  116.      * @return the description string after floor area parsed out
  117.      * @throws ParseException
  118.      */
  119.     private String doFloorArea(String desc) throws ParseException {
  120.        
  121.         Matcher m = kPatMetres.matcher(desc);
  122.         if (m.find()) {
  123.             String strNum = m.group(1);
  124.             desc = removeString(desc, m.group());
  125.             double d = numFormat.parse(strNum).doubleValue();
  126.             d *= 10.76; // metres to square ft.
  127.             squareFt = (int)d; // truncate to integer
  128.         }
  129.         m = kPatFoot.matcher(desc);
  130.         if (m.find()) {
  131.             String strNum = m.group(1);
  132.             desc = removeString(desc, m.group());
  133.             if (squareFt == 0) {
  134.                 // Only use sq.ft. if we didn't have metres
  135.                 double d = numFormat.parse(strNum).doubleValue();
  136.                 squareFt = (int)d;
  137.             }
  138.         }
  139.         // More matches to swallow unwanted duplicates/ranges e.g. x ft to y ft
  140.         Pattern[] pats = {kPatMetres, kPatFoot, kPatAcre, kPatAcre};
  141.         for (Pattern pat : pats) {
  142.             m = pat.matcher(desc);
  143.             if (m.find()) {
  144.                 desc = removeString(desc, m.group());
  145.             }
  146.         }
  147.        
  148.         return desc;
  149.        
  150.     }
  151.    
  152.     /**
  153.      * The original myhome.ie description
  154.      *
  155.      * @return the description
  156.      */
  157.     public String getBedsType() {
  158.         return bedsType;
  159.     }
  160.    
  161.     /**
  162.      * Number of beds
  163.      *
  164.      * @return num beds if present in description string, otherwise zero
  165.      */
  166.     public int getNumBeds() {
  167.         return numBeds;
  168.     }
  169.    
  170.     /**
  171.      * Floor area in sq. ft.
  172.      *
  173.      * @return Floor area in sq. ft. if present, otherwise zero.
  174.      */
  175.     public int getSquareFt() {
  176.         return squareFt;
  177.     }
  178.    
  179.     /**
  180.      * House type. If this returns null then all the rest of the data is
  181.      * unreliable too.
  182.      *
  183.      * @return
  184.      */
  185.     public HouseType getHouseType() {
  186.         return houseType;
  187.     }
  188.  
  189.     /**
  190.      * Extended house type string.
  191.      *
  192.      * @return house type string
  193.      */
  194.     public String getHouseTypeStr() {
  195.         return houseTypeStr;
  196.     }
  197.  
  198.     /**
  199.      * Sale type.
  200.      * @return the sale type.
  201.      */
  202.     public SaleType getSaleType() {
  203.         return saleType;
  204.     }
  205.  
  206.     /**
  207.      * True if there was any special tax treatment e.g. section 23.
  208.      * @return tax treatment
  209.      */
  210.     public boolean getSpecialTaxTreatment() {
  211.         return specialTaxTreatment;
  212.     }
  213.  
  214.     // Static Metadata
  215.    
  216.     static private Map<String, HouseType> houseTypeMap;
  217.     static {
  218.         Object[] oh = {
  219.                 "", HouseType.Unspecified,
  220.                 "Site", HouseType.Site,
  221.                 "Development Land", HouseType.Site,
  222.                 "Apartment", HouseType.Apartment,
  223.                 "Penthouse", HouseType.Apartment,
  224.                 "Studio", HouseType.Apartment,
  225.                 "Live Work Unit", HouseType.Apartment,
  226.                 "Duplex", HouseType.Apartment,
  227.                 "House", HouseType.House,
  228.                 "Detached House", HouseType.House,
  229.                 "End of Terrace House", HouseType.House,
  230.                 "End of Terrace Houses", HouseType.House,
  231.                 "Semi Detached House", HouseType.House,
  232.                 "Terraced House", HouseType.House,
  233.                 "Bungalow", HouseType.House,
  234.                 "Country House", HouseType.House,
  235.                 "Period House", HouseType.House,
  236.                 "Cottage", HouseType.House,
  237.                 "Townhouse", HouseType.House,
  238.                 "Dormer", HouseType.House,
  239.                 "Holiday Home", HouseType.House,
  240.                 "Mews", HouseType.House,
  241.                 "Investment Property", HouseType.Commercial,
  242.                 "Office", HouseType.Commercial,
  243.                 "Pubs & Restaurants", HouseType.Commercial,
  244.                 "Retail Units", HouseType.Commercial,
  245.                 "Industrial Units", HouseType.Commercial,
  246.                 "Farm Land", HouseType.Commercial,
  247.                 "Farm", HouseType.Commercial,
  248.                 "Businesses", HouseType.Commercial,
  249.         };     
  250.         houseTypeMap = new HashMap<String, HouseType>();
  251.         for (int i = 0; i < oh.length; i += 2) {
  252.             houseTypeMap.put((String)oh[i], (HouseType)oh[i+1]);
  253.         }
  254.     }
  255.  
  256.     static final List<Pair<String, SaleType>> kSaleTypeList;
  257.     static {
  258.         kSaleTypeList = new ArrayList<Pair<String,SaleType>>();
  259.         Object os[] = {
  260.             "For Sale By Tender", SaleType.Sale,
  261.             "For Sale By Auction", SaleType.Auction,
  262.             "For Sale Rent To Buy", SaleType.RentToBuy,
  263.             "For Auction", SaleType.Auction,
  264.             "For Sale", SaleType.Sale,
  265.             "Rent To Buy", SaleType.RentToBuy,
  266.         };
  267.         for (int i = 0; i < os.length; i += 2) {
  268.             kSaleTypeList.add(new Pair<String, SaleType>((String)os[i], (SaleType)os[i+1]));
  269.         }
  270.        
  271.     }
  272.  
  273.     static final String kTaxTreatments[] = {
  274.         "Tax Section 23", "Tax Section 27",
  275.         "Tax Section 50", "Tax Pre 63", "Tax Holiday Home"
  276.     };
  277.    
  278.     static final Pattern kPatMetres = Pattern.compile("([[0-9][,.]]*) ?m²");
  279.     static final Pattern kPatFoot = Pattern.compile("([[0-9][,.]]*) ?ft²");
  280.     static final Pattern kPatAcre = Pattern.compile("([[0-9][,.]]*) ?((Acres?)|(Hectares))");
  281.     static NumberFormat intFormat = NumberFormat.getIntegerInstance();
  282.     static NumberFormat numFormat = NumberFormat.getNumberInstance();
  283.  
  284.     // Utilities
  285.    
  286.     /**
  287.      * A convenience class to represent a pair of values.
  288.      *
  289.      * @param <FIRST>
  290.      *            the type of the first value.
  291.      * @param <SECOND>
  292.      *            the type of the second value.
  293.      */
  294.     static class Pair<FIRST, SECOND> {
  295.         private FIRST first;
  296.         private SECOND second;
  297.  
  298.         public Pair(FIRST f, SECOND s) {
  299.             first = f;
  300.             second = s;
  301.         }
  302.        
  303.         public FIRST first() {
  304.             return first;
  305.         }
  306.  
  307.         public SECOND second() {
  308.             return second;
  309.         }
  310.     }
  311.    
  312.     // String methods
  313.    
  314.     /**
  315.      * Trim leading and trailing spaces and compress internal runs of white space to a single space.
  316.      * @param s string to compress
  317.      * @return compressed string
  318.      */
  319.     public static String compressString(String s) {
  320.         if (s == null) {
  321.             return "";
  322.         }
  323.         StringBuilder sb = new StringBuilder();
  324.         boolean inSpace = true;
  325.         for (int i = 0; i < s.length(); i++) {
  326.             char ch = s.charAt(i);
  327.             if (Character.isWhitespace(ch)) {
  328.                 if (!inSpace) {
  329.                     sb.append(' ');
  330.                     inSpace = true;
  331.                 }
  332.             } else {
  333.                 sb.append(ch);
  334.                 inSpace = false;
  335.             }
  336.         }
  337.         int len = sb.length();
  338.         if ((len > 0) && (sb.charAt(len - 1) == ' ')) {
  339.             sb.delete(len - 1, len);
  340.         }
  341.         return sb.toString();
  342.     }
  343.  
  344.     /**
  345.      * Remove one string embedded in another.
  346.      *
  347.      * @param s
  348.      *            the input string
  349.      * @param toRemove
  350.      *            the string to remove
  351.      * @return if s contains toRemove then a new string with toRemove removed,
  352.      *         otherwise s
  353.      */
  354.     public static String removeString(String s, String toRemove) {
  355.         int pos = s.indexOf(toRemove);
  356.         return (pos < 0) ? s : s.substring(0, pos)
  357.                 + s.substring(pos + toRemove.length());
  358.     }
  359.    
  360.    
  361. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement