package com.mindhaq.apiversions.web; import static org.springframework.http.HttpStatus.ACCEPTED; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; import static org.springframework.web.bind.annotation.RequestMethod.GET; import static org.springframework.web.bind.annotation.RequestMethod.POST; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import com.mindhaq.apiversions.domain.Address; import com.mindhaq.apiversions.service.AddressService; @Controller public class AddressController { @Autowired private AddressService addressService; @RequestMapping(value = "/apiurl/v1/address", method = GET, produces = APPLICATION_JSON_VALUE) @ResponseBody public AddressParamV1 getAddressUrlV1() { Address address = addressService.load(); return convertToV1(address); } @RequestMapping(value = "/apiurl/v2/address", method = GET, produces = APPLICATION_JSON_VALUE) @ResponseBody public AddressParamV2 getAddressUrlV2() { Address address = addressService.load(); return convertToV2(address); } @RequestMapping(value = "/apiurl/v1/address", method = POST) @ResponseBody @ResponseStatus(ACCEPTED) public void saveAddressUrlV1(@Valid @ModelAttribute final AddressParamV1 addressParamV1) { Address address = convertFromV1(addressParamV1); addressService.save(address); } @RequestMapping(value = "/apiurl/v2/address", method = POST) @ResponseStatus(ACCEPTED) public void saveAddressUrlV2(@Valid @ModelAttribute final AddressParamV2 addressParamV2) { Address address = convertFromV2(addressParamV2); addressService.save(address); } @RequestMapping( value = "/apiheader/address", method = GET, produces = APPLICATION_JSON_VALUE, headers = "X-API-Version=v1" ) @ResponseBody public AddressParamV1 getAddressHeaderV1() { Address address = addressService.load(); return convertToV1(address); } @RequestMapping( value = "/apiheader/address", method = GET, produces = APPLICATION_JSON_VALUE, headers = "X-API-Version=v2" ) @ResponseBody public AddressParamV2 getAddressHeaderV2() { Address address = addressService.load(); return convertToV2(address); } @RequestMapping(value = "/apiheader/address", method = POST, headers = "X-API-Version=v1") @ResponseStatus(ACCEPTED) public void saveAddressHeaderV1(@ModelAttribute @Valid final AddressParamV1 addressParamV1) { Address address = convertFromV1(addressParamV1); addressService.save(address); } @RequestMapping(value = "/apiheader/address", method = POST, headers = "X-API-Version=v2") @ResponseStatus(ACCEPTED) public void saveAddressHeaderV2(@ModelAttribute @Valid final AddressParamV2 addressParamV2) { Address address = convertFromV2(addressParamV2); addressService.save(address); } @RequestMapping(value = "/apiaccept/address", method = GET, produces = "application/vnd.company.app-v1+json") @ResponseBody public AddressParamV1 getAddressAcceptV1() { Address address = addressService.load(); return convertToV1(address); } @RequestMapping(value = "/apiaccept/address", method = GET, produces = "application/vnd.company.app-v2+json") @ResponseBody public AddressParamV2 getAddressAcceptV2() { Address address = addressService.load(); return convertToV2(address); } @RequestMapping(value = "/apiaccept/address", method = POST, headers = "Accept=application/vnd.company.app-v1+json") @ResponseStatus(ACCEPTED) public void saveAddressAcceptV1(@ModelAttribute @Valid final AddressParamV1 addressParamV1) { Address address = convertFromV1(addressParamV1); addressService.save(address); } @RequestMapping(value = "/apiaccept/address", method = POST, headers = "Accept=application/vnd.company.app-v2+json") @ResponseStatus(ACCEPTED) public void saveAddressAcceptV2(@ModelAttribute @Valid final AddressParamV2 addressParamV2) { Address address = convertFromV2(addressParamV2); addressService.save(address); } private AddressParamV1 convertToV1(final Address address) { AddressParamV1 addressParamV1 = new AddressParamV1(); addressParamV1.setAddress(address.getZip() + ' ' + address.getTown()); return addressParamV1; } private AddressParamV2 convertToV2(final Address address) { AddressParamV2 addressParamV2 = new AddressParamV2(); addressParamV2.setZip(address.getZip()); addressParamV2.setTown(address.getTown()); return addressParamV2; } private Address convertFromV1(final AddressParamV1 addressParamV1) { final String zip, town; Pattern p = Pattern.compile("(\\d{5}) (.*)"); Matcher m = p.matcher(addressParamV1.getAddress()); if (!m.matches()) { throw new IllegalArgumentException("unparsable address " + addressParamV1.getAddress()); } zip = m.group(1); town = m.group(2); return new Address(zip, town); } private Address convertFromV2(final AddressParamV2 addressParamV2) { return new Address(addressParamV2.getZip(), addressParamV2.getTown()); } }