diff --git a/src/itest/java/com/sybit/airtable/TableDestroyTest.java b/src/itest/java/com/sybit/airtable/TableDestroyTest.java index 682d8c8..1db400c 100644 --- a/src/itest/java/com/sybit/airtable/TableDestroyTest.java +++ b/src/itest/java/com/sybit/airtable/TableDestroyTest.java @@ -10,9 +10,10 @@ import com.sybit.airtable.exception.AirtableException; import com.sybit.airtable.movies.Actor; import com.sybit.airtable.mock.WireMockBaseTest; -import java.util.List; import org.apache.http.client.HttpResponseException; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import org.junit.Ignore; import org.junit.Test; /** @@ -20,26 +21,43 @@ * @author fzr */ public class TableDestroyTest extends WireMockBaseTest { - - - + @Test - public void testDestroyMovie() throws AirtableException, HttpResponseException{ - + public void testDestroyMovie() throws AirtableException, HttpResponseException { + Base base = airtable.base("appe9941ff07fffcc"); Table actorTable = base.table("Actors", Actor.class); - - actorTable.destroy("recapJ3Js8AEwt0Bf"); - + + boolean destroyed = actorTable.destroy("recapJ3Js8AEwt0Bf"); + assertTrue(destroyed); + } + + /** + * No Condition found under which Airtable returns false for deleting an Object. Either it doesent find it, which results in a 404 HTTP Exception + * Or something else is wrong with the Syntax, which results in another Exception. + * Therefore this test is Ignored as long as we dont have an Example of a failed delete from Airtable. + * @throws AirtableException + */ - @Test (expected = AirtableException.class) - public void testDestroyMovieException() throws AirtableException{ - + @Ignore + @Test + public void testDestroyMovieFailure() throws AirtableException { + Base base = airtable.base("appe9941ff07fffcc"); Table actorTable = base.table("Actors", Actor.class); - - actorTable.destroy("not succesfull"); + + boolean destroyed = actorTable.destroy("failed"); + assertFalse(destroyed); } - + + @Test(expected = AirtableException.class) + public void testDestroyMovieException() throws AirtableException { + + Base base = airtable.base("appe9941ff07fffcc"); + Table actorTable = base.table("Actors", Actor.class); + + boolean destroyed = actorTable.destroy("not succesfull"); + } + } diff --git a/src/itest/resources/__files/body-ActorDeleteFailed.json b/src/itest/resources/__files/body-ActorDeleteFailed.json new file mode 100644 index 0000000..69e2833 --- /dev/null +++ b/src/itest/resources/__files/body-ActorDeleteFailed.json @@ -0,0 +1,4 @@ +{ + "deleted": false, + "id": "recapJ3Js8AEwt0BfF" +} \ No newline at end of file diff --git a/src/itest/resources/__files/body-ActorDelete.json b/src/itest/resources/__files/body-ActorDeleteSucess.json similarity index 100% rename from src/itest/resources/__files/body-ActorDelete.json rename to src/itest/resources/__files/body-ActorDeleteSucess.json diff --git a/src/itest/resources/mappings/mapping-ActorDeleteFailed.json b/src/itest/resources/mappings/mapping-ActorDeleteFailed.json new file mode 100644 index 0000000..ec12656 --- /dev/null +++ b/src/itest/resources/mappings/mapping-ActorDeleteFailed.json @@ -0,0 +1,10 @@ +{ + "request" : { + "url" : "/v0/appe9941ff07fffcc/Actors/failed", + "method" : "DELETE" + }, + "response" : { + "status" : 200, + "bodyFileName" : "/body-ActorDeleteFailed.json" + } +} \ No newline at end of file diff --git a/src/itest/resources/mappings/mapping-ActorDelete.json b/src/itest/resources/mappings/mapping-ActorDeleteSucces.json similarity index 74% rename from src/itest/resources/mappings/mapping-ActorDelete.json rename to src/itest/resources/mappings/mapping-ActorDeleteSucces.json index 0ce8f0e..7417ae7 100644 --- a/src/itest/resources/mappings/mapping-ActorDelete.json +++ b/src/itest/resources/mappings/mapping-ActorDeleteSucces.json @@ -5,6 +5,6 @@ }, "response" : { "status" : 200, - "bodyFileName" : "/body-ActorDelete.json" + "bodyFileName" : "/body-ActorDeleteSucess.json" } } \ No newline at end of file diff --git a/src/main/java/com/sybit/airtable/Table.java b/src/main/java/com/sybit/airtable/Table.java index c5409a5..66206cc 100644 --- a/src/main/java/com/sybit/airtable/Table.java +++ b/src/main/java/com/sybit/airtable/Table.java @@ -34,10 +34,10 @@ */ public class Table { - private static final Logger LOG = LoggerFactory.getLogger( Table.class ); + private static final Logger LOG = LoggerFactory.getLogger(Table.class); private final String name; - private final Class type; + private final Class type; private Base parent; @@ -61,7 +61,7 @@ public Table(String name, Class type) { * @param base */ @SuppressWarnings("WeakerAccess") - public Table(String name, Class type, Base base){ + public Table(String name, Class type, Base base) { this(name, type); setParent(base); } @@ -129,29 +129,29 @@ public List select(Query query) throws AirtableException { GetRequest request = Unirest.get(getTableEndpointUrl()) .header("accept", "application/json") .header("Authorization", getBearerToken()); - if(query.getFields() != null && query.getFields().length > 0){ + if (query.getFields() != null && query.getFields().length > 0) { String[] fields = query.getFields(); for (int i = 0; i < fields.length; i++) { - request.queryString("fields[]",fields[i]); - } + request.queryString("fields[]", fields[i]); + } } - if(query.getMaxRecords() != null) { + if (query.getMaxRecords() != null) { request.queryString("maxRecords", query.getMaxRecords()); } - if(query.getView() != null) { + if (query.getView() != null) { request.queryString("view", query.getView()); } - if(query.filterByFormula() != null) { + if (query.filterByFormula() != null) { request.queryString("filterByFormula", query.filterByFormula()); } - if(query.getPageSize() != null){ + if (query.getPageSize() != null) { if (query.getPageSize() > 100) { - request.queryString("pageSize",100); + request.queryString("pageSize", 100); } else { - request.queryString("pageSize",query.getPageSize()); - } + request.queryString("pageSize", query.getPageSize()); + } } - if(query.getSort() != null) { + if (query.getSort() != null) { int i = 0; for (Sort sort : query.getSort()) { request.queryString("sort[" + i + "][field]", sort.getField()); @@ -162,14 +162,13 @@ public List select(Query query) throws AirtableException { LOG.debug("URL=" + request.getUrl()); response = request.asObject(Records.class); - } - catch (UnirestException e) { + } catch (UnirestException e) { throw new AirtableException(e); } int code = response.getStatus(); List list = null; - if(200 == code) { + if (200 == code) { list = getList(response); } else { HttpResponseExceptionHandler.onResponse(response); @@ -180,11 +179,11 @@ public List select(Query query) throws AirtableException { /** * select with Parameter maxRecords - * + * * @param maxRecords * @return * @throws AirtableException - * @throws HttpResponseException + * @throws HttpResponseException */ public List select(Integer maxRecords) throws AirtableException, HttpResponseException { return select(new Query() { @@ -222,12 +221,13 @@ public Integer getPageSize() { /** * Select data of table by definied view. + * * @param view * @return * @throws AirtableException * @throws HttpResponseException */ - public List select(String view) throws AirtableException, HttpResponseException { + public List select(String view) throws AirtableException, HttpResponseException { return select(new Query() { @Override public Integer getMaxRecords() { @@ -262,8 +262,8 @@ public Integer getPageSize() { } /** - *select Table data with defined sortation - * + * select Table data with defined sortation + * * @param sortation * @return * @throws AirtableException @@ -305,14 +305,14 @@ public Integer getPageSize() { } }); } - + /** * Select only Table data with defined fields. * * @param fields array of requested fields. * @return list of item using only requested fields. * @throws AirtableException - * @throws HttpResponseException + * @throws HttpResponseException */ public List select(String[] fields) throws AirtableException, HttpResponseException { @@ -360,7 +360,7 @@ private List getList(HttpResponse response) { final Records records = response.getBody(); final List list = new ArrayList<>(); - for(Map record : records.getRecords()) { + for (Map record : records.getRecords()) { T item = null; try { item = transform(record, this.type.newInstance()); @@ -385,16 +385,16 @@ public T find(String id) throws AirtableException { HttpResponse response; try { - response = Unirest.get( getTableEndpointUrl() + "/" + id) - .header("accept", "application/json") - .header("Authorization", getBearerToken()) - .asObject(RecordItem.class); + response = Unirest.get(getTableEndpointUrl() + "/" + id) + .header("accept", "application/json") + .header("Authorization", getBearerToken()) + .asObject(RecordItem.class); } catch (UnirestException e) { throw new AirtableException(e); } int code = response.getStatus(); - if(200 == code) { + if (200 == code) { body = response.getBody(); } else { HttpResponseExceptionHandler.onResponse(response); @@ -402,95 +402,95 @@ public T find(String id) throws AirtableException { } try { - return transform(body, this.type.newInstance() ); + return transform(body, this.type.newInstance()); } catch (InvocationTargetException | IllegalAccessException | InstantiationException e) { throw new AirtableException(e); } } - + /** * Create Record of given Item - * + * * @param item the item to be created * @return the created item * @throws AirtableException * @throws IllegalAccessException * @throws InvocationTargetException - * @throws NoSuchMethodException + * @throws NoSuchMethodException */ public T create(T item) throws AirtableException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { - + RecordItem responseBody = null; - + checkProperties(item); - + PostRecord body = new PostRecord(); body.setFields(item); - + HttpResponse response; try { - response = Unirest.post( getTableEndpointUrl()) - .header("accept", "application/json") - .header("Authorization", getBearerToken()) - .header("Content-type","application/json") - .body(body) - .asObject(RecordItem.class); + response = Unirest.post(getTableEndpointUrl()) + .header("accept", "application/json") + .header("Authorization", getBearerToken()) + .header("Content-type", "application/json") + .body(body) + .asObject(RecordItem.class); } catch (UnirestException e) { throw new AirtableException(e); } - + int code = response.getStatus(); - if(200 == code) { + if (200 == code) { responseBody = response.getBody(); } else { HttpResponseExceptionHandler.onResponse(response); } try { - return transform(responseBody, this.type.newInstance() ); + return transform(responseBody, this.type.newInstance()); } catch (InvocationTargetException | IllegalAccessException | InstantiationException e) { LOG.error(e.getMessage(), e); } - + return null; } public T update(T item) throws AirtableException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { - + RecordItem responseBody = null; - + String id = getIdOfItem(item); - + PostRecord body = new PostRecord(); body.setFields(filterFields(item)); - + HttpResponse response; try { - response = Unirest.patch( getTableEndpointUrl()+"/"+id) - .header("accept", "application/json") - .header("Authorization", getBearerToken()) - .header("Content-type","application/json") - .body(body) - .asObject(RecordItem.class); + response = Unirest.patch(getTableEndpointUrl() + "/" + id) + .header("accept", "application/json") + .header("Authorization", getBearerToken()) + .header("Content-type", "application/json") + .body(body) + .asObject(RecordItem.class); } catch (UnirestException e) { throw new AirtableException(e); } - + int code = response.getStatus(); - if(200 == code) { + if (200 == code) { responseBody = response.getBody(); } else { HttpResponseExceptionHandler.onResponse(response); } try { - return transform(responseBody, this.type.newInstance() ); + return transform(responseBody, this.type.newInstance()); } catch (InvocationTargetException | IllegalAccessException | InstantiationException e) { LOG.error(e.getMessage(), e); } - + return null; } @@ -499,38 +499,39 @@ public T replace(T item) { throw new UnsupportedOperationException("not yet implemented"); } - + /** * Delete Record by given id - * + * * @param id - * @throws AirtableException + * @throws AirtableException */ + public boolean destroy(String id) throws AirtableException { - public void destroy(String id) throws AirtableException { - Delete body = null; HttpResponse response; try { response = Unirest.delete(getTableEndpointUrl() + "/" + id) - .header("accept", "application/json") - .header("Authorization", getBearerToken()) - .asObject(Delete.class); + .header("accept", "application/json") + .header("Authorization", getBearerToken()) + .asObject(Delete.class); } catch (UnirestException e) { throw new AirtableException(e); } int code = response.getStatus(); - if(200 == code) { + if (200 == code) { body = response.getBody(); } else { HttpResponseExceptionHandler.onResponse(response); } - if(!body.isDeleted()){ - throw new AirtableException("Record id: "+body.getId()+" could not be deleted."); - } +// if (!body.isDeleted()) { +// throw new AirtableException("Record id: " + body.getId() + " could not be deleted."); +// } + + return body.isDeleted(); } /** @@ -569,10 +570,10 @@ private String getBearerToken() { * @throws InstantiationException */ private T transform(Map record, T retval) throws InvocationTargetException, IllegalAccessException { - for(String key: record.keySet()) { - if("fields".equals(key)) { + for (String key : record.keySet()) { + if ("fields".equals(key)) { //noinspection unchecked - retval = transform((Map)record.get("fields"), retval); + retval = transform((Map) record.get("fields"), retval); } else { setProperty(retval, key, record.get(key)); } @@ -609,18 +610,18 @@ private T transform(RecordItem record, T retval) throws InvocationTargetExceptio private void setProperty(T retval, String key, Object value) throws IllegalAccessException, InvocationTargetException { String property = key2property(key); - for (Field f: this.type.getDeclaredFields()) { + for (Field f : this.type.getDeclaredFields()) { final SerializedName annotation = f.getAnnotation(SerializedName.class); - if(annotation != null && property.equalsIgnoreCase(annotation.value())){ - property = f.getName(); - break; + if (annotation != null && property.equalsIgnoreCase(annotation.value())) { + property = f.getName(); + break; } } if (propertyExists(retval, property)) { BeanUtils.setProperty(retval, property, value); - }else { + } else { LOG.warn(retval.getClass() + " does not support public setter for existing property [" + property + "]"); } } @@ -632,13 +633,13 @@ private void setProperty(T retval, String key, Object value) throws IllegalAcces * @return */ private String key2property(String key) { - - if(key.contains(" ") || key.contains("-") ) { - LOG.warn( "Annotate columns having special characters by using @SerializedName for property: [" + key + "]"); + + if (key.contains(" ") || key.contains("-")) { + LOG.warn("Annotate columns having special characters by using @SerializedName for property: [" + key + "]"); } String property = key.trim(); - property = property.substring(0,1).toLowerCase() + property.substring(1, property.length()); - + property = property.substring(0, 1).toLowerCase() + property.substring(1, property.length()); + return property; } @@ -649,104 +650,104 @@ private String key2property(String key) { * @param property name of property * @return true if writable property exists. */ - private static boolean propertyExists (Object bean, String property) { - return PropertyUtils.isReadable(bean, property) && - PropertyUtils.isWriteable(bean, property); + private static boolean propertyExists(Object bean, String property) { + return PropertyUtils.isReadable(bean, property) + && PropertyUtils.isWriteable(bean, property); } /** * Checks if the Property Values of the item are valid for the Request. - * + * * @param item * @throws AirtableException * @throws IllegalAccessException * @throws InvocationTargetException - * @throws NoSuchMethodException + * @throws NoSuchMethodException */ private void checkProperties(T item) throws AirtableException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { - - if(propertyExists(item,"id") || propertyExists(item,"createdTime")){ + + if (propertyExists(item, "id") || propertyExists(item, "createdTime")) { Field[] attributes = item.getClass().getDeclaredFields(); for (Field attribute : attributes) { String name = attribute.getName(); if (name.equals("id") || name.equals("createdTime")) { - if(BeanUtils.getProperty(item,attribute.getName()) != null){ - throw new AirtableException("Property "+name+" should be null!"); - } - } else if (name.equals("photos")){ + if (BeanUtils.getProperty(item, attribute.getName()) != null) { + throw new AirtableException("Property " + name + " should be null!"); + } + } else if (name.equals("photos")) { List obj = (List) BeanUtilsBean.getInstance().getPropertyUtils().getProperty(item, "photos"); checkPropertiesOfAttachement(obj); - } + } } } - + } - - private void checkPropertiesOfAttachement(List attachements) throws AirtableException, IllegalAccessException, InvocationTargetException, NoSuchMethodException{ - - if(attachements != null){ + + private void checkPropertiesOfAttachement(List attachements) throws AirtableException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { + + if (attachements != null) { for (int i = 0; i < attachements.size(); i++) { - if(propertyExists(attachements.get(i),"id") || propertyExists(attachements.get(i),"size") || propertyExists(attachements.get(i), "type") || propertyExists(attachements.get(i), "filename")){ + if (propertyExists(attachements.get(i), "id") || propertyExists(attachements.get(i), "size") || propertyExists(attachements.get(i), "type") || propertyExists(attachements.get(i), "filename")) { Field[] attributesPhotos = attachements.getClass().getDeclaredFields(); for (Field attributePhoto : attributesPhotos) { String namePhotoAttribute = attributePhoto.getName(); - if (namePhotoAttribute.equals("id") || namePhotoAttribute.equals("size") || namePhotoAttribute.equals("Tpye") || namePhotoAttribute.equals("filename")) { - if(BeanUtils.getProperty(attachements.get(i),namePhotoAttribute) != null){ - throw new AirtableException("Property "+namePhotoAttribute+" should be null!"); - } + if (namePhotoAttribute.equals("id") || namePhotoAttribute.equals("size") || namePhotoAttribute.equals("Tpye") || namePhotoAttribute.equals("filename")) { + if (BeanUtils.getProperty(attachements.get(i), namePhotoAttribute) != null) { + throw new AirtableException("Property " + namePhotoAttribute + " should be null!"); + } } } } - } - } + } + } } - + /** - * + * * Get the String Id from the item. - * + * * @param item * @return * @throws AirtableException * @throws IllegalAccessException * @throws InvocationTargetException - * @throws NoSuchMethodException + * @throws NoSuchMethodException */ - private String getIdOfItem(T item) throws AirtableException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { - - if(propertyExists(item,"id")){ + + if (propertyExists(item, "id")) { String id = BeanUtils.getProperty(item, "id"); - if(id != null){ + if (id != null) { return id; - } + } } - throw new AirtableException("Id of "+item+" not Found!"); + throw new AirtableException("Id of " + item + " not Found!"); } /** - * - * Filter the Fields of the PostRecord Object. Id and created Time are set to null so Object Mapper doesent convert them to JSON. - * + * + * Filter the Fields of the PostRecord Object. Id and created Time are set + * to null so Object Mapper doesent convert them to JSON. + * * @param item * @return * @throws IllegalAccessException * @throws InvocationTargetException - * @throws NoSuchMethodException + * @throws NoSuchMethodException */ private T filterFields(T item) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { - + System.out.println(item); - + Field[] attributes = item.getClass().getDeclaredFields(); - + for (Field attribute : attributes) { String name = attribute.getName(); - if ((name.equals("id") || name.equals("createdTime")) && (BeanUtils.getProperty(item,name) != null)) { - BeanUtilsBean.getInstance().getPropertyUtils().setProperty(item, name, null); + if ((name.equals("id") || name.equals("createdTime")) && (BeanUtils.getProperty(item, name) != null)) { + BeanUtilsBean.getInstance().getPropertyUtils().setProperty(item, name, null); } } - + return item; } }