public class OfferAPIBean {
	private String attributionSrc;
	private String rating;
	private String reviewCount;
	private String profileUrl;
	private String phone;
	private String imageUrl;
	private String listingId;
	private String listingName;
	private String offerId;
	private String offerDescription;
	private String offerTitle;
	private String referenceId;
	private String latitude;
	private String longitude;
	private String street;
	private String city;
	private String state;
	private String zip;
	private String couponUrl;
	private LocationProfile profile;

	public String getAttributionSrc() {
		return attributionSrc;
	}

	public void setAttributionSrc(String attributionSrc) {
		this.attributionSrc = attributionSrc;
	}

	public String getRating() {
		return rating;
	}

	public void setRating(String rating) {
		this.rating = rating;
	}

	public String getReviewCount() {
		return reviewCount;
	}

	public void setReviewCount(String reviewCount) {
		this.reviewCount = reviewCount;
	}

	public String getProfileUrl() {
		return profileUrl;
	}

	public void setProfileUrl(String profileUrl) {
		this.profileUrl = profileUrl;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public String getImageUrl() {
		return imageUrl;
	}

	public void setImageUrl(String imageUrl) {
		this.imageUrl = imageUrl;
	}

	public String getListingId() {
		return listingId;
	}

	public void setListingId(String listingId) {
		this.listingId = listingId;
	}

	public String getListingName() {
		return listingName;
	}

	public void setListingName(String listingName) {
		this.listingName = listingName;
	}

	public String getOfferId() {
		return offerId;
	}

	public void setOfferId(String offerId) {
		this.offerId = offerId;
	}

	public String getOfferDescription() {
		return offerDescription;
	}

	public void setOfferDescription(String offerDescription) {
		this.offerDescription = offerDescription;
	}

	public String getOfferTitle() {
		return offerTitle;
	}

	public void setOfferTitle(String offerTitle) {
		this.offerTitle = offerTitle;
	}

	public String getReferenceId() {
		return referenceId;
	}

	public void setReferenceId(String referenceId) {
		this.referenceId = referenceId;
	}

	public String getLatitude() {
		return latitude;
	}

	public void setLatitude(String latitude) {
		this.latitude = latitude;
	}

	public String getLongitude() {
		return longitude;
	}

	public void setLongitude(String longitude) {
		this.longitude = longitude;
	}

	public String getStreet() {
		return street;
	}

	public void setStreet(String street) {
		this.street = street;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}

	public String getZip() {
		return zip;
	}

	public void setZip(String zip) {
		this.zip = zip;
	}

	public String getCouponUrl() {
		return couponUrl;
	}

	public void setCouponUrl(String couponUrl) {
		this.couponUrl = couponUrl;
	}

	public LocationProfile getProfile() {
		return profile;
	}

	public void setProfile(LocationProfile profile) {
		this.profile = profile;
	}

} public class OfferProxy extends AbstractProxy {
	private final static String PROPERTY_OFFERS_URL = "offers.url";
	private Logger log = Logger.getLogger(getClass());
	private static final String OFFER = "offer";
	private static final String RPP_OFFERS = "2";
	private static final String CITY = "city";
	private static final String ATTRIBUTION_SOURCE = "attribution_source";
	private static final String CS_RATING = "cs_rating";
	private static final String REVIEW_COUNT = "review_count";
	private static final String IMAGE_URL = "image_url";
	private static final String LATITUDE = "latitude";
	private static final String LISTING_ID = "listing_id";
	private static final String LISTING_NAME = "listing_name";
	private static final String LONGITUDE = "longitude";
	private static final String OFFER_DESCRIPTION = "offer_description";
	private static final String OFFER_ID = "offer_id";
	private static final String OFFER_TITLE = "offer_title";
	private static final String REFERENCE_ID = "reference_id";
	private static final String STATE = "state";
	private static final String STREET = "street";
	private static final String ZIP = "zip";
	private static final String PUBLISHER_HEADER = "X-Publisher";

	protected String getQueryString(RequestBean request)
			throws CitysearchException {
		log.info("Start OfferProxy getQueryString()");
		StringBuilder strBuilder = new StringBuilder();

		strBuilder.append(constructQueryParam(APIFieldNameConstants.RPP,
				RPP_OFFERS));
		strBuilder.append(CommonConstants.SYMBOL_AMPERSAND);

		strBuilder.append(constructQueryParam(APIFieldNameConstants.CLIENT_IP,
				request.getClientIP()));
		strBuilder.append(CommonConstants.SYMBOL_AMPERSAND);

		if (!StringUtils.isBlank(request.getWhat())) {
			// Offers API throws internal error when reading sushi+restaurant
			String what = request.getWhat().trim();
			try {
				what = URLEncoder.encode(what, "UTF-8");
			} catch (UnsupportedEncodingException excep) {
				throw new CitysearchException("OffersHelper", "getQueryString",
						excep);
			}
			strBuilder.append(constructQueryParam(APIFieldNameConstants.WHAT,
					what));
		}

		if (!StringUtils.isBlank(request.getLatitude())
				&& !StringUtils.isBlank(request.getLongitude())) {
			strBuilder.append(CommonConstants.SYMBOL_AMPERSAND);
			strBuilder.append(constructQueryParam(
					APIFieldNameConstants.LATITUDE, request.getLatitude()
							.trim()));

			strBuilder.append(CommonConstants.SYMBOL_AMPERSAND);
			strBuilder.append(constructQueryParam(
					APIFieldNameConstants.LONGITUDE, request.getLongitude()
							.trim()));
		} else {
			strBuilder.append(CommonConstants.SYMBOL_AMPERSAND);
			strBuilder.append(constructQueryParam(APIFieldNameConstants.WHERE,
					request.getWhere().trim()));
		}
		if (!StringUtils.isBlank(request.getTag())) {
			strBuilder.append(CommonConstants.SYMBOL_AMPERSAND);
			strBuilder.append(constructQueryParam(APIFieldNameConstants.TAG,
					request.getTag().trim()));
		}
		if (!StringUtils.isBlank(request.getExpiresBefore())) {
			strBuilder.append(CommonConstants.SYMBOL_AMPERSAND);
			strBuilder.append(constructQueryParam(
					APIFieldNameConstants.EXPIRES_BEFORE, request
							.getExpiresBefore().trim()));
		}
		if (!StringUtils.isBlank(request.getCustomerHasbudget())) {
			strBuilder.append(CommonConstants.SYMBOL_AMPERSAND);
			strBuilder.append(constructQueryParam(
					APIFieldNameConstants.CUSTOMER_HASBUDGET, String
							.valueOf(request.getCustomerHasbudget().trim())));
		}
		if (!StringUtils.isBlank(request.getRadius())) {
			strBuilder.append(CommonConstants.SYMBOL_AMPERSAND);
			String radius = Utils.parseRadius(request.getRadius());
			request.setRadius(radius);
			strBuilder.append(constructQueryParam(APIFieldNameConstants.RADIUS,
					request.getRadius()));
		}
		if (!StringUtils.isBlank(request.getCallBackFunction())) {
			strBuilder.append(CommonConstants.SYMBOL_AMPERSAND);
			strBuilder.append(constructQueryParam(
					APIFieldNameConstants.CALLBACK, request
							.getCallBackFunction().trim()));
		}
		log.info("Start OfferProxy getQueryString() querystring is "
				+ strBuilder);
		return strBuilder.toString();
	}

	private OfferAPIBean toOffer(Element offerElement)
			throws CitysearchException {
		OfferAPIBean offer = new OfferAPIBean();
		offer.setCity(offerElement.getChildText(CITY));
		offer.setState(offerElement.getChildText(STATE));
		offer.setAttributionSrc(offerElement.getChildText(ATTRIBUTION_SOURCE));
		offer.setRating(offerElement.getChildText(CS_RATING));
		offer.setReviewCount(offerElement.getChildText(REVIEW_COUNT));
		offer.setImageUrl(offerElement.getChildText(IMAGE_URL));
		offer.setLatitude(offerElement.getChildText(LATITUDE));
		offer.setListingId(offerElement.getChildText(LISTING_ID));
		offer.setLongitude(offerElement.getChildText(LONGITUDE));
		offer.setOfferId(offerElement.getChildText(OFFER_ID));
		offer.setOfferTitle(offerElement.getChildText(OFFER_TITLE));
		offer.setOfferDescription(offerElement.getChildText(OFFER_DESCRIPTION));
		offer.setListingName(offerElement.getChildText(LISTING_NAME));
		offer.setReferenceId(offerElement.getChildText(REFERENCE_ID));
		offer.setStreet(offerElement.getChildText(STREET));
		offer.setZip(offerElement.getChildText(ZIP));
		return offer;
	}

	private List<OfferAPIBean> parse(RequestBean request, Document doc,
			int requiredNoOfOffers) throws CitysearchException {
		log.info("Start OffersHelper parseXML");
		List<OfferAPIBean> offersList = null;
		if (doc != null && doc.hasRootElement()) {
			Element rootElement = doc.getRootElement();
			List<Element> offersElementList = rootElement.getChildren(OFFER);
			if (StringUtils.isBlank(request.getLatitude())
					|| StringUtils.isBlank(request.getLongitude())) {
				offersList = (List<OfferAPIBean>) getOffersByRating(request,
						offersElementList, requiredNoOfOffers);
			} else {
				offersList = (List<OfferAPIBean>) getOffersByDistance(request,
						offersElementList, requiredNoOfOffers);
			}
		}
		log.info("End OffersHelper parseXML");
		return offersList;
	}

	private List<OfferAPIBean> getOffersByDistance(RequestBean request,
			List<Element> offerElemList, int requiredNoOfOffers)
			throws CitysearchException {
		log.info("Start OffersHelper getOffersByDistance");
		List<OfferAPIBean> offersLst = new ArrayList<OfferAPIBean>();
		if (!offerElemList.isEmpty()) {
			BigDecimal sourceLatitude = new BigDecimal(request.getLatitude());
			BigDecimal sourceLongitude = new BigDecimal(request.getLongitude());
			SortedMap<Double, List<Element>> elmsSortedByDistance = new TreeMap<Double, List<Element>>();
			for (Element elm : offerElemList) {
				BigDecimal businessLatitude = new BigDecimal(elm
						.getChildText(CommonConstants.LATITUDE));
				BigDecimal businessLongitude = new BigDecimal(elm
						.getChildText(CommonConstants.LONGITUDE));
				double distance = Utils.getDistance(sourceLatitude,
						sourceLongitude, businessLatitude, businessLongitude);
				if (elmsSortedByDistance.containsKey(distance)) {
					elmsSortedByDistance.get(distance).add(elm);
				} else {
					List<Element> elms = new ArrayList<Element>();
					elms.add(elm);
					elmsSortedByDistance.put(distance, elms);
				}
			}
			offersLst = getOffersList(request, elmsSortedByDistance,
					requiredNoOfOffers);
		}
		log.info("End OffersHelper getOffersByDistance");
		return offersLst;
	}

	private List<OfferAPIBean> getOffersByRating(RequestBean request,
			List<Element> offerElemList, int requiredNoOfOffers)
			throws CitysearchException {
		log.info("Start OffersHelper getOffersByRating");
		List<OfferAPIBean> offersLst = new ArrayList<OfferAPIBean>();
		if (!offerElemList.isEmpty()) {
			SortedMap<Double, List<Element>> elmsSortedByRating = new TreeMap<Double, List<Element>>();
			for (Element elm : offerElemList) {
				String ratingVal = elm.getChildText(CS_RATING);
				if (!StringUtils.isBlank(ratingVal)
						&& NumberUtils.isNumber(ratingVal)) {
					double rating = NumberUtils.toDouble(ratingVal);
					if (elmsSortedByRating.containsKey(rating)) {
						elmsSortedByRating.get(rating).add(elm);
					} else {
						List<Element> elms = new ArrayList<Element>();
						elms.add(elm);
						elmsSortedByRating.put(rating, elms);
					}
				}
			}
			offersLst = getOffersList(request, elmsSortedByRating,
					requiredNoOfOffers);
		}
		log.info("End OffersHelper getOffersByRating");
		return offersLst;
	}

	private List<OfferAPIBean> getOffersList(RequestBean request,
			SortedMap<Double, List<Element>> sortedElms, int requiredNoOfOffers)
			throws CitysearchException {
		List<OfferAPIBean> offersLst = new ArrayList<OfferAPIBean>();
		if (!sortedElms.isEmpty()) {
			for (int j = 0; j < sortedElms.size(); j++) {
				if (offersLst.size() >= requiredNoOfOffers) {
					break;
				}
				Double key = sortedElms.firstKey();
				List<Element> elms = sortedElms.remove(key);
				for (int idx = 0; idx < elms.size(); idx++) {
					if (offersLst.size() == requiredNoOfOffers) {
						break;
					}
					OfferAPIBean offer = toOffer(elms.get(idx));
					offersLst.add(offer);
				}
			}
		}
		return offersLst;
	}

	public List<OfferAPIBean> getOffers(RequestBean request,
			int requiredNoOfOffers) throws InvalidRequestParametersException,
			CitysearchException {
		log.info("Start OfferProxy getOffers()");
		request.validate();
		request.setCustomerHasbudget("true");

		Properties properties = PropertiesLoader.getAPIProperties();
		StringBuilder urlString = new StringBuilder(properties
				.getProperty(PROPERTY_OFFERS_URL));
		urlString.append(getQueryString(request));
		Document responseDocument = null;
		try {
			String publisherHdr = request.getPublisher().trim();
			HashMap<String, String> hdrMap = new HashMap<String, String>();
			hdrMap.put(PUBLISHER_HEADER, publisherHdr);
			responseDocument = getAPIResponse(urlString.toString(), hdrMap);
		} catch (InvalidHttpResponseException ihe) {
			log.error(ihe.getMessage());
			return null;
		}
		log.info("End OfferProxy getOffers()");
		return parse(request, responseDocument, requiredNoOfOffers);
	}
} public class Offer {

    private String attributionSrc;
    private List<Integer> listingRating;
    private int reviewCount;
    private String profileUrl;
    private String profileTrackingUrl;
    private String phone;
    private String imageUrl;
    private String listingId;
    private String listingName;
    private String offerId;
    private String offerDescription;
    private String offerTitle;
    private String offerShortDescription;
    private String offerShortTitle;
    private String referenceId;
    private String latitude;
    private String longitude;
    private String street;
    private String city;
    private String state;
    private String zip;
    private String callBackFunction;
    private String callBackUrl;
    private String couponUrl;
    private String distance;
    private String location;
    private Profile profile;
    
    public Profile getProfile() {
        return profile;
    }

    public void setProfile(Profile profile) {
        this.profile = profile;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public String getCouponUrl() {
        return couponUrl;
    }

    public void setCouponUrl(String couponUrl) {
        this.couponUrl = couponUrl;
    }

    public String getCallBackFunction() {
        return callBackFunction;
    }

    public void setCallBackFunction(String callBackFunction) {
        this.callBackFunction = callBackFunction;
    }

    public String getCallBackUrl() {
        return callBackUrl;
    }

    public void setCallBackUrl(String callBackUrl) {
        this.callBackUrl = callBackUrl;
    }

    public String getProfileTrackingUrl() {
        return profileTrackingUrl;
    }

    public void setProfileTrackingUrl(String profileTrackingUrl) {
        this.profileTrackingUrl = profileTrackingUrl;
    }

    public String getAttributionSrc() {
        return attributionSrc;
    }

    public void setAttributionSrc(String attributionSrc) {
        this.attributionSrc = attributionSrc;
    }

    public List<Integer> getListingRating() {
        return listingRating;
    }

    public void setListingRating(List<Integer> listingRating) {
        this.listingRating = listingRating;
    }

    public int getReviewCount() {
        return reviewCount;
    }

    public void setReviewCount(int reviewCount) {
        this.reviewCount = reviewCount;
    }

    public String getProfileUrl() {
        return profileUrl;
    }

    public void setProfileUrl(String profileUrl) {
        this.profileUrl = profileUrl;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }

    public String getListingId() {
        return listingId;
    }

    public void setListingId(String listingId) {
        this.listingId = listingId;
    }

    public String getListingName() {
        return listingName;
    }

    public void setListingName(String listingName) {
        this.listingName = listingName;
    }

    public String getOfferId() {
        return offerId;
    }

    public void setOfferId(String offerId) {
        this.offerId = offerId;
    }

    public String getLatitude() {
        return latitude;
    }

    public void setLatitude(String latitude) {
        this.latitude = latitude;
    }

    public String getLongitude() {
        return longitude;
    }

    public void setLongitude(String longitude) {
        this.longitude = longitude;
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getZip() {
        return zip;
    }

    public void setZip(String zip) {
        this.zip = zip;
    }

    public String getOfferTitle() {
        return offerTitle;
    }

    public void setOfferTitle(String offerTitle) {
        this.offerTitle = offerTitle;
    }

    public String getOfferDescription() {
        return offerDescription;
    }

    public void setOfferDescription(String offerDescription) {
        this.offerDescription = offerDescription;
    }

    public String getOfferShortDescription() {
        if (offerShortDescription != null && offerShortDescription.length() > 36)
            offerShortDescription = offerShortDescription.substring(0, 36) + "...";

        return offerShortDescription;
    }

    public void setOfferShortDescription(String offerShortDescription) {
        this.offerShortDescription = offerShortDescription;
    }

    public String getOfferShortTitle() {
        if (offerShortTitle != null && offerShortTitle.length() > 20)
            offerShortTitle = offerShortTitle.substring(0, 20) + "...";

        return offerShortTitle;
    }

    public void setOfferShortTitle(String offerShortTitle) {
        this.offerShortTitle = offerShortTitle;
    }

    public String getDistance() {
        return distance;
    }

    public void setDistance(String distance) {
        this.distance = distance;
    }

    public String getReferenceId() {
        return referenceId;
    }

    public void setReferenceId(String referenceId) {
        this.referenceId = referenceId;
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();

        sb.append("=reviewCount=" + reviewCount);
        sb.append("=attributionSrc=" + attributionSrc);
        sb.append("=csRating=" + listingRating);
        sb.append("=imgUrl=" + imageUrl);
        sb.append("=listingId=" + listingId);
        sb.append("=listingName=" + listingName);
        sb.append("=offerDesc=" + offerDescription);
        sb.append("=offerId=" + offerId);
        sb.append("=offerTtl=" + offerTitle);
        sb.append("=refId=" + referenceId);
        sb.append("=lat=" + latitude);
        sb.append("=longs=" + longitude);
        sb.append("=street=" + street);
        sb.append("=city=" + city);
        sb.append("=state=" + state);
        sb.append("=zip=" + zip);
        sb.append("=distance=" + distance);

        return sb.toString();
    }
} public class Profile {
    private Address address;
    private String phone;
    private String profileUrl;
    private String sendToFriendUrl;
    private String sendToFriendTrackingUrl;
    private String imageUrl;
    private String reviewsUrl;
    private String websiteUrl;
    private String menuUrl;
    private String reservationUrl;
    private String mapUrl;
    private Review review;
    private String trackingUrl;
    private String listingId;
    private String reviewCount;
    
    public String getReviewCount() {
		return reviewCount;
	}

	public void setReviewCount(String reviewCount) {
		this.reviewCount = reviewCount;
	}

	public String getSendToFriendTrackingUrl() {
        return sendToFriendTrackingUrl;
    }

    public void setSendToFriendTrackingUrl(String sendToFriendTrackingUrl) {
        this.sendToFriendTrackingUrl = sendToFriendTrackingUrl;
    }

    public String getListingId() {
        return listingId;
    }

    public void setListingId(String listingId) {
        this.listingId = listingId;
    }

    public String getTrackingUrl() {
        return trackingUrl;
    }

    public void setTrackingUrl(String trackingUrl) {
        this.trackingUrl = trackingUrl;
    }

    public String getReviewsUrl() {
        return reviewsUrl;
    }

    public void setReviewsUrl(String reviewsUrl) {
        this.reviewsUrl = reviewsUrl;
    }

    public String getWebsiteUrl() {
        return websiteUrl;
    }

    public void setWebsiteUrl(String websiteUrl) {
        this.websiteUrl = websiteUrl;
    }

    public String getMenuUrl() {
        return menuUrl;
    }

    public void setMenuUrl(String menuUrl) {
        this.menuUrl = menuUrl;
    }

    public String getReservationUrl() {
        return reservationUrl;
    }

    public void setReservationUrl(String reservationUrl) {
        this.reservationUrl = reservationUrl;
    }

    public String getMapUrl() {
        return mapUrl;
    }

    public void setMapUrl(String mapUrl) {
        this.mapUrl = mapUrl;
    }

    public Review getReview() {
        return review;
    }

    public void setReview(Review review) {
        this.review = review;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getProfileUrl() {
        return profileUrl;
    }

    public void setProfileUrl(String profileUrl) {
        this.profileUrl = profileUrl;
    }

    public String getSendToFriendUrl() {
        return sendToFriendUrl;
    }

    public void setSendToFriendUrl(String sendToFriendUrl) {
        this.sendToFriendUrl = sendToFriendUrl;
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }

} public class RequestBean {
	private Logger log = Logger.getLogger(getClass());
	protected String publisher;
	protected boolean customerOnly;
	protected String adUnitName;
	protected String adUnitSize;
	protected Integer displaySize;
	protected String clientIP;
	protected String dartClickTrackUrl;
	protected String callBackFunction;
	protected String callBackUrl;
	protected String where;
	protected String what;
	protected String latitude;
	protected String longitude;
	protected String radius;
	protected String listingId;
	protected String tags;
	// Review Specific Params
	protected String tagId;
	protected String tagName;
	protected String rating;
	protected String days;
	protected String max;
	protected String placement;

	// Offer specific Params
	protected String version;
	protected String tag;
	protected String page;
	protected String rpp;
	protected String expiresBefore;
	protected String customerHasbudget;

	public String getTagId() {
		return tagId;
	}

	public void setTagId(String tagId) {
		this.tagId = tagId;
	}

	public String getTagName() {
		return tagName;
	}

	public void setTagName(String tagName) {
		this.tagName = tagName;
	}

	public String getCallBackFunction() {
		return callBackFunction;
	}

	public void setCallBackFunction(String callBackFunction) {
		this.callBackFunction = callBackFunction;
	}

	public String getCallBackUrl() {
		return callBackUrl;
	}

	public void setCallBackUrl(String callBackUrl) {
		this.callBackUrl = callBackUrl;
	}

	public String getDartClickTrackUrl() {
		return dartClickTrackUrl;
	}

	public void setDartClickTrackUrl(String dartClickTrackUrl) {
		this.dartClickTrackUrl = dartClickTrackUrl;
	}

	public String getClientIP() {
		return clientIP;
	}

	public void setClientIP(String clientIP) {
		this.clientIP = clientIP;
	}

	public String getPublisher() {
		return publisher;
	}

	public void setPublisher(String publisher) {
		this.publisher = publisher;
	}

	public boolean isCustomerOnly() {
		return customerOnly;
	}

	public void setCustomerOnly(boolean customerOnly) {
		this.customerOnly = customerOnly;
	}

	public String getAdUnitName() {
		return adUnitName;
	}

	public void setAdUnitName(String adUnitName) {
		this.adUnitName = adUnitName;
	}

	public String getAdUnitSize() {
		return adUnitSize;
	}

	public void setAdUnitSize(String adUnitSize) {
		this.adUnitSize = adUnitSize;
	}

	public Integer getDisplaySize() {
		return displaySize;
	}

	public void setDisplaySize(Integer displaySize) {
		this.displaySize = displaySize;
	}

	public String getWhere() {
		return where;
	}

	public void setWhere(String where) {
		this.where = where;
	}

	public String getWhat() {
		return what;
	}

	public void setWhat(String what) {
		this.what = what;
	}

	public String getLatitude() {
		return latitude;
	}

	public void setLatitude(String latitude) {
		this.latitude = latitude;
	}

	public String getLongitude() {
		return longitude;
	}

	public void setLongitude(String longitude) {
		this.longitude = longitude;
	}

	public String getRadius() {
		return radius;
	}

	public void setRadius(String radius) {
		this.radius = radius;
	}

	public String getListingId() {
		return listingId;
	}

	public void setListingId(String listingId) {
		this.listingId = listingId;
	}

	public String getRating() {
		return rating;
	}

	public void setRating(String rating) {
		this.rating = rating;
	}

	public String getDays() {
		return days;
	}

	public void setDays(String days) {
		this.days = days;
	}

	public String getMax() {
		return max;
	}

	public void setMax(String max) {
		this.max = max;
	}

	public String getPlacement() {
		return placement;
	}

	public void setPlacement(String placement) {
		this.placement = placement;
	}

	public String getVersion() {
		return version;
	}

	public void setVersion(String version) {
		this.version = version;
	}

	public String getTag() {
		return tag;
	}

	public void setTag(String tag) {
		this.tag = tag;
	}

	public String getPage() {
		return page;
	}

	public void setPage(String page) {
		this.page = page;
	}

	public String getRpp() {
		return rpp;
	}

	public void setRpp(String rpp) {
		this.rpp = rpp;
	}

	public String getExpiresBefore() {
		return expiresBefore;
	}

	public void setExpiresBefore(String expiresBefore) {
		this.expiresBefore = expiresBefore;
	}

	public String getCustomerHasbudget() {
		return customerHasbudget;
	}

	public void setCustomerHasbudget(String customerHasbudget) {
		this.customerHasbudget = customerHasbudget;
	}

	public String getTags() {
		return tags;
	}

	public void setTags(String tags) {
		this.tags = tags;
	}

	/**
	 * Method to validate required parameters for a request.
	 * 
	 * @throws CitysearchException
	 *             , InvalidRequestParametersException
	 */
	public void validate() throws InvalidRequestParametersException,
			CitysearchException {
		log.info("Start RequestBean validate()");
		List<String> errors = new ArrayList<String>();

		if (StringUtils.isBlank(getPublisher())) {
			errors.add("Publisher code is required.");
		}

		if (StringUtils.isBlank(getWhat())) {
			errors.add("What is required.");
		}

		if ((StringUtils.isBlank(getLatitude()) || StringUtils
				.isBlank(getLongitude()))
				&& StringUtils.isBlank(getWhere())) {
			errors
					.add("Where is required if latitude & longitude is not provided.");
		}
		if (!StringUtils.isBlank(getLatitude())
				&& StringUtils.isBlank(getLongitude())) {
			errors.add("Invalid longitude.");
		} else if (StringUtils.isBlank(getLatitude())
				&& !StringUtils.isBlank(getLongitude())) {
			errors.add("Invalid latitude.");
		}

		if (StringUtils.isBlank(getClientIP())) {
			errors.add("Client IP is required.");
		}
		if (!errors.isEmpty()) {
			throw new InvalidRequestParametersException(this.getClass()
					.getName(), "RequestBean.validate()",
					"Invalid parameters.", errors);
		}
		log.info("End RequestBean validate()");
	}

	public String getAdUnitIdentifier() {
		StringBuilder str = new StringBuilder();
		str.append(adUnitName);
		str.append(".");
		str.append(adUnitSize);
		return str.toString().toUpperCase();
	}
} public class CitysearchException extends Exception {
    private static final long serialVersionUID = 1L;
    private String className;
    private String methodName;

    public CitysearchException(String className, String methodName) {
        super();
        this.className = className;
        this.methodName = methodName;
    }

    public CitysearchException(String className, String methodName, String message) {
        super(message);
        this.className = className;
        this.methodName = methodName;
    }

    public CitysearchException(String className, String methodName, String message, Throwable cause) {
        super(message, cause);
        this.className = className;
        this.methodName = methodName;
    }

    public CitysearchException(String className, String methodName, Throwable cause) {
        super(cause);
        this.className = className;
        this.methodName = methodName;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public static long getSerialversionuid() {
        return serialVersionUID;
    }
} public class InvalidRequestParametersException extends CitysearchException {
	private List<String> errors;

	public InvalidRequestParametersException(String className,
			String methodName, String message, List<String> errors) {
		super(className, methodName, message);
		this.errors = errors;
	}

	/**
	 * Returns the list of errors
	 * 
	 * @return List
	 */
	public List<String> getErrors() {
		return errors;
	}

	/**
	 * Adds the error message to the error list
	 * 
	 * @param message
	 */
	public void addError(String message) {
		if (errors == null) {
			errors = new ArrayList<String>();
		}
		errors.add(message);
	}

	public void setErrors(List<String> errors) {
		this.errors = errors;
	}

	/**
	 * Returns the detailed message with the classname, methodname and list of
	 * all errors
	 * 
	 * @return String
	 */
	public String getDetailedMessage() {
		StringBuilder strBuilder = new StringBuilder();
		strBuilder.append(getClassName());
		strBuilder.append(".");
		strBuilder.append(getMethodName());
		strBuilder.append("::");
		strBuilder.append(getMessage());
		if (errors != null && !errors.isEmpty()) {
			strBuilder.append('\n');
			Iterator<String> it = errors.iterator();
			while (it.hasNext()) {
				strBuilder.append(it.next());
				strBuilder.append('\n');
			}
		}
		return strBuilder.toString();
	}
} public class ProfileHelper {
	private String contextPath;

	public ProfileHelper(String contextPath) {
		this.contextPath = contextPath;
	}

	private Profile toProfile(LocationProfile location)
			throws CitysearchException {
		Profile profile = new Profile();
		profile.setListingId(location.getListingId());
		profile.setProfileUrl(location.getProfileUrl());
		profile.setSendToFriendUrl(location.getSendToFriendUrl());
		profile.setReviewsUrl(location.getReviewsUrl());
		profile.setWebsiteUrl(location.getWebsiteUrl());
		profile.setMenuUrl(location.getMenuUrl());
		profile.setReservationUrl(location.getReservationUrl());
		profile.setMapUrl(location.getMapUrl());
		profile.setReviewCount(location.getReviewCount());
		profile.setImageUrl(location.getImageUrl());
		profile.setPhone(location.getPhone());

		Address address = new Address();
		address.setStreet(location.getStreet());
		address.setCity(location.getCity());
		address.setState(location.getState());
		address.setPostalCode(location.getPostalCode());
		profile.setAddress(address);
		return profile;
	}

	private Profile toProfileAndLatestReview(RequestBean request,
			LocationProfile location) throws CitysearchException {
		Profile profile = toProfile(location);

		if (location.getReview() != null) {
			ReviewResponse reviewResponse = location.getReview();
			Review review = ReviewHelper.toReview(request, reviewResponse,
					contextPath, request.getAdUnitIdentifier());

			review.setCallBackFunction(request.getCallBackFunction());
			review.setCallBackUrl(request.getCallBackUrl());

			String adDisplayTrackingUrl = Utils.getTrackingUrl(review
					.getReviewUrl(), null, request.getCallBackUrl(), request
					.getDartClickTrackUrl(), profile.getListingId(), profile
					.getPhone(), request.getPublisher(), request
					.getAdUnitName(), request.getAdUnitSize());
			review.setReviewTrackingUrl(adDisplayTrackingUrl);

			String callBackFn = Utils.getCallBackFunctionString(request
					.getCallBackFunction(), profile.getListingId(), profile
					.getPhone());
			review.setCallBackFunction(callBackFn);

			profile.setReview(review);

			if (profile.getSendToFriendUrl() != null) {
				String sendToFriendTrackingUrl = Utils.getTrackingUrl(profile
						.getSendToFriendUrl(), null, request.getCallBackUrl(),
						request.getDartClickTrackUrl(), profile.getListingId(),
						profile.getPhone(), request.getPublisher(), request
								.getAdUnitName(), request.getAdUnitSize());
				profile.setSendToFriendTrackingUrl(sendToFriendTrackingUrl);
			}
		}

		return profile;
	}

	public Profile getProfile(RequestBean request) throws CitysearchException {
		ProfileProxy proxy = new ProfileProxy();
		LocationProfile profileResponse = proxy
				.getProfile(request, contextPath);
		return toProfile(profileResponse);
	}

	public Profile getProfileAndHighestReview(RequestBean request)
			throws CitysearchException {
		ProfileProxy proxy = new ProfileProxy();
		LocationProfile profileResponse = proxy.getProfileAndLatestReview(
				request, contextPath);
		return toProfileAndLatestReview(request, profileResponse);
	}
} public class CommonConstants {
    public static final Integer DEFAULT_NEARBY_DISPLAY_SIZE = 3;

    public static final String WHAT = "what";
    public static final String WHERE = "where";
    public static final String TAGS = "tags";
    public static final String TAG_SEARCH = "tag";
    public static final String PUBLISHER_CODE = "publishercode";
    public static final String LAT_URL = "lat";
    public static final String LON_URL = "lon";
    public static final String RADIUS = "radius";
    public static final String RES_CONTENT_TYPE = "text/html";
    public static final int RES_SUCCESS_CODE = 200;
    public static final String REDIRECT_URL_PARAM = "default.redirect.url";
    public static final String CALL_BACK_FUNCTION_PARAM = "callbackfunction";
    public static final String CALL_BACK_URL = "callbackURL";
    public static final String API_PROP_READ_ERROR = "api.properties";
    public static final String LATITUDE = "latitude";
    public static final String LONGITUDE = "longitude";
    public static final String PFP_WITHOUT_GEOGRAPHY = "pfpWithoutGeography";
    public static final String SEARCH_API_TYPE = "search";
    public static final String PFP_API_TYPE = "pfp";
    public static final String NAME = "name";
    public static final String STREET = "street";
    public static final String CITY = "city";
    public static final String STATE = "state";
    public static final String POSTALCODE = "postalcode";
    public static final String DISTANCE = "distance";
    public static final String SEARCHRESPONSE = "searchResponse";
    public static final String SEARCH_API_QUERIED = "searchAPIQueried";
    public static final String RATING = "rating";
    public static final String REVIEWCOUNT = "reviewCount";
    public static final String LISTING_ID = "listingId";
    public static final String CATEGORY = "category";
    public static final String DLAT = "dLat";
    public static final String DLON = "dLon";
    public static final String PHONENUMBER = "phonenumber";
    public static final String PHONE = "phone";
    public static final String DISPLAY_URL = "displayURL";
    public static final String IMAGE_URL = "imageURL";
    public static final String REVIEW_API_TYPE = "review";
    public static final String OFFERS = "offers";
    
    public final static String API_KEY_PROPERTY = "apikey";

    public final static String SYMBOL_AMPERSAND = "&";

    public static final String IMAGES_PROPERTIES_FILE = "images.properties";
    public static final String IMAGE_ERROR = "image.properties.error";
    
    public static final String DESCRIPTION_LENGTH = "description.length";
    public static final String NAME_LENGTH = "name.length";
    public static final String TAGLINE_LENGTH = "tagline.length";
    public static final String TITLE_LENGTH = "title.length";
    public static final String DISPLAY_URL_LENGTH = "displayurl.length";
    public static final String REVIEW_TITLE_LENGTH = "review.title.length";
    public static final String REVIEW_TEXT_LENGTH = "review.text.length";
    public static final String REVIEW_TEXT_SMALL_LENGTH = "review.text.small.length";
    public static final String REVIEW_PROS_LENGTH = "review.pros.length";
    public static final String REVIEW_CONS_LENGTH = "review.cons.length";
    
    public static final int EXTENDED_RADIUS = 25;
    public static final int DEFAULT_RADIUS = 25;
    public static final String DISTANCE_DISPLAY_CUTOFF = "nearby.distance.display.cutoff";
    
    public static final String MANTLE_AD_SIZE = "300x250";
    public static final String CONQUEST_AD_SIZE = "645x100";
    public static final int MANTLE_DISPLAY_SIZE = 3;
    public static final int CONQUEST_DISPLAY_SIZE = 2;
    
    public static final String AD_UNIT_NAME_NEARBY = "nearby";
    public static final String AD_UNIT_NAME_REVIEW = "review";
    public static final String AD_UNIT_NAME_OFFERS = "offers";
    public static final String AD_UNIT_NAME_DEALS = "deals";
    public static final String PUBLISHER_PROJECT_YELLOW = "yelp";
    public final static String PUBLISHER_CITYSEARCH = "citysearch";
    public final static String PUBLISHER_INSIDERPAGES = "insider_pages";
    public final static String PUBLISHER_URBANSPOON = "urbanspoon";
    public final static String PUBLISHER_CBS = "cbs";
} public class PropertiesLoader {
	private static Logger log = Logger.getLogger(PropertiesLoader.class);
	private static final String API_PROPERTIES_FILE = "/api.properties";
	private static final String ERROR_PROPERTIES_FILE = "/error.properties";
	private static final String APPLICATION_PROPERTIES_FILE = "/application.properties";
	private static final String TRACKING_PROPERTIES_FILE = "/onebyonetracking.properties";
	private static final String FIELD_PROPERTIES_FILE = "/field.properties";
	private static Properties errorProperties;
	private static Properties apiProperties;
	private static Properties applicationProperties;
	private static Properties fieldProperties;
	
	/**
	 * Takes the file name as input and reads the properties from the file.
	 * Returns the Properties object that contains parameters as key,value pairs
	 * 
	 * @param fileName
	 * @return Properties
	 */
	public static Properties getProperties(String fileName)
			throws CitysearchException {
		InputStream inputStream;
		Properties properties;
		inputStream = PropertiesLoader.class.getClassLoader()
				.getResourceAsStream(fileName);
		properties = new Properties();

		// load the inputStream using the Properties
		try {
			if (inputStream != null)
				properties.load(inputStream);
		} catch (IOException ioexcep) {
			throw new CitysearchException("PropertiesLoader", "getProperties",
					ioexcep);
		} finally {
			try {
				inputStream.close();
			} catch (IOException ioexcep) {
				throw new CitysearchException("PropertiesLoader",
						"getProperties", ioexcep);
			}
		}
		return properties;
	}

	/**
	 * Read the error.properties file. If that file is missing, throws
	 * CitysearchException
	 * 
	 * @return Properties
	 * @throws CitysearchException
	 */
	@Deprecated
	public static Properties getErrorProperties() throws CitysearchException {
		if (errorProperties == null) {
			errorProperties = getProperties(ERROR_PROPERTIES_FILE);
		}
		return errorProperties;
	}

	/**
	 * Read the api.properties file. If that file is missing, throws
	 * CitysearchException
	 * 
	 * @return Properties
	 * @throws CitysearchException
	 */
	public static Properties getAPIProperties() throws CitysearchException {
		if (apiProperties == null) {
			apiProperties = getProperties(API_PROPERTIES_FILE);
		}
		return apiProperties;
	}

	public static Properties getApplicationProperties()
			throws CitysearchException {
		if (applicationProperties == null) {
			applicationProperties = getProperties(APPLICATION_PROPERTIES_FILE);
		}
		return applicationProperties;
	}

	public static Properties getTrackingProperties() throws CitysearchException {
		return getProperties(TRACKING_PROPERTIES_FILE);
	}
	
	public static Properties getFieldProperties() throws CitysearchException {
		if (fieldProperties == null) {
			fieldProperties = getProperties(FIELD_PROPERTIES_FILE);
		}
		return fieldProperties;
	}
} public class Utils {
    private static Logger log = Logger.getLogger(Utils.class);
    private static final int TOTAL_RATING = 5;
    private static final int EMPTY_STAR = 0;
    private static final int HALF_STAR = 1;
    private static final int FULL_STAR = 2;
    private static final double KM_TO_MILE = 0.622;
    private static final int RADIUS = 6371;
    private static final String COMMA = ",";
    private static final String SPACE = " ";

    public static String constructQueryParam(String name, String value) throws CitysearchException {
        StringBuilder apiQueryString = new StringBuilder();
        if (StringUtils.isNotBlank(value)) {
            apiQueryString.append(name);
            apiQueryString.append("=");
            try {
                value = URLEncoder.encode(value, "UTF-8");
                apiQueryString.append(value);
            } catch (UnsupportedEncodingException excep) {
                throw new CitysearchException("Utils", "constructQueryParam", excep);
            }
        }
        return apiQueryString.toString();
    }

    public static Document buildFromStream(InputStream input) throws IOException,
            CitysearchException {
        Document document = null;
        try {
            if (input != null) {
                SAXBuilder builder = new SAXBuilder();
                document = builder.build(input);
            }
        } catch (JDOMException jde) {
            throw new CitysearchException("Utils", "buildFromStream", jde);
        } catch (IOException ioe) {
            throw new CitysearchException("Utils", "buildFromStream", ioe);
        } finally {
            input.close();
        }
        return document;
    }

    /**
     * Parses the dateStr to Date object as per the formatter format
     * 
     * @param dateStr
     * @param formatter
     * @return Date
     * @throws CitysearchException
     */
    public static Date parseDate(String dateStr, SimpleDateFormat formatter)
            throws CitysearchException {
        Date date = null;
        try {
            date = formatter.parse(dateStr);
        } catch (ParseException excep) {
            throw new CitysearchException("Utils", "parseDate", excep);
        }
        return date;
    }

    /**
     * Calculate the ratings value and determines the rating stars to be displayed Returns what type
     * of star to be displayed in an array E.g.for 3.5 rating the array will have values {2,2,2,1,0}
     * where 2 represents full star, 1 half star and 0 empty star
     * 
     * @param rating
     * @return
     */
    public static List<Integer> getRatingsList(String rating) {
        List<Integer> ratingList = new ArrayList<Integer>();
        if (StringUtils.isNotBlank(rating)) {
            double ratings = (Double.parseDouble(rating)) / 2;
            int userRating = (int) ratings;
            while (ratingList.size() < userRating) {
                ratingList.add(FULL_STAR);
            }

            if (ratings % 1 != 0)
                ratingList.add(HALF_STAR);

            while (ratingList.size() < TOTAL_RATING) {
                ratingList.add(EMPTY_STAR);
            }

        } else {
            for (int count = 0; count < TOTAL_RATING; count++) {
                ratingList.add(EMPTY_STAR);
            }
        }
        return ratingList;
    }

    /**
     * This method takes the source latitude, longitude and destination latitude, longitude to
     * calculate the distance between two points and returns the distance
     * 
     * @param sourceLat
     * @param sourceLon
     * @param destLat
     * @param destLon
     * @return double
     */
    public static double getDistance(BigDecimal sourceLatitude, BigDecimal sourceLongitude,
            BigDecimal destLatitude, BigDecimal destLongitude) {

        double distance = 0.0;
        double diffOfLat = Math.toRadians(destLatitude.doubleValue() - sourceLatitude.doubleValue());
        double diffOfLon = Math.toRadians(destLongitude.doubleValue()
                - sourceLongitude.doubleValue());
        double sourceLatRad = Math.toRadians(sourceLatitude.doubleValue());
        double destLatRad = Math.toRadians(destLatitude.doubleValue());

        double calcResult = Math.sin(diffOfLat / 2) * Math.sin(diffOfLat / 2)
                + Math.cos(sourceLatRad) * Math.cos(destLatRad) * Math.sin(diffOfLon / 2)
                * Math.sin(diffOfLon / 2);

        calcResult = 2 * Math.atan2(Math.sqrt(calcResult), Math.sqrt(1 - calcResult));
        distance = RADIUS * calcResult;
        // Converting from kms to Miles
        distance = distance * KM_TO_MILE;
        // Rounding to one decimal place
        distance = Math.floor(distance * 10) / 10.0;
        return distance;
    }

    public static double getRatingValue(String rating) {
        double ratings = 0.0;
        if (StringUtils.isNotBlank(rating)) {
            ratings = (Double.parseDouble(rating)) / 2;
            ratings = Math.floor(ratings * 10) / 10.0;
        }
        return ratings;

    }

    public static int toInteger(String stringToConvert) {
        int intValue = 0;
        if (StringUtils.isNotBlank(stringToConvert)) {
            intValue = Integer.parseInt(stringToConvert);
        }
        return intValue;
    }

    public static String getLocationString(String city, String state) {
        StringBuilder location = new StringBuilder();
        if (StringUtils.isNotBlank(city))
            location.append(city.trim());
        if (StringUtils.isNotBlank(state)) {
            if (location.length() > 0) {
                location.append(COMMA);
                location.append(SPACE);
            }
            location.append(state.trim());
        }
        return location.toString();
    }

    public static String getAbbreviatedString(String stringToAbbreviate, String apiPropertyName,
            int defaultLength) throws CitysearchException {
        String value = PropertiesLoader.getAPIProperties().getProperty(apiPropertyName);
        int length = 0;
        if (StringUtils.isNotBlank(value)) {
            length = NumberUtils.toInt(value);
        }
        if (length == 0) {
            length = defaultLength;
        }
        String abbreviatedString = StringUtils.abbreviate(stringToAbbreviate, length);
        return StringUtils.trimToEmpty(abbreviatedString);
    }

    public static String getAbbreviatedString(String stringToAbbreviate, String propertyName)
            throws CitysearchException {
        Properties prop = PropertiesLoader.getFieldProperties();
        if (prop.containsKey(propertyName)) {
            String value = prop.getProperty(propertyName);
            if (StringUtils.isNotBlank(value)) {
                int length = NumberUtils.toInt(value);
                stringToAbbreviate = StringUtils.abbreviate(stringToAbbreviate, length);
            }
        }
        return stringToAbbreviate;
    }

    public static String getTruncatedString(String stringTotruncate, String propertyName)
            throws CitysearchException {
        Properties prop = PropertiesLoader.getFieldProperties();
        if (prop.containsKey(propertyName)) {
            String value = prop.getProperty(propertyName);
            if (StringUtils.isNotBlank(value)) {
                int length = NumberUtils.toInt(value);
                stringTotruncate = StringUtils.substring(stringTotruncate, 0, length);
            }
        }
        return stringTotruncate;
    }

    public static List<String> getImages(String contextPath) throws CitysearchException {
        List<String> imageList = new ArrayList<String>();
        Properties imageProperties = PropertiesLoader.getProperties(CommonConstants.IMAGES_PROPERTIES_FILE);
        Enumeration<Object> enumerator = imageProperties.keys();
        while (enumerator.hasMoreElements()) {
            String key = (String) enumerator.nextElement();
            String value = imageProperties.getProperty(key);
            if (value != null && !value.startsWith("http")) {
                StringBuilder strBuilder = new StringBuilder(contextPath);
                strBuilder.append(value);
                value = strBuilder.toString();
            }
            imageList.add(value);
        }
        return imageList;
    }

    public static String getCallBackFunctionString(String callBackFunction, String listingId,
            String phone) {
        if (callBackFunction != null && callBackFunction.trim().length() > 0) {
            // Should produce javascript:fnName('param1','param2')
            StringBuilder strBuilder = new StringBuilder("javascript:");
            strBuilder.append(callBackFunction);
            strBuilder.append("(\"");
            strBuilder.append(listingId);
            strBuilder.append("\",\"");
            strBuilder.append(phone);
            strBuilder.append("\")");
            return strBuilder.toString();
        }
        return "";
    }

    public static String getTrackingUrl(String adDisplayURL, String adDestinationUrl,
            String callBackUrl, String dartTrackingUrl, String listingId, String phone,
            String publisher, String adUnitName, String adUnitSize) throws CitysearchException {
        String urlToTrack = adDisplayURL;
        // takes care of callBackUrl
        if (callBackUrl != null && callBackUrl.trim().length() > 0) {
            callBackUrl = callBackUrl.replace("$l", listingId);
            callBackUrl = callBackUrl.replace("$p", phone);
            urlToTrack = callBackUrl;
        }
        // adds http:// if it does not specify one
        if (!urlToTrack.startsWith("http://")) {
            StringBuilder strb = new StringBuilder("http://");
            strb.append(urlToTrack);
            urlToTrack = strb.toString();
        }
        try {
            // get prod destination id
            URL url = new URL(urlToTrack);
            String host = url.getHost();
            int prodDetId = 12; // Click outside Citysearch
            if (host.indexOf("citysearch.com") != -1) {
                prodDetId = 16;
            }

            StringBuilder strBuilder = new StringBuilder();
            // dart tracking goes first
            if (dartTrackingUrl != null) {
                strBuilder.append(dartTrackingUrl);
            }

            String destinationUrl = null;
            if (adDestinationUrl != null && adDestinationUrl.trim().length() > 0) {
                // in house click tracker goes next
                StringBuilder destinationUrlBuilder = new StringBuilder();
                destinationUrlBuilder.append(adDestinationUrl);
                destinationUrlBuilder.append("&placement=");
                destinationUrlBuilder.append(publisher + "_" + adUnitName + "_" + adUnitSize);
                if (adDestinationUrl.indexOf("&directUrl=") == -1) {
                    destinationUrlBuilder.append("&directUrl=");
                    destinationUrlBuilder.append(URLEncoder.encode(urlToTrack, "UTF-8"));
                }
                if (prodDetId != 16) {
                    destinationUrl = destinationUrlBuilder.toString().replaceAll("prodDetId=16",
                            "prodDetId=" + prodDetId);
                } else {
                    destinationUrl = destinationUrlBuilder.toString();
                }
            } else {
                destinationUrl = urlToTrack;
            }
            strBuilder.append(destinationUrl);

            return strBuilder.toString();
        } catch (MalformedURLException mue) {
            throw new CitysearchException("Utils", "getTrackingUrl", mue);
        } catch (UnsupportedEncodingException excep) {
            throw new CitysearchException("Utils", "getTrackingUrl", excep);
        }
    }

    public static String getThirdPartyTrackingUrl(String urlToTrack, String dartTrackingUrl,
            String thirdPartyTrackingUrlKey) throws CitysearchException {
        try {
            StringBuilder strBuilder = new StringBuilder();
            // dart tracking goes first
            if (dartTrackingUrl != null) {
                strBuilder.append(dartTrackingUrl);
            }

            Properties apiProperties = PropertiesLoader.getAPIProperties();
            String thirdPartyTrackingUrl = apiProperties.getProperty(thirdPartyTrackingUrlKey);
            if (thirdPartyTrackingUrl != null && thirdPartyTrackingUrl.trim().length() > 0) {
                StringBuilder destinationUrlBuilder = new StringBuilder(thirdPartyTrackingUrl);
                destinationUrlBuilder.append(URLEncoder.encode(urlToTrack, "UTF-8"));
                thirdPartyTrackingUrl = destinationUrlBuilder.toString();
            }
            strBuilder.append(thirdPartyTrackingUrl);
            return strBuilder.toString();
        } catch (UnsupportedEncodingException excep) {
            throw new CitysearchException("Utils", "getTrackingUrl", excep);
        }
    }

    public static String parseRadius(String radiusStr) {
        try {
            Float r = Float.parseFloat(radiusStr);
            int radius = Math.round(r);
            radius = (radius < 1 || radius > CommonConstants.DEFAULT_RADIUS) ? CommonConstants.DEFAULT_RADIUS
                    : radius;
            return String.valueOf(radius);
        } catch (NumberFormatException nfe) {
            log.error("Unable to parse radius to Float: " + radiusStr);
            // DO not throw an exception here.
        }
        return String.valueOf(CommonConstants.DEFAULT_RADIUS);
    }

    /**
     * Parses a plain 3101231234 into (310) 123-1234
     */
    public static String parsePhone(String phoneStr) {
        String areaCode = phoneStr.substring(0, 3);
        String prefix = phoneStr.substring(3, 6);
        String number = phoneStr.substring(6, 10);

        StringBuilder strBuilder = new StringBuilder();
        strBuilder.append('(');
        strBuilder.append(areaCode);
        strBuilder.append(") ");
        strBuilder.append(prefix);
        strBuilder.append('-');
        strBuilder.append(number);

        return strBuilder.toString();
    }
}
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Random;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import com.citysearch.webwidget.api.bean.OfferAPIBean;
import com.citysearch.webwidget.api.proxy.OfferProxy;
import com.citysearch.webwidget.bean.Offer;
import com.citysearch.webwidget.bean.Profile;
import com.citysearch.webwidget.bean.RequestBean;
import com.citysearch.webwidget.exception.CitysearchException;
import com.citysearch.webwidget.exception.InvalidRequestParametersException;
import com.citysearch.webwidget.facade.helper.ProfileHelper;
import com.citysearch.webwidget.util.CommonConstants;
import com.citysearch.webwidget.util.PropertiesLoader;
import com.citysearch.webwidget.util.Utils;
package com.citysearch.webwidget.facade;




public abstract class AbstractOffersFacade {
	private Logger log = Logger.getLogger(getClass());
	private final static String PROPERTY_CITYSEARCH_COUPON_URL = "citysearch.coupon.url";
	protected String contextPath;
	protected int displaySize;

	protected AbstractOffersFacade(String contextPath, int displaySize) {
		this.contextPath = contextPath;
		this.displaySize = displaySize;
	}

	protected List<Offer> addDefaultImages(List<Offer> offers, String path)