class ShippingDistancePreProcessorImpl implements ShippingQuotePrePostProcessModule {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(ShippingDistancePreProcessorImpl.class);
	
	private final static String BLANK = " ";
	
	private final static String MODULE_CODE = "shippingDistanceModule";

	@Value("${config.shippingDistancePreProcessor.apiKey}")
	private String apiKey;

	@Value("#{'${config.shippingDistancePreProcessor.acceptedZones}'.split(',')}") 
	private List<String> allowedZonesCodes = null;



	public List<String> getAllowedZonesCodes() {
		return allowedZonesCodes;
	}





	public void setAllowedZonesCodes(List<String> allowedZonesCodes) {
		this.allowedZonesCodes = allowedZonesCodes;
	}





	public void prePostProcessShippingQuotes(ShippingQuote quote,
			List<PackageDetails> packages, BigDecimal orderTotal,
			Delivery delivery, ShippingOrigin origin, MerchantStore store,
			IntegrationConfiguration globalShippingConfiguration,
			IntegrationModule currentModule,
			ShippingConfiguration shippingConfiguration,
			List<IntegrationModule> allModules, Locale locale)
			throws IntegrationException {<FILL_FUNCTION_BODY>}




	
	public String getModuleCode() {
		return MODULE_CODE;
	}














}

		
		
		/** which destinations are supported by this module **/
		
		if(delivery.getZone()==null) {
			return;
		}
		
		boolean zoneAllowed = false;
		if(allowedZonesCodes!=null) {
			for(String zoneCode : allowedZonesCodes) {
				if(zoneCode.equals(delivery.getZone().getCode())) {
					zoneAllowed = true;
					break;
				}
			}
		}
		
		if(!zoneAllowed) {
			return;
		}
		
		if(StringUtils.isBlank(delivery.getPostalCode())) {
			return;
		}
		
		Validate.notNull(apiKey, "Requires the configuration of google apiKey");
		
		GeoApiContext context = new GeoApiContext().setApiKey(apiKey);
		
		//build origin address
		StringBuilder originAddress = new StringBuilder();
		
		originAddress.append(origin.getAddress()).append(BLANK)
		.append(origin.getCity()).append(BLANK)
		.append(origin.getPostalCode()).append(BLANK);
		
		if(!StringUtils.isBlank(origin.getState())) {
			originAddress.append(origin.getState()).append(" ");
		}
		if(origin.getZone()!=null) {
			originAddress.append(origin.getZone().getCode()).append(" ");
		}
		originAddress.append(origin.getCountry().getIsoCode());

		
		//build destination address
		StringBuilder destinationAddress = new StringBuilder();
		
		destinationAddress.append(delivery.getAddress()).append(BLANK);
		if(!StringUtils.isBlank(delivery.getCity())) {
			destinationAddress.append(delivery.getCity()).append(BLANK);
		}
		destinationAddress.append(delivery.getPostalCode()).append(BLANK);
		
		if(!StringUtils.isBlank(delivery.getState())) {
			destinationAddress.append(delivery.getState()).append(" ");
		}
		if(delivery.getZone()!=null) {
			destinationAddress.append(delivery.getZone().getCode()).append(" ");
		}
		destinationAddress.append(delivery.getCountry().getIsoCode());
		
		
		try {
			GeocodingResult[] originAdressResult =  GeocodingApi.geocode(context,
					originAddress.toString()).await();

			GeocodingResult[] destinationAdressResult =  GeocodingApi.geocode(context,
					destinationAddress.toString()).await();

			if(originAdressResult.length>0 && destinationAdressResult.length>0) {
				LatLng originLatLng = originAdressResult[0].geometry.location;
				LatLng destinationLatLng = destinationAdressResult[0].geometry.location;
				
				delivery.setLatitude(String.valueOf(destinationLatLng.lat));
				delivery.setLongitude(String.valueOf(destinationLatLng.lng));
				
				//keep latlng for further usage in order to display the map
	
				
				DistanceMatrix  distanceRequest = DistanceMatrixApi.newRequest(context)
		 		.origins(new LatLng(originLatLng.lat, originLatLng.lng))
		 		
		 		.destinations(new LatLng(destinationLatLng.lat, destinationLatLng.lng))
		 				.awaitIgnoreError();
				
				
				if(distanceRequest!=null) {
					DistanceMatrixRow distanceMax = distanceRequest.rows[0];
					Distance distance = distanceMax.elements[0].distance;
					quote.getQuoteInformations().put(Constants.DISTANCE_KEY, 0.001 * distance.inMeters);
				} else {
				  LOGGER.error("Expected distance inner google api to return DistanceMatrix, it returned null. API key might not be working for this request");
				}

			}
		
		} catch (Exception e) {
			LOGGER.error("Exception while calculating the shipping distance",e);
		}

	
<no_super_class>