protected function _execute($address) {
		/** @var \Geo\Model\Table\GeocodedAddressesTable|null $GeocodedAddresses */
		$GeocodedAddresses = null;
		if ($this->getConfig('cache')) {
			$GeocodedAddresses = TableRegistry::get('Geo.GeocodedAddresses');
			/** @var \Geo\Model\Entity\GeocodedAddress $result */
			$result = $GeocodedAddresses->find()->where(['address' => $address])->first();
			if ($result) {
				/** @var \Geocoder\Model\Address|null $data */
				$data = $result->data;
				return $data ?: null;
			}
		}

		try {
			$addresses = $this->_Geocoder->geocode($address);
		} catch (InconclusiveException $e) {
			$addresses = null;
		} catch (NotAccurateEnoughException $e) {
			$addresses = null;
		}
		$result = null;
		if ($addresses && $addresses->count() > 0) {
			$result = $addresses->first();
		}

		if ($this->getConfig('cache')) {
			/** @var \Geo\Model\Entity\GeocodedAddress $addressEntity */
			$addressEntity = $GeocodedAddresses->newEntity([
				'address' => $address
			]);
			if ($result) {
				$formatter = new StringFormatter();
				$addressEntity->formatted_address = $formatter->format($result, '%S %n, %z %L');
				$addressEntity->lat = $result->getLatitude();
				$addressEntity->lng = $result->getLongitude();
				$addressEntity->country = $result->getCountry()->getCode();
				$addressEntity->data = $result;
			}

			if (!$GeocodedAddresses->save($addressEntity, ['atomic' => false])) {
				throw new RuntimeException('Could not store geocoding cache data');
			}
		}

		return $result;
	}