diff --git a/pom.xml b/pom.xml index 01e0494..cb6d153 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ BookingBug-SDK BookingBug-SDK - 1.4 + 1.8 @@ -74,6 +74,12 @@ 1.1 + + io.reactivex + rxjava + 1.1.0 + + diff --git a/src/main/bookingbugAPI/api/AdminURLS.java b/src/main/bookingbugAPI/api/AdminURLS.java index e4ba96e..21141c0 100644 --- a/src/main/bookingbugAPI/api/AdminURLS.java +++ b/src/main/bookingbugAPI/api/AdminURLS.java @@ -11,6 +11,7 @@ public static class Company { public static UriTemplate company() { return UriTemplate.buildFromTemplate(new Config().serverUrl) .literal("/admin") + .path(UriTemplateBuilder.var("companyId")) .literal("/company") .build(); } @@ -85,6 +86,7 @@ public static UriTemplate serviceList(){ .literal("/admin") .path(UriTemplateBuilder.var("companyId")) .literal("/services") + .query(UriTemplateBuilder.var("page"), UriTemplateBuilder.var("per_page")) .build(); } @@ -96,6 +98,16 @@ public static UriTemplate serviceRead() { .path(UriTemplateBuilder.var("serviceId")) .build(); } + + public static UriTemplate serviceNewBooking() { + return UriTemplate.buildFromTemplate(new Config().serverUrl) + .literal("/admin") + .path(UriTemplateBuilder.var("companyId")) + .literal("/services") + .path(UriTemplateBuilder.var("serviceId")) + .literal("/new_booking") + .build(); + } } @@ -269,6 +281,7 @@ public static UriTemplate bookingList(){ .literal("/admin") .path(UriTemplateBuilder.var("companyId")) .literal("/bookings") + .query(UriTemplateBuilder.var("page"), UriTemplateBuilder.var("per_page")) .build(); } @@ -625,6 +638,16 @@ public static UriTemplate eventChainReadUsingRefId() { .path(UriTemplateBuilder.var("refId")) .build(); } + + public static UriTemplate eventChainEventsList() { + return UriTemplate.buildFromTemplate(new Config().serverUrl) + .literal("/admin") + .path(UriTemplateBuilder.var("companyId")) + .literal("/event_chains") + .path(UriTemplateBuilder.var("eventChainId")) + .literal("/events") + .build(); + } } diff --git a/src/main/bookingbugAPI/api/PublicURLS.java b/src/main/bookingbugAPI/api/PublicURLS.java index acfae19..1be7644 100644 --- a/src/main/bookingbugAPI/api/PublicURLS.java +++ b/src/main/bookingbugAPI/api/PublicURLS.java @@ -67,7 +67,9 @@ public static class Service { */ public static UriTemplate serviceList(){ return UriTemplate.buildFromTemplate(new Config().serverUrl).path(UriTemplateBuilder.var("companyId")) - .literal("/" + servicesLink).build(); + .literal("/" + servicesLink) + .query(UriTemplateBuilder.var("page"), UriTemplateBuilder.var("per_page")) + .build(); } /** @@ -179,8 +181,13 @@ public static class Event { * @return UriTemplate */ public static UriTemplate eventList(){ - return UriTemplate.buildFromTemplate(new Config().serverUrl).path(UriTemplateBuilder.var("companyId")) - .literal("/" + eventsLink).build(); + return UriTemplate.buildFromTemplate(new Config().serverUrl) + .path(UriTemplateBuilder.var("companyId")) + .literal("/" + eventsLink) + .query("page", "per_page", "event_chain_id", + "start_date", "end_date", "resource_id", "person_id", + "event_group_id", "summary", "member_level_id") + .build(); } /** @@ -244,7 +251,9 @@ public static UriTemplate availabilityDaysForBookableItem() { */ public static UriTemplate availabilityTimesForBookableItem() { return UriTemplate.buildFromTemplate(new Config().serverUrl).path(UriTemplateBuilder.var("companyId")) - .literal("/time_data").build(); + .literal("/time_data") + .query("event_id", "service_id", "resource_id","resource_ids", "person_id", "group_id", "location", + "date", "end_date", "duration", "num_resources").build(); } /** @@ -314,7 +323,9 @@ public static class EventChain { */ public static UriTemplate eventChainList(){ return UriTemplate.buildFromTemplate(new Config().serverUrl).path(UriTemplateBuilder.var("companyId")) - .literal("/" + eventChainsLink).build(); + .literal("/" + eventChainsLink) + .query(UriTemplateBuilder.var("page"), UriTemplateBuilder.var("per_page")) + .build(); } /** diff --git a/src/main/bookingbugAPI/models/BBRoot.java b/src/main/bookingbugAPI/models/BBRoot.java index ac369ea..8cbca12 100644 --- a/src/main/bookingbugAPI/models/BBRoot.java +++ b/src/main/bookingbugAPI/models/BBRoot.java @@ -3,6 +3,9 @@ import bookingbugAPI.services.HttpService; import com.damnhandy.uri.template.UriTemplate; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; import com.theoryinpractise.halbuilder.api.ContentRepresentation; import com.theoryinpractise.halbuilder.api.Link; import com.theoryinpractise.halbuilder.api.RepresentationException; @@ -107,6 +110,18 @@ public String get(String key){ return val; } + public boolean getBoolean(String key, boolean defaultValue) { + String val = this.get(key); + if(val != null) return Boolean.parseBoolean(val); + return defaultValue; + } + + public int getInteger(String key, int defaultValue) { + String val = this.get(key); + if(val != null) return Integer.parseInt(val); + return defaultValue; + } + public String getAuth_token() { return auth_token; @@ -138,6 +153,16 @@ public String toString() { return response.getRep().getContent(); } + public String toPrettyString() { + ObjectMapper mapper = new ObjectMapper(); + try { + return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(response.getRep()); + } catch (JsonProcessingException e) { + e.printStackTrace(); + return toString(); + } + } + public String getCurl() { curl = "curl \"" + getSelf() + "\" " + response.getParamsStr() + " -X " + response.getMethod(); diff --git a/src/main/bookingbugAPI/models/BookableAvailability.java b/src/main/bookingbugAPI/models/BookableAvailability.java index 0a42f4a..7879c42 100644 --- a/src/main/bookingbugAPI/models/BookableAvailability.java +++ b/src/main/bookingbugAPI/models/BookableAvailability.java @@ -50,20 +50,36 @@ public Date getDateTimeObj(){ return datetime; } - public boolean isAvailable(Date datetime){ - Calendar calendar = Calendar.getInstance(); - calendar.setTime(datetime); - int hour_to_check = calendar.get(Calendar.HOUR_OF_DAY); - - ArrayList times = new ArrayList<>(getRep().getResourcesByRel("times")); - for (ReadableRepresentation rep : times) { - int time_min = Integer.parseInt((String) rep.getValue("time")); - int avail = Integer.parseInt((String) rep.getValue("avail")); - - int hour = time_min / 60; - if(hour_to_check >= hour && hour_to_check < hour + 1 && avail == 1) - return true; + public ArrayList getAvailTimes(){ + + ArrayList times_reps = new ArrayList<>(getRep().getResourcesByRel("times")); + ArrayList times = new ArrayList<>(); + + for (ReadableRepresentation rep : times_reps) { + AvailTime timeObj = new AvailTime(); + timeObj.time_minutes = Integer.parseInt((String) rep.getValue("time")); + timeObj.avail = Integer.parseInt((String) rep.getValue("avail")) == 1 ? true : false; + timeObj.price = Integer.parseInt((String) rep.getValue("price")); + times.add(timeObj); + } + return times; + } + + public static class AvailTime { + int time_minutes; + boolean avail; + int price; + + public int getTime_minutes() { + return time_minutes; + } + + public boolean isAvail() { + return avail; + } + + public int getPrice() { + return price; } - return false; } } diff --git a/src/main/bookingbugAPI/models/Company.java b/src/main/bookingbugAPI/models/Company.java index 8c36265..8427f25 100644 --- a/src/main/bookingbugAPI/models/Company.java +++ b/src/main/bookingbugAPI/models/Company.java @@ -124,8 +124,10 @@ public Service serviceEdit_Admin(String serviceId) throws IOException { * @throws IOException */ public BBCollection serviceList_Admin(ServiceListParams slParams) throws IOException { - String urlStr = AdminURLS.Service.serviceList().set("companyId", this.id).expand(); - URL url = new URL(Utils.inflateLink(urlStr, slParams.getParams())); + UriTemplate template = Utils.TemplateWithPagination( + AdminURLS.Service.serviceList().set("companyId", this.id), + slParams); + URL url = new URL(template.expand()); BBCollection services = new BBCollection(HttpService.api_GET(url, auth_token), auth_token, "services", Service.class); return services; } @@ -322,9 +324,21 @@ public Resource companyDetails(String companyId) throws IOException { * @throws IOException */ public BBCollection eventList() throws IOException { - URL url = new URL(PublicURLS.Event.eventList().set("companyId", this.id).expand()); - BBCollection events = new BBCollection(HttpService.api_GET(url, auth_token), auth_token, "events", Event.class); - return events; + return eventList(new Params()); + } + + /** + * Get a List of Bookable Events. + * @param params Parameters for pagination + * @return BBCollection + * @throws IOException + */ + public BBCollection eventList(Params params) throws IOException { + UriTemplate template = Utils.TemplateWithPagination( + PublicURLS.Event.eventList().set("companyId", this.id), + params); + URL url = new URL(template.expand()); + return new BBCollection(HttpService.api_GET(url, auth_token), auth_token, "events", Event.class); } @@ -369,9 +383,13 @@ public BBCollection bookableItemsByDate(String date) throws IOExce * @return Resource * @throws IOException */ - public BBCollection availabilityDaysForBookableItem() throws IOException { - URL url = new URL(PublicURLS.Bookable.availabilityDaysForBookableItem().set("companyId", this.id).expand()); - return new BBCollection(HttpService.api_GET(url, auth_token), auth_token, "events", BookableAvailability.class); + public BBRoot availabilityDaysForBookableItem(TimeDataParams params) throws IOException { + URL url = new URL( + PublicURLS.Bookable.availabilityDaysForBookableItem() + .set("companyId", this.id) + .set((Map)params.getParams()) + .expand()); + return new BBRoot(HttpService.api_GET(url, auth_token), auth_token); } @@ -380,9 +398,13 @@ public BBCollection availabilityDaysForBookableItem() thro * @return Resource * @throws IOException */ - public Resource availabilityTimesForBookableItem() throws IOException { - URL url = new URL(PublicURLS.Bookable.availabilityTimesForBookableItem().set("companyId", this.id).expand()); - return new Resource(HttpService.api_GET(url, auth_token), auth_token); + public BBCollection availabilityTimesForBookableItem(TimeDataParams params) throws IOException { + URL url = new URL( + PublicURLS.Bookable.availabilityTimesForBookableItem() + .set("companyId", this.id) + .set((Map)params.getParams()) + .expand()); + return new BBCollection(HttpService.api_GET(url, auth_token), auth_token, "events", BookableAvailability.class); } @@ -439,7 +461,20 @@ public EventGroup eventGroupRead(String eventGroupId) throws IOException { * @throws IOException */ public BBCollection eventChainList() throws IOException { - URL url = new URL (PublicURLS.EventChain.eventChainList().set("companyId", this.id).expand()); + return eventChainList(new Params()); + } + + /** + * Get a List of Courses or Repeating Events for a Company. + * @param params Parameters for pagination + * @return BBCollection + * @throws IOException + */ + public BBCollection eventChainList(Params params) throws IOException { + UriTemplate template = Utils.TemplateWithPagination( + AdminURLS.EventChain.eventChainList().set("companyId", this.id), + params); + URL url = new URL(template.expand()); BBCollection eventChains = new BBCollection(HttpService.api_GET(url, auth_token), auth_token, "event_chains", EventChain.class); return eventChains; } @@ -605,18 +640,24 @@ public Resource spaceStatusList() throws IOException { } + /** * Loads all of the public settings for a company, this allows you to configure a booking widget, * and shows all of the details need to book and show an appropriate widget. - * @return Resource + * @return CompanySettings * @throws IOException */ - public Resource settingsDetails() throws IOException { - URL url = new URL(PublicURLS.Company.settingsDetails().set("companyId", this.id).expand()); - return new Resource(HttpService.api_GET(url)); + public CompanySettings getSettings() throws IOException { + if(getRep().getResourcesByRel("settings").size() > 0) { + //Return settings from embedded + return new CompanySettings(new HttpServiceResponse((ContentRepresentation) getRep().getResourcesByRel("settings").get(0))); + } else { + //Call API + URL url = new URL(PublicURLS.Company.settingsDetails().set("companyId", this.id).expand()); + return new CompanySettings(HttpService.api_GET(url)); + } } - /** * You can either get all the company questions or pass a param to specifiy that you only want company questions * that apply to either a service, resource, person, company: @@ -1036,6 +1077,11 @@ public Resource deleteBasketCoupon() throws IOException { return new Resource(HttpService.api_DELETE(url), auth_token); } + public SchemaForm getNewBookingSchema() throws IOException { + String link = getRep().getLinkByRel("new_booking").getHref(); + URL url = new URL(UriTemplate.fromTemplate(link).expand()); + return new SchemaForm(HttpService.api_GET(url, auth_token)); + } public Booking bookingCreate_Admin(BookingCreateParams bCParams) throws IOException { String urlStr = AdminURLS.Bookings.bookingCreate().set("companyId", this.id).expand(); @@ -1050,8 +1096,13 @@ public Booking bookingCreate_Admin(BookingCreateParams bCParams) throws IOExcept * @throws IOException */ public BBCollection bookingList_Admin(BookingListParams bLParams) throws IOException { - String urlStr = AdminURLS.Bookings.bookingList().set("companyId", this.id).expand(); - URL url = new URL(Utils.inflateLink(urlStr, bLParams.getParams())); + URL url; + if(getLink("bookings") != null) + url = new URL(Utils.inflateLink(getLink("bookings"), bLParams.getParams())); + else { + UriTemplate template = AdminURLS.Bookings.bookingList().set("companyId", this.id); + url = new URL(Utils.inflateLink(template, bLParams.getParams())); + } BBCollection bookings = new BBCollection(HttpService.api_GET(url, auth_token), auth_token, "bookings", Booking.class); return bookings; } @@ -1070,6 +1121,8 @@ public Booking bookingRead_Admin(String bookingId) throws IOException { } + + /** * Get all the coupons for a Company. * @return BBCollection diff --git a/src/main/bookingbugAPI/models/CompanySettings.java b/src/main/bookingbugAPI/models/CompanySettings.java new file mode 100644 index 0000000..a1fd5e1 --- /dev/null +++ b/src/main/bookingbugAPI/models/CompanySettings.java @@ -0,0 +1,55 @@ +package bookingbugAPI.models; + +import helpers.HttpServiceResponse; + +/** + * Created by sebi on 31.03.2016. + */ +public class CompanySettings extends BBRoot { + + public CompanySettings(HttpServiceResponse httpServiceResponse, String auth_token) { + super(httpServiceResponse, auth_token); + } + + public CompanySettings(HttpServiceResponse response) { + super(response); + } + + public boolean has_coupons() { + return getBoolean("has_coupons", false); + } + + public boolean has_deals() { + return getBoolean("has_deals", false); + } + + public boolean has_products() { + return getBoolean("has_products", false); + } + + public boolean has_events() { + return getBoolean("has_events", false); + } + + public boolean has_classes() { + return getBoolean("has_classes", false); + } + + public boolean requires_login() { + return getBoolean("requires_login", false); + } + + public boolean has_wallets() { + return getBoolean("has_wallets", false); + } + + public int getPaymentTax() { + return getInteger("payment_tax", 0); + } + + + + public Currency getCurrency() { + return Currency.fromString(get("currency")); + } +} diff --git a/src/main/bookingbugAPI/models/Currency.java b/src/main/bookingbugAPI/models/Currency.java new file mode 100644 index 0000000..1cf3c6b --- /dev/null +++ b/src/main/bookingbugAPI/models/Currency.java @@ -0,0 +1,33 @@ +package bookingbugAPI.models; + +/** + * Created by sebi on 31.03.2016. + */ +public enum Currency { + GBP("GBP"), + EUR("EUR"); + + private final String apiValue; + + private Currency(String apiValue) { + this.apiValue = apiValue; + } + + public String symbol() { + switch (this) { + case GBP: return "\u00a3"; + case EUR: return "\u20ac"; + default: return ""; + } + } + + public static Currency fromString(String str) { + if(str != null) { + for(Currency currency : Currency.values()) { + if(str.equalsIgnoreCase(currency.apiValue)) + return currency; + } + } + return null; + } +} diff --git a/src/main/bookingbugAPI/models/Event.java b/src/main/bookingbugAPI/models/Event.java index 575fb38..0daad2f 100644 --- a/src/main/bookingbugAPI/models/Event.java +++ b/src/main/bookingbugAPI/models/Event.java @@ -1,7 +1,12 @@ package bookingbugAPI.models; +import bookingbugAPI.services.HttpService; +import com.damnhandy.uri.template.UriTemplate; import helpers.HttpServiceResponse; +import java.io.IOException; +import java.net.URL; + public class Event extends BBRoot{ @@ -17,4 +22,14 @@ public Event(HttpServiceResponse httpServiceResponse, String auth_token){ public Event() {} + public SchemaForm getNewBookingSchema() throws IOException { + if(getLink("new_booking") != null) { + String link = getLink("new_booking"); + URL url = new URL(UriTemplate.fromTemplate(link).expand()); + return new SchemaForm(HttpService.api_GET(url, this.auth_token)); + } + // Throw exception: link is missing + throw new IOException("new_booking link missing"); + } + } diff --git a/src/main/bookingbugAPI/models/EventChain.java b/src/main/bookingbugAPI/models/EventChain.java index dc32cbe..ee29033 100644 --- a/src/main/bookingbugAPI/models/EventChain.java +++ b/src/main/bookingbugAPI/models/EventChain.java @@ -1,6 +1,16 @@ package bookingbugAPI.models; +import bookingbugAPI.api.PublicURLS; +import bookingbugAPI.models.params.EventListParams; +import bookingbugAPI.services.HttpService; +import com.damnhandy.uri.template.UriTemplate; import helpers.HttpServiceResponse; +import helpers.Utils; +import rx.Observable; + +import java.io.IOException; +import java.net.URL; +import java.util.concurrent.Callable; public class EventChain extends BBRoot{ @@ -18,4 +28,38 @@ public EventChain(HttpServiceResponse httpServiceResponse, String auth_token){ public EventChain() {} + public SchemaForm getNewBookingSchema() throws IOException { + URL url = new URL(UriTemplate.fromTemplate(this.getRep().getLinkByRel("new_booking").getHref()).expand()); + return new SchemaForm(HttpService.api_GET(url, this.auth_token)); + } + + /** + * Get a List of Bookable Events for an EventChain. + * @param params Parameters for pagination + * @return BBCollection + * @throws IOException + */ + public BBCollection eventList(EventListParams params) throws IOException { + UriTemplate template; + if(getLink("events") != null) { + template = Utils.TemplateWithPagination( + Utils.paginatedUriTemplate(getLink("events")), + params); + } else { + params.setEvent_chain_id(this.id); + template = PublicURLS.Event.eventList().set("companyId", get("company_id")); + } + + URL url = new URL(template.expand(params.getParamsMapObj())); + return new BBCollection(HttpService.api_GET(url, auth_token), auth_token, "events", Event.class); + } + + public Observable> eventListObs(final EventListParams params){ + return Observable.fromCallable(new Callable>() { + @Override + public BBCollection call() throws Exception { + return eventList(params); + } + }); + } } diff --git a/src/main/bookingbugAPI/models/Login.java b/src/main/bookingbugAPI/models/Login.java index 303f445..050d5b6 100644 --- a/src/main/bookingbugAPI/models/Login.java +++ b/src/main/bookingbugAPI/models/Login.java @@ -5,7 +5,10 @@ import com.damnhandy.uri.template.UriTemplate; import com.theoryinpractise.halbuilder.api.ContentRepresentation; import com.theoryinpractise.halbuilder.api.Link; +import helpers.Config; import helpers.HttpServiceResponse; +import helpers.TokenGenerator; +import org.json.simple.JSONObject; import java.io.IOException; import java.net.MalformedURLException; diff --git a/src/main/bookingbugAPI/models/SchemaForm.java b/src/main/bookingbugAPI/models/SchemaForm.java new file mode 100644 index 0000000..3c98cd7 --- /dev/null +++ b/src/main/bookingbugAPI/models/SchemaForm.java @@ -0,0 +1,58 @@ +package bookingbugAPI.models; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import helpers.HttpServiceResponse; + +import java.util.Map; + +/** + * Created by sebi on 11.04.2016. + */ +public class SchemaForm extends BBRoot { + public SchemaForm(HttpServiceResponse httpServiceResponse, String auth_token) { + super(httpServiceResponse, auth_token); + } + + public SchemaForm(HttpServiceResponse response) { + super(response); + } + + public String getSchemaStr() { + return getSchemaJson().toString(); + } + + public JsonNode getSchemaJson() { + JsonNodeFactory factory = JsonNodeFactory.instance; + ObjectMapper mapper = new ObjectMapper(); + + // Defaults to empty json + JsonNode schema = factory.objectNode(); + + + if(getRep().getValue("schema", null) != null) { + schema = mapper.convertValue(getRep().getValue("schema"), JsonNode.class); + } + + return schema; + } + + public String getFormStr() { + return getFormJson().toString(); + } + + public JsonNode getFormJson() { + JsonNodeFactory factory = JsonNodeFactory.instance; + ObjectMapper mapper = new ObjectMapper(); + + // Defaults to empty json + JsonNode form = factory.objectNode(); + + if(getRep().getValue("form", null) != null) { + form = mapper.convertValue(getRep().getValue("form"), JsonNode.class); + } + + return form; + } +} diff --git a/src/main/bookingbugAPI/models/Service.java b/src/main/bookingbugAPI/models/Service.java index 63400d7..d6b0215 100644 --- a/src/main/bookingbugAPI/models/Service.java +++ b/src/main/bookingbugAPI/models/Service.java @@ -3,15 +3,20 @@ import bookingbugAPI.services.HttpService; import com.damnhandy.uri.template.UriTemplate; import com.theoryinpractise.halbuilder.api.Link; +import com.theoryinpractise.halbuilder.api.ReadableRepresentation; import helpers.HttpServiceResponse; import helpers.Utils; import java.io.IOException; import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; public class Service extends BBRoot { + private ArrayList durations; + private ArrayList prices; public Service(HttpServiceResponse httpServiceResponse) { super(httpServiceResponse); @@ -26,6 +31,15 @@ public Service(HttpServiceResponse httpServiceResponse, String auth_token) { public Service() { } + public SchemaForm getNewBookingSchema() throws IOException { + if(getLink("new_booking") != null) { + String link = getLink("new_booking"); + URL url = new URL(UriTemplate.fromTemplate(link).expand()); + return new SchemaForm(HttpService.api_GET(url, this.auth_token)); + } + // Throw exception: link is missing + throw new IOException("new_booking link missing"); + } public Service getService(Link link) throws IOException { String absUrl = Utils.absoluteURL(link.getHref()); @@ -34,5 +48,31 @@ public Service getService(Link link) throws IOException { return service; } + public ArrayList getDurations() { + if(durations == null) { + durations = new ArrayList<>(); + Object duration_reps = getRep().getValue("durations"); + if(duration_reps instanceof Collection) { + for (Object rep : (Collection) duration_reps) { + durations.add(Integer.parseInt(rep.toString())); + } + } + } + return durations; + } + + public ArrayList getPrices() { + if(prices == null) { + prices = new ArrayList<>(); + Object prices_reps = getRep().getValue("prices"); + if(prices_reps instanceof Collection) { + for (Object rep : (Collection) prices_reps) { + prices.add(Integer.parseInt(rep.toString())); + } + } + } + return prices; + } + } diff --git a/src/main/bookingbugAPI/models/params/BookingCreateParams.java b/src/main/bookingbugAPI/models/params/BookingCreateParams.java index f0bb1bb..01ce2e0 100644 --- a/src/main/bookingbugAPI/models/params/BookingCreateParams.java +++ b/src/main/bookingbugAPI/models/params/BookingCreateParams.java @@ -17,36 +17,8 @@ public class BookingCreateParams extends Params{ public BookingCreateParams(){} - public BookingCreateParams(Map args){ - if (args==null || args.isEmpty()) { - return; - } - - String strValue; - - for (Map.Entry entry : args.entrySet()) { - final String[] value = entry.getValue(); - if (value[0]!=null && !value[0].trim().isEmpty()) { - strValue = null; - } else { - strValue = value[0]; - } - - switch(entry.getKey()) { - case "datetime": datetime = strValue; - break; - case "service_id": service_id = strValue; - break; - case "person_id": person_id = strValue; - break; - case "resource_id": resource_id = strValue; - break; - case "member_id": member_id = strValue; - break; - case "notifications": notifications = strValue; - break; - } - } + public BookingCreateParams(Map args){ + super(args); } public String getDatetime() { diff --git a/src/main/bookingbugAPI/models/params/BookingListParams.java b/src/main/bookingbugAPI/models/params/BookingListParams.java index 9544eac..007af21 100644 --- a/src/main/bookingbugAPI/models/params/BookingListParams.java +++ b/src/main/bookingbugAPI/models/params/BookingListParams.java @@ -4,7 +4,7 @@ import java.util.Map; -public class BookingListParams { +public class BookingListParams extends Params { String start_date; String end_date; @@ -15,80 +15,15 @@ public class BookingListParams { String modified_since; String created_since; String email; - String page; - String per_page; String client_id; + String order_by; public BookingListParams(){} - public BookingListParams(Map args){ - if (args==null || args.isEmpty()) { - return; - } - - String strValue; - - for (Map.Entry entry : args.entrySet()) { - final String[] value = entry.getValue(); - if (value[0]!=null && !value[0].trim().isEmpty()) { - strValue = null; - } else { - strValue = value[0]; - } - - switch(entry.getKey()) { - case "start_date": start_date = strValue; - break; - case "end_date": end_date = strValue; - break; - case "include_cancelled": include_cancelled = strValue; - break; - case "event_id": event_id = strValue; - break; - case "category_id": category_id = strValue; - break; - case "start_time": start_time = strValue; - break; - case "modified_since": modified_since = strValue; - break; - case "created_since": created_since = strValue; - break; - case "email": email = strValue; - break; - case "page": page = strValue; - break; - case "per_page": per_page = strValue; - break; - case "client_id": client_id = strValue; - break; - } - } - } - - - /** - * getParams - * @return Map - */ - public Map getParams() { - Map params = new HashMap(); - - params.put("start_date", new String[]{start_date}); - params.put("end_date", new String[]{end_date}); - params.put("include_cancelled", new String[]{include_cancelled}); - params.put("event_id", new String[]{event_id}); - params.put("category_id", new String[]{category_id}); - params.put("start_time", new String[]{start_time}); - params.put("modified_since", new String[]{modified_since}); - params.put("created_since", new String[]{created_since}); - params.put("email", new String[]{email}); - params.put("page", new String[]{page}); - params.put("per_page", new String[]{per_page}); - params.put("client_id", new String[]{client_id}); - - return params; + public BookingListParams(int page){ + super(page); } @@ -173,30 +108,21 @@ public BookingListParams setEmail(String email) { return this; } - public String getPage() { - return page; - } - - public BookingListParams setPage(String page) { - this.page = page; - return this; - } - - public String getPer_page() { - return per_page; + public String getClient_id() { + return client_id; } - public BookingListParams setPer_page(String per_page) { - this.per_page = per_page; + public BookingListParams setClient_id(String client_id) { + this.client_id = client_id; return this; } - public String getClient_id() { - return client_id; + public String getOrder_by() { + return order_by; } - public BookingListParams setClient_id(String client_id) { - this.client_id = client_id; + public BookingListParams setOrder_by(String order_by) { + this.order_by = order_by; return this; } } diff --git a/src/main/bookingbugAPI/models/params/EventListParams.java b/src/main/bookingbugAPI/models/params/EventListParams.java new file mode 100644 index 0000000..48ed147 --- /dev/null +++ b/src/main/bookingbugAPI/models/params/EventListParams.java @@ -0,0 +1,85 @@ +package bookingbugAPI.models.params; + +/** + * Created by sebi on 31.03.2016. + */ +public class EventListParams extends Params { + String resource_id; + String event_chain_id; + String person_id; + String event_group_id; + String summary; + String member_level_id; + String start_date; + String end_date; + + public EventListParams() {} + + public EventListParams(int page){ + super(page); + } + + public String getResource_id() { + return resource_id; + } + + public void setResource_id(String resource_id) { + this.resource_id = resource_id; + } + + public String getPerson_id() { + return person_id; + } + + public void setPerson_id(String person_id) { + this.person_id = person_id; + } + + public String getEvent_group_id() { + return event_group_id; + } + + public void setEvent_group_id(String event_group_id) { + this.event_group_id = event_group_id; + } + + public String getSummary() { + return summary; + } + + public void setSummary(String summary) { + this.summary = summary; + } + + public String getMember_level_id() { + return member_level_id; + } + + public void setMember_level_id(String member_level_id) { + this.member_level_id = member_level_id; + } + + public String getStart_date() { + return start_date; + } + + public void setStart_date(String start_date) { + this.start_date = start_date; + } + + public String getEnd_date() { + return end_date; + } + + public void setEnd_date(String end_date) { + this.end_date = end_date; + } + + public String getEvent_chain_id() { + return event_chain_id; + } + + public void setEvent_chain_id(String event_chain_id) { + this.event_chain_id = event_chain_id; + } +} diff --git a/src/main/bookingbugAPI/models/params/Params.java b/src/main/bookingbugAPI/models/params/Params.java index d2a8f09..4ba3652 100644 --- a/src/main/bookingbugAPI/models/params/Params.java +++ b/src/main/bookingbugAPI/models/params/Params.java @@ -1,29 +1,68 @@ package bookingbugAPI.models.params; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; -public abstract class Params { +public class Params { + + private int page = 1; + private int per_page = 100; + + public boolean hasJson = false; + private String jsonContent; public Params() {} + public Params(int page) { + this.page = page; + } + public Params(Map args){ setNotNullStringMap(args); } + public static Params withPagination(int page, int per_page){ + Params params = new Params(); + params.page = page; + params.per_page = per_page; + return params; + } + + public static Params withPagination(int page){ + Params params = new Params(); + params.page = page; + return params; + } + + public void setJson(String json) { + hasJson = true; + jsonContent = json; + } + public Map getNotNullStringMap() { - Map result = new HashMap(); + Map result = new HashMap<>(); Field[] declaredFields = this.getClass().getDeclaredFields(); for (Field field : declaredFields) { try { - if(field.getType() == String.class && (String)field.get(this) != null) - result.put(field.getName(), (String)field.get(this)); + if(field.get(this) != null) + result.put(field.getName(), field.get(this).toString()); } catch (IllegalAccessException e) { e.printStackTrace(); } } + + //Add pagination params + result.put("page", String.valueOf(getPage())); + result.put("per_page", String.valueOf(getPer_page())); + return result; } @@ -41,7 +80,64 @@ public void setNotNullStringMap(Map map) { } } - public Map getParams(){ - return getNotNullStringMap(); + /** + * Get parameters. If hasJson is true (setJson method has been called) then the parameters will be extracted from + * json string. Otherwise all non null declared fields of this object will be included + * + * @return Generic Map with parameters + */ + public Map getParams(){ + if(!hasJson) + // Return default map + return getNotNullStringMap(); + + // Return map from jsonContent + ObjectMapper mapper = new ObjectMapper(); + HashMap map = new HashMap<>(); + try { + map = mapper.readValue(jsonContent, HashMap.class); + } catch (IOException e) { + e.printStackTrace(); + } + return map; + } + + /** + * @see Params#getParams() + * @return + */ + public Map getParamsMapObj() { + Map objectMap = new HashMap<>(); + objectMap.putAll(getParams()); + return objectMap; + } + + public int getPage() { + return page; + } + + public int getPer_page() { + return per_page; + } + + public Params setPerPage(int per_page) { + this.per_page = per_page; + return this; + } + + public Params setPage(int page) { + this.page = page; + return this; + } + + @Override + public String toString(){ + String jsonThis = ""; + try { + jsonThis = new ObjectMapper().writeValueAsString(this); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + return hasJson ? jsonContent : jsonThis; } } \ No newline at end of file diff --git a/src/main/bookingbugAPI/models/params/ServiceListParams.java b/src/main/bookingbugAPI/models/params/ServiceListParams.java index b41b33d..ea587af 100644 --- a/src/main/bookingbugAPI/models/params/ServiceListParams.java +++ b/src/main/bookingbugAPI/models/params/ServiceListParams.java @@ -4,67 +4,12 @@ import java.util.Map; -public class ServiceListParams { +public class ServiceListParams extends Params{ - String page; - String per_page; + public ServiceListParams() {} - - public ServiceListParams(){} - - - public ServiceListParams(Map args){ - if (args==null || args.isEmpty()) { - return; - } - - String strValue; - - for (Map.Entry entry : args.entrySet()) { - final String[] value = entry.getValue(); - if (value[0]!=null && !value[0].trim().isEmpty()) { - strValue = null; - } else { - strValue = value[0]; - } - - switch(entry.getKey()) { - case "page": page = strValue; - break; - case "per_page": per_page = strValue; - break; - } - } + public ServiceListParams(int page){ + super(page); } - - /** - * getParams - * @return Map - */ - public Map getParams() { - Map params = new HashMap(); - - params.put("page", new String[]{page}); - params.put("per_page", new String[]{per_page}); - - return params; - } - - - public String getPage() { - return page; - } - - public void setPage(String page) { - this.page = page; - } - - public String getPerPage() { - return per_page; - } - - public void setPerPage(String per_page) { - this.per_page = per_page; - } } diff --git a/src/main/bookingbugAPI/models/params/TimeDataParams.java b/src/main/bookingbugAPI/models/params/TimeDataParams.java new file mode 100644 index 0000000..bbfab58 --- /dev/null +++ b/src/main/bookingbugAPI/models/params/TimeDataParams.java @@ -0,0 +1,126 @@ +package bookingbugAPI.models.params; + +import com.fasterxml.jackson.databind.util.ISO8601DateFormat; + +import javax.print.DocFlavor; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Date; +import java.util.StringTokenizer; + +/** + * Created by sebi on 27.02.2016. + */ +public class TimeDataParams extends Params { + + String event_id; + String service_id; + String resource_id; + String resource_ids; + String person_id; + String group_id; + String location; + String date; + String end_date; + String duration; + String num_resources; + + public String getEvent_id() { + return event_id; + } + + public void setEvent_id(String event_id) { + this.event_id = event_id; + } + + public String getNum_resources() { + return num_resources; + } + + public void setNum_resources(String num_resources) { + this.num_resources = num_resources; + } + + public int getDuration() { + return Integer.parseInt(duration); + } + + public void setDuration(int duration) { + this.duration = String.valueOf(duration); + } + + public String getEnd_date() { + return end_date; + } + + public void setEnd_date(Date end_date) { + this.end_date = new ISO8601DateFormat().format(end_date); + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public String getDate() { + return date; + } + + public void setDate(Date date) { + this.date = new ISO8601DateFormat().format(date); + } + + + + public String getPerson_id() { + return person_id; + } + + public void setPerson_id(String person_id) { + this.person_id = person_id; + } + + public String getGroup_id() { + return group_id; + } + + public void setGroup_id(String group_id) { + this.group_id = group_id; + } + + public String getService_id() { + return service_id; + } + + public void setService_id(String service_id) { + this.service_id = service_id; + } + + public String getResource_id() { + return resource_id; + } + + public void setResource_id(String resource_id) { + this.resource_id = resource_id; + } + + public ArrayList getResource_ids() { + ArrayList res = new ArrayList<>(); + StringTokenizer tokenizer = new StringTokenizer(resource_ids, ","); + while (tokenizer.hasMoreTokens()) + res.add(tokenizer.nextToken()); + return res; + } + + public void setResource_ids(ArrayList resource_ids) { + this.resource_ids = ""; + for(int i = 0; i < resource_ids.size(); i++) { + this.resource_ids += resource_ids.get(i); + if(i + 1 < resource_ids.size()) + this.resource_ids += ","; + } + } +} diff --git a/src/main/bookingbugAPI/services/HttpService.java b/src/main/bookingbugAPI/services/HttpService.java index 283bcba..349beae 100644 --- a/src/main/bookingbugAPI/services/HttpService.java +++ b/src/main/bookingbugAPI/services/HttpService.java @@ -3,21 +3,18 @@ import bookingbugAPI.models.HttpException; import bookingbugAPI.models.PublicRoot; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import com.theoryinpractise.halbuilder.api.ContentRepresentation; import com.theoryinpractise.halbuilder.api.RepresentationFactory; -import com.theoryinpractise.halbuilder.json.JsonRepresentationFactory; import helpers.Config; import bookingbugAPI.models.BBRoot; +import helpers.Http; import helpers.HttpServiceResponse; import helpers.hal_addon.CustomJsonRepresentationFactory; import java.io.*; import java.lang.reflect.InvocationTargetException; import java.net.HttpURLConnection; -import java.net.ProtocolException; import java.net.URL; -import java.net.URLEncoder; import java.util.Map; import java.util.logging.Logger; @@ -29,50 +26,13 @@ public class HttpService { public final static String jsonContentType = "application/json"; public final static String urlEncodedContentType = "application/x-www-form-urlencoded"; + public final static String UTF8Encoding = "UTF-8"; - public static String encodeParams(Map params) { - StringBuilder postData = new StringBuilder(); - try{ - for (Map.Entry param : params.entrySet()) { - if (postData.length() != 0) postData.append('&'); - postData.append(URLEncoder.encode(param.getKey(), "UTF-8")); - postData.append('='); - postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8")); - } - } catch(UnsupportedEncodingException e){ - log.warning(e.getMessage()); - } - return postData.toString(); - } - - public static String encodeParamsJson(Map params) { - String json = ""; - try { - json = new ObjectMapper().writeValueAsString(params); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - return json; - } - - public static byte[] encodeUTF8(Map params, String contentType) { - byte[] data = new byte[0]; - String encodedParams = ""; - - //Convert to json instead - if(contentType == urlEncodedContentType) - encodedParams = encodeParams(params); - else if(contentType == jsonContentType) - encodedParams = encodeParamsJson(params); - - try { - data = encodedParams.getBytes("UTF-8"); - //data = json.getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - log.warning(e.getMessage()); - } - return data; + public static byte[] encodeUTF8(Map params, String contentType) throws Http.UnknownContentType, Http.EncodingException, UnsupportedEncodingException { + return Http.getEncoder(contentType) + .encode(params) + .getBytes(UTF8Encoding); } public static HttpServiceResponse api_GET(URL url, boolean testingMode) throws HttpException { @@ -99,23 +59,23 @@ public static HttpServiceResponse api_POST(URL url, String auth_token) throws Ht return callApi(url, auth_token, "POST", urlEncodedContentType, null); } - public static HttpServiceResponse api_POST(URL url, Map params) throws HttpException { + public static HttpServiceResponse api_POST(URL url, Map params) throws HttpException { return callApi(url, null, "POST", urlEncodedContentType, params); } - public static HttpServiceResponse api_POST(URL url, Map params, String auth_token) throws HttpException { + public static HttpServiceResponse api_POST(URL url, Map params, String auth_token) throws HttpException { return callApi(url, auth_token, "POST", urlEncodedContentType, params); } - public static HttpServiceResponse api_PUT(URL url, Map params) throws HttpException { + public static HttpServiceResponse api_PUT(URL url, Map params) throws HttpException { return callApi(url, null, "PUT", urlEncodedContentType, params); } - public static HttpServiceResponse api_PUT(URL url, Map params, String auth_token) throws HttpException { + public static HttpServiceResponse api_PUT(URL url, Map params, String auth_token) throws HttpException { return callApi(url, auth_token, "PUT", urlEncodedContentType, params); } - public static HttpServiceResponse api_PUT(URL url, String contentType, Map params, String auth_token) throws HttpException { + public static HttpServiceResponse api_PUT(URL url, String contentType, Map params, String auth_token) throws HttpException { return callApi(url, auth_token, "PUT", contentType, params); } @@ -127,17 +87,18 @@ public static HttpServiceResponse api_DELETE(URL url, String auth_token) throws return callApi(url, auth_token, "DELETE", urlEncodedContentType, null); } - public static HttpServiceResponse api_DELETE(URL url, String contentType, Map params, String auth_token) throws HttpException { + public static HttpServiceResponse api_DELETE(URL url, String contentType, Map params, String auth_token) throws HttpException { return callApi(url, auth_token, "DELETE", contentType, params); } - private static HttpServiceResponse callApi(URL url, String auth_token, String method, String contentType, Map params) throws HttpException { + private static HttpServiceResponse callApi(URL url, String auth_token, String method, String contentType, Map params) throws HttpException { return callApi(url, auth_token, method, contentType, params, false); } - private static HttpServiceResponse callApi(URL url, String auth_token, String method, String contentType, Map params, boolean testingMode) throws HttpException { + private static HttpServiceResponse callApi(URL url, String auth_token, String method, String contentType, Map params, boolean testingMode) throws HttpException { String returnString = ""; String errorMessage = ""; + byte[] bodyBytes = new byte[0]; int responseCode = 200; boolean throwError = false; HttpURLConnection urlConnection = null; @@ -158,7 +119,8 @@ private static HttpServiceResponse callApi(URL url, String auth_token, String me if(params != null) { //Set params in body urlConnection.setDoOutput(true); - urlConnection.getOutputStream().write(encodeUTF8(params, contentType)); + bodyBytes = encodeUTF8(params, contentType); + urlConnection.getOutputStream().write(bodyBytes); } responseCode = urlConnection.getResponseCode(); @@ -191,50 +153,25 @@ private static HttpServiceResponse callApi(URL url, String auth_token, String me if (!testingMode) { if(throwError) { - errorMessage = "The call to " + url.toString() + " returned " + urlConnection.getResponseCode() + " . Error message: " + returnString; + errorMessage = "The call to " + url.toString() + + "with parameters " + new String(bodyBytes, UTF8Encoding) + " returned " + + urlConnection.getResponseCode() + " . Error message: " + returnString; //System.out.println("Error message: "+ errorMessage); } else { Reader reader = new InputStreamReader(new ByteArrayInputStream(returnString.getBytes())); - return new HttpServiceResponse(representationFactory.readRepresentation(HAL_JSON, reader), method, params, auth_token); + return new HttpServiceResponse(representationFactory.readRepresentation(HAL_JSON, reader), method, contentType, params, auth_token); } } else { Reader reader = new InputStreamReader(new ByteArrayInputStream(returnString.getBytes())); - return new HttpServiceResponse(representationFactory.readRepresentation(HAL_JSON, reader), method, params, auth_token); + return new HttpServiceResponse(representationFactory.readRepresentation(HAL_JSON, reader), method, contentType, params, auth_token); } - } catch (IOException e) { throw new HttpException("Error", returnString, e) ; + } catch (Http.EncodingException | Http.UnknownContentType e) { + throw new HttpException("Error when writing body params", e) ; } finally { if(urlConnection != null) urlConnection.disconnect(); } throw new HttpException(errorMessage, returnString, responseCode); } - - public PublicRoot start() throws IOException { - URL url = new URL(new Config().serverUrl); - return new PublicRoot(api_GET(url)); - } - - public BBRoot start(Class type) throws IOException { - URL url = new URL(new Config().serverUrl); - ContentRepresentation representation = api_GET(url).getRep(); - Object obj = null; - - Class[] args = new Class[2]; - args[0] = representation.getClass(); - args[1] = this.getClass(); - - try { - obj = type.getConstructor(ContentRepresentation.class, HttpService.class).newInstance(representation, this); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - return (BBRoot)obj; - } } \ No newline at end of file diff --git a/src/main/helpers/Http.java b/src/main/helpers/Http.java new file mode 100644 index 0000000..9607b70 --- /dev/null +++ b/src/main/helpers/Http.java @@ -0,0 +1,162 @@ +package helpers; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.*; + +/** + * Created by sebi on 13.04.2016. + */ +public class Http { + public final static String jsonContentType = "application/json"; + public final static String urlEncodedContentType = "application/x-www-form-urlencoded"; + + public static Encoder getEncoder(String content_type) throws UnknownContentType { + if(jsonContentType.equals(content_type)) + return new JsonEncoder(); + else if(urlEncodedContentType.equals(content_type)) + return new UrlEncoder(); + + throw new UnknownContentType("Unknown content type: " + content_type + + ". Possible values are " + jsonContentType + ", " + urlEncodedContentType); + } + + public interface Encoder { + String encode(Map map) throws EncodingException; + } + + public static class UrlEncoder implements Encoder { + + private static final Set> PRIMITIVE_WRAPPER_TYPES; + static { + PRIMITIVE_WRAPPER_TYPES = new HashSet>(); + PRIMITIVE_WRAPPER_TYPES.add(Boolean.class); + PRIMITIVE_WRAPPER_TYPES.add(Character.class); + PRIMITIVE_WRAPPER_TYPES.add(String.class); + PRIMITIVE_WRAPPER_TYPES.add(Short.class); + PRIMITIVE_WRAPPER_TYPES.add(Integer.class); + PRIMITIVE_WRAPPER_TYPES.add(Long.class); + PRIMITIVE_WRAPPER_TYPES.add(Float.class); + PRIMITIVE_WRAPPER_TYPES.add(Double.class); + } + + private boolean ignoreNull = false; + + public UrlEncoder(){} + + public UrlEncoder(boolean ignoreNull) { + this.ignoreNull = ignoreNull; + } + + public String encode(Map map) throws EncodingException { + try { + ArrayList encoded = new ArrayList<>(); + for (Object o : map.entrySet()) { + Map.Entry pair = (Map.Entry) o; + + encoded.add(nest(pair.getKey().toString(), pair.getValue())); + } + return joinArray(encoded); + } catch (UnsupportedEncodingException e) { + throw new EncodingException("Exception when encoding to " + urlEncodedContentType, e); + } + } + + private String encode(String value) throws UnsupportedEncodingException { + return URLEncoder.encode(value, "UTF-8"); + } + + private static String joinArray(ArrayList arr) { + String res = ""; + for(int i = 0; i < arr.size(); i++) { + if(arr.get(i).toString().isEmpty()) continue; + res += arr.get(i).toString(); + //Last element + if(i == arr.size() - 1) continue; + res += '&'; + } + return res; + } + + private String arrayNest(String name, ArrayList value) throws UnsupportedEncodingException { + if(value == null) return ""; + + ArrayList encoded = new ArrayList<>(); + for(Object obj : value) { + encoded.add(nest(name + "[]", obj)); + } + return joinArray(encoded); + } + + private String objectNest(String name, Map value) throws UnsupportedEncodingException { + if(value == null) return ""; + + ArrayList encoded = new ArrayList<>(); + for (Object o : value.entrySet()) { + Map.Entry pair = (Map.Entry) o; + encoded.add(nest(name + '[' + pair.getKey().toString() + ']', pair.getValue())); + } + + return joinArray(encoded); + } + + private String nest(String name, Object value) throws UnsupportedEncodingException { + String res = ""; + + if(value == null) { + res = ignoreNull ? "" : encode(name) + '=' + "null"; + } else if(isPrimitiveWrapper(value.getClass())) { + res = encode(name) + '=' + encode(value.toString()); + } else if (value instanceof Collection) { + //Array + res = arrayNest(name, (ArrayList)value); + } else if (value instanceof Map) { + //Object + res = objectNest(name, (Map)value); + } + + return res; + } + + public static boolean isPrimitiveWrapper(Class clazz) + { + return PRIMITIVE_WRAPPER_TYPES.contains(clazz); + } + } + + public static class JsonEncoder implements Encoder { + + @Override + public String encode(Map map) throws EncodingException { + try { + return new ObjectMapper().writeValueAsString(map); + } catch (JsonProcessingException e) { + throw new EncodingException("Exception when encoding to " + jsonContentType, e); + } + } + } + + public static class EncodingException extends Exception { + + public EncodingException(String message) { + super(message); + } + + public EncodingException(String message, Throwable cause) { + super(message, cause); + } + + public EncodingException(Throwable cause) { + super(cause); + } + } + + public static class UnknownContentType extends Exception { + public UnknownContentType(String message) { + super(message); + } + } + +} diff --git a/src/main/helpers/HttpServiceResponse.java b/src/main/helpers/HttpServiceResponse.java index 622a00b..8626f12 100644 --- a/src/main/helpers/HttpServiceResponse.java +++ b/src/main/helpers/HttpServiceResponse.java @@ -1,5 +1,6 @@ package helpers; +import bookingbugAPI.services.HttpService; import com.theoryinpractise.halbuilder.api.ContentRepresentation; import java.util.Map; @@ -10,7 +11,8 @@ public class HttpServiceResponse { protected ContentRepresentation rep; protected String method; - protected Map params; + protected String contentType = HttpService.jsonContentType; + protected Map params; protected String authToken; @@ -22,7 +24,7 @@ public HttpServiceResponse(ContentRepresentation rep) { } - public HttpServiceResponse(ContentRepresentation rep, String method, Map params) { + public HttpServiceResponse(ContentRepresentation rep, String method, Map params) { this.rep = rep; this.method = method; this.params = params; @@ -30,9 +32,10 @@ public HttpServiceResponse(ContentRepresentation rep, String method, Map params, String auth_token) { + public HttpServiceResponse(ContentRepresentation rep, String method, String contentType, Map params, String auth_token) { this.rep = rep; this.method = method; + this.contentType = contentType; this.params = params; this.authToken = auth_token; } @@ -58,12 +61,12 @@ public void setMethod(String method) { } - public void setParams(Map params) { + public void setParams(Map params) { this.params = params; } - public Map getParams() { + public Map getParams() { return params; } @@ -84,18 +87,15 @@ public String getParamsStr() { paramsStr += " -H \"Auth_Token:" + authToken + "\""; } - if (params!=null) { + try { + paramsStr += " -H \"Content-Type: " + contentType + "\""; paramsStr += " -d \""; - int i=0; - for (Map.Entry param : params.entrySet()) { - if (i>0) { - paramsStr += "&"; - } - paramsStr += param.getKey() + "=" + param.getValue(); - i++; - } + paramsStr += Http.getEncoder(contentType).encode(params); paramsStr += "\""; } + catch (Http.EncodingException | Http.UnknownContentType | NullPointerException e) { + e.printStackTrace(); + } return paramsStr; } diff --git a/src/main/helpers/Utils.java b/src/main/helpers/Utils.java index 1129a96..5c821c9 100644 --- a/src/main/helpers/Utils.java +++ b/src/main/helpers/Utils.java @@ -1,6 +1,8 @@ package helpers; +import bookingbugAPI.models.params.Params; import com.damnhandy.uri.template.UriTemplate; +import com.damnhandy.uri.template.UriTemplateBuilder; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -45,6 +47,24 @@ public static String absoluteURL(String url){ return absoluteURL(url, null); } + /** + * Given a string url returns a templated url with pagination + * @param fromTemplate String to convert to UriTemplate + * @return + */ + public static UriTemplate paginatedUriTemplate(String fromTemplate){ + return UriTemplate.buildFromTemplate(fromTemplate) + .query(UriTemplateBuilder.var("page"), UriTemplateBuilder.var("per_page")) + .build(); + } + + public static UriTemplate TemplateWithPagination(UriTemplate template, Params params){ + if(params != null){ + template.set("page", params.getPage()); + template.set("per_page", params.getPer_page()); + } + return template; + } /** * @param content @@ -79,25 +99,30 @@ public static boolean linkHasArgs(String link) { return vars.length > 0; } + public static String inflateLink(UriTemplate template, Map args) { + Map toInflate = new HashMap(); + + for (Object key : args.keySet()) { + final Object value = args.get(key); + + if(value == null || (value instanceof String && ((String) value).trim().isEmpty())) + continue; + + if(value instanceof String[] && (((String[])value).length > 0 || ((String[])value)[0].trim().isEmpty())) + continue; + + toInflate.put(key.toString(), value); + } + return template.expand(toInflate); + } /** * @param link * @param args * @return */ - public static String inflateLink(String link, Map args) { - UriTemplate template = UriTemplate.fromTemplate(link); - Map toInflate = new HashMap(); - - for (Map.Entry entry : args.entrySet()) { - final String key = entry.getKey(); - final String[] value = entry.getValue(); - - if (value[0]!=null && !value[0].trim().isEmpty()) { - toInflate.put(key, value); - } - } - return template.expand(toInflate); + public static String inflateLink(String link, Map args) { + return inflateLink(UriTemplate.fromTemplate(link), args); } diff --git a/src/main/helpers/hal_addon/CustomJsonDeserializer.java b/src/main/helpers/hal_addon/CustomJsonDeserializer.java index 14b255f..dfc65d2 100644 --- a/src/main/helpers/hal_addon/CustomJsonDeserializer.java +++ b/src/main/helpers/hal_addon/CustomJsonDeserializer.java @@ -3,22 +3,39 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer; +import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import java.io.IOException; +import java.util.HashMap; /** * Created by sebi on 04.02.2016. */ -public class CustomJsonDeserializer extends JsonDeserializer { +public class CustomJsonDeserializer extends UntypedObjectDeserializer { + + @Override + public Object deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { + if(jsonParser.getCurrentTokenId() == 11) { + return ""; + } + return super.deserialize(jsonParser, deserializationContext); + } + @Override - public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { - return jsonParser.getText(); + public Object deserializeWithType(JsonParser jsonParser, DeserializationContext deserializationContext, TypeDeserializer typeDeserializer) throws IOException, JsonProcessingException { + if(jsonParser.getCurrentTokenId() == 11) { + return ""; + } + return super.deserialize(jsonParser, deserializationContext, typeDeserializer); } @Override - public String getNullValue(){ + public Object getNullValue() { return ""; } } diff --git a/src/test/bookingbugAPI/api/CompanyTest.java b/src/test/bookingbugAPI/api/CompanyTest.java new file mode 100644 index 0000000..7f9679e --- /dev/null +++ b/src/test/bookingbugAPI/api/CompanyTest.java @@ -0,0 +1,54 @@ +package bookingbugAPI.api; + +import bookingbugAPI.models.*; +import bookingbugAPI.services.HttpService; +import org.junit.Ignore; +import org.junit.Test; + +import java.net.URL; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * Created by sebi on 31.03.2016. + */ + +@Ignore +public class CompanyTest { + + private static final String companyId = "37028"; + private static final String token = "7gcmPMDS-G2gpNiPSUQA4A"; + + @Test + public void companySettings(){ + Company company = null; + try { + URL url = new URL(AdminURLS.Company.company().set("companyId", companyId).expand()); + company = new Company(HttpService.api_GET(url, token), token); + assertNotNull(company); + assertNotNull(company.getSettings()); + assertEquals(company.getSettings().getCurrency(), Currency.GBP); + }catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void companyBookingSchema(){ + Company company = null; + SchemaForm schemaForm = null; + try { + URL url = new URL(AdminURLS.Company.company().set("companyId", companyId).expand()); + company = new Company(HttpService.api_GET(url, token), token); + assertNotNull(company); + + schemaForm = company.getNewBookingSchema(); + assertNotNull(schemaForm); + schemaForm.getSchemaJson(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/bookingbugAPI/models/ParamsTest.java b/src/test/bookingbugAPI/models/ParamsTest.java index c53cfbc..f99f54f 100644 --- a/src/test/bookingbugAPI/models/ParamsTest.java +++ b/src/test/bookingbugAPI/models/ParamsTest.java @@ -2,11 +2,15 @@ import bookingbugAPI.models.params.BookingCreateParams; import bookingbugAPI.models.params.ClientCreateParams; +import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Test; +import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; /** @@ -21,8 +25,7 @@ public void paramsMap(){ params.setService_id("service_id"); params.setMember_id("member_id"); - Map map = params.getParams(); - assertTrue(map.size() == 3); + Map map = params.getParams(); assertTrue(map.containsKey("datetime")); assertTrue(map.containsKey("service_id")); @@ -41,7 +44,6 @@ public void clientCreateParamsFromMap(){ params.setLast_name("Last"); Map map = params.getParams(); - assertTrue(map.size() == 3); assertTrue(map.containsKey("first_name")); assertTrue(map.get("first_name").equals("first")); @@ -56,4 +58,15 @@ public void clientCreateParamsFromMap(){ assertTrue(params2.getPostcode().equals("123")); assertTrue(params2.getMember_type().equals("3")); } + + @Test + public void jsonParamsTest() { + String json = "{\"str\":\"val\", \"num\":0, \"arr\":[29], \"arr2\":[{\"name\":\"mkyong1\"}, {\"name\":\"mkyong1\"}]}}"; + BookingCreateParams params = new BookingCreateParams(); + params.setJson(json); + Map m = params.getParams(); + assertNotNull(m); + assertTrue(m.containsKey("arr2") && m.get("arr2") != null && m.get("arr2") instanceof ArrayList); + assertTrue(m.containsKey("str") && "val".equals(m.get("str"))); + } } diff --git a/src/test/bookingbugAPI/services/HalCustomJsonDeserializer.java b/src/test/bookingbugAPI/services/HalCustomJsonDeserializer.java new file mode 100644 index 0000000..6d01400 --- /dev/null +++ b/src/test/bookingbugAPI/services/HalCustomJsonDeserializer.java @@ -0,0 +1,46 @@ +package bookingbugAPI.services; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import helpers.hal_addon.CustomJsonDeserializer; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertTrue; + +/** + * Created by sebi on 27.04.2016. + */ +public class HalCustomJsonDeserializer { + + private ObjectMapper mapper; + + @Before + public void setUp() { + this.mapper = new ObjectMapper(); + + SimpleModule simpleModule = new SimpleModule(); + simpleModule.addDeserializer(Object.class, new CustomJsonDeserializer()); + this.mapper.registerModule(simpleModule); + } + + @After + public void tearDown() throws Exception { + mapper = null; + } + + @Test + public void nullFieldJsonTest() throws IOException { + Map map = mapper.readValue("{\"settings\":{\"who_cancelled\":{\"embed\":null}, \"late\":1}}", Map.class); + assertTrue(map.get("settings") != null); + assertTrue(((Map)map.get("settings")).get("who_cancelled") != null); + assertTrue(((Map)((Map)map.get("settings")).get("who_cancelled")).get("embed") != null); + + } +} + diff --git a/src/test/bookingbugAPI/services/UrlEncoderTest.java b/src/test/bookingbugAPI/services/UrlEncoderTest.java new file mode 100644 index 0000000..34ba573 --- /dev/null +++ b/src/test/bookingbugAPI/services/UrlEncoderTest.java @@ -0,0 +1,67 @@ +package bookingbugAPI.services; + +import com.fasterxml.jackson.databind.ObjectMapper; +import helpers.Http; +import org.junit.Test; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +import static org.junit.Assert.assertTrue; + +/** + * Created by sebi on 13.04.2016. + */ +public class UrlEncoderTest { + + final String json = "{\"str\":\"val\", \"num\":0, \"arr\":[3, {\"prop\": \"false\"}, 1, null, 6 ], \"obj\":{\"prop1\":null, \"prop2\":[\"elem\"]}}"; + final String nullTrueResCorrect = "arr%5B%5D=3&arr%5B%5D%5Bprop%5D=false&arr%5B%5D=1&arr%5B%5D=6&num=0&obj%5Bprop2%5D%5B%5D=elem&str=val"; + final String nullFalseCorrect = "str=val&num=0&arr%5B%5D=3&arr%5B%5D%5Bprop%5D=false&arr%5B%5D=1&arr%5B%5D=null&arr%5B%5D=6&obj%5Bprop1%5D=null&obj%5Bprop2%5D%5B%5D=elem"; + + private HashMap getMap() { + ObjectMapper mapper = new ObjectMapper(); + HashMap map = new HashMap<>(); + try { + map = mapper.readValue(json, HashMap.class); + } catch (IOException e) { + e.printStackTrace(); + } + return map; + } + + private boolean sameEncoding(String originalEncoding, String resultEncoding) { + String[] split = resultEncoding.split("&"); + Set set = new HashSet<>(Arrays.asList(originalEncoding.split("&"))); + + if(split.length != set.size()) return false; + if(!set.containsAll(Arrays.asList(split))) return false; + return true; + } + + @Test + public void encodeMapIgnoreNullTrue(){ + HashMap map = getMap(); + try { + Http.UrlEncoder encoder = new Http.UrlEncoder(true); + String res = encoder.encode(map); + assertTrue(sameEncoding(nullTrueResCorrect, res)); + } catch (Http.EncodingException e) { + e.printStackTrace(); + } + } + + @Test + public void encodeMapIgnoreNullFalse(){ + HashMap map = getMap(); + try { + Http.UrlEncoder encoder = new Http.UrlEncoder(false); + String res = encoder.encode(map); + assertTrue(sameEncoding(nullFalseCorrect, res)); + } catch (Http.EncodingException e) { + e.printStackTrace(); + } + } +}