/*
* © Copyright IBM Corp. 2014
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.ibm.sbt.services.client.smartcloud.bss;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import com.ibm.commons.util.StringUtil;
import com.ibm.commons.util.io.json.JsonException;
import com.ibm.commons.util.io.json.JsonJavaFactory;
import com.ibm.commons.util.io.json.JsonJavaObject;
import com.ibm.commons.util.io.json.JsonParser;
import com.ibm.sbt.services.client.ClientService;
import com.ibm.sbt.services.client.Response;
import com.ibm.sbt.services.client.base.JsonEntity;
import com.ibm.sbt.services.client.base.NamedUrlPart;
import com.ibm.sbt.services.client.base.datahandlers.EntityList;
import com.ibm.sbt.services.endpoints.Endpoint;
/**
* Use subscription management services to create subscriptions, suspend subscriptions, get subscriptions by ID, and more.
*
* @author mwallace
*/
public class SubscriberManagementService extends BssService {
private static final long serialVersionUID = 1L;
/**
* Constructor
*/
public SubscriberManagementService() {
}
/**
* Constructor
*
* @param endpointName
*/
public SubscriberManagementService(String endpointName) {
super(endpointName);
}
/**
* Constructor
*
* @param endpointName
* @param cacheSize
*/
public SubscriberManagementService(String endpointName, int cacheSize) {
super(endpointName, cacheSize);
}
/**
* Constructor
*
* @param endpoint
*/
public SubscriberManagementService(Endpoint endpoint) {
super(endpoint);
}
/**
* Constructor
*
* @param endpoint
* @param cacheSize
*/
public SubscriberManagementService(Endpoint endpoint, int cacheSize) {
super(endpoint, cacheSize);
}
/**
* Return subscriber id for the specified JSON object.
*
* @param subscriberObject
* @return {JsonJavaObject}
*/
public String getSubscriberId(JsonJavaObject subscriberObject) {
return getId(subscriberObject, PROPERTY_SUBSCRIBER);
}
/**
* Add a subscriber either to the vendor's organization or to the organization of one of the vendor's customers.
*
* @param subscriber
* @return {JsonJavaObject}
* @throws BssException
* @throws JsonException
* @throws IOException
*/
public JsonJavaObject addSubscriber(SubscriberJsonBuilder subscriber) throws BssException, IOException, JsonException {
return addSubscriber(subscriber.toJson());
}
/**
* Add a subscriber either to the vendor's organization or to the organization of one of the vendor's customers.
*
* @param subscriberJson
* @return {JsonJavaObject}
* @throws BssException
* @throws JsonException
* @throws IOException
*/
public JsonJavaObject addSubscriber(String subscriberJson) throws BssException, JsonException, IOException {
JsonJavaObject jsonObject = (JsonJavaObject)JsonParser.fromJson(JsonJavaFactory.instanceEx, subscriberJson);
return addSubscriber(jsonObject);
}
/**
* Add a subscriber either to the vendor's organization or to the organization of one of the vendor's customers.
*
* @param subscriberJson
* @return JSON object containing
* @throws BssException
* @throws IOException
*/
public JsonJavaObject addSubscriber(JsonJavaObject subscriberJson) throws BssException {
try {
String serviceUrl = BssUrls.API_RESOURCE_SUBSCRIBER.format(this);
Response serverResponse = createData(serviceUrl, null, JsonHeader, subscriberJson, ClientService.FORMAT_JSON);
return (serverResponse == null) ? null : (JsonJavaObject)serverResponse.getData();
} catch (Exception e) {
throw new BssException(e, "Error adding subscriber {0} caused by {1}", subscriberJson, e.getMessage());
}
}
/**
* Add a subscriber w/ suppressing emails either to the vendor's organization or to the organization of one of the vendor's customers.
*
* @param subscriber
* @return {JsonJavaObject}
* @throws BssException
* @throws JsonException
* @throws IOException
*/
public JsonJavaObject addSubscriberSuppressEmail(SubscriberJsonBuilder subscriber) throws BssException, IOException, JsonException {
return addSubscriberSuppressEmail(subscriber.toJson());
}
/**
* Add a subscriber w/ suppressing emails either to the vendor's organization or to the organization of one of the vendor's customers.
*
* @param subscriberJson
* @return {JsonJavaObject}
* @throws BssException
* @throws JsonException
* @throws IOException
*/
public JsonJavaObject addSubscriberSuppressEmail(String subscriberJson) throws BssException, JsonException, IOException {
JsonJavaObject jsonObject = (JsonJavaObject)JsonParser.fromJson(JsonJavaFactory.instanceEx, subscriberJson);
return addSubscriberSuppressEmail(jsonObject);
}
/**
* Add a subscriber w/ suppressing emails either to the vendor's organization or to the organization of one of the vendor's customers.
*
* @param subscriberJson
* @return JSON object containing
* @throws BssException
* @throws IOException
*/
public JsonJavaObject addSubscriberSuppressEmail(JsonJavaObject subscriberJson) throws BssException {
try {
// TODO add url to BSSUrls when moving to SocialSDK
String serviceUrl = "/api/bss/resource/subscriber?suppressEmail=true";
Response serverResponse = createData(serviceUrl, null, JsonHeader, subscriberJson, ClientService.FORMAT_JSON);
return (serverResponse == null) ? null : (JsonJavaObject)serverResponse.getData();
} catch (Exception e) {
throw new BssException(e, "Error adding subscriber {0} caused by {1}", subscriberJson, e.getMessage());
}
}
/**
* Get details about a single subscriber.
*
* @param subscriberId
* @return {JsonEntity}
* @throws BssException
*/
public JsonEntity getSubscriberById(String subscriberId) throws BssException {
try {
String serviceUrl = BssUrls.API_RESOURCE_SUBSCRIBER_SUBSCRIBERID.format(this, BssUrls.subscriberId(subscriberId));
return getEntity(serviceUrl, null, getJsonFeedHandler());
} catch (Exception e) {
throw new BssException(e, "Error retrieving subscriber {0} caused by {1}", subscriberId, e.getMessage());
}
}
/**
* Activate a subscriber.
*
* @param subscriberId
* @throws BssException
*/
public void activateSubscriber(String subscriberId) throws BssException {
try {
String serviceUrl = BssUrls.API_RESOURCE_SUBSCRIBER_SUBSCRIBERID.format(this, BssUrls.subscriberId(subscriberId));
Response response = createData(serviceUrl, (Map<String, String>)null, ActivateSubscriberHeader, (Object)null);
// expect a 204
int statusCode = response.getResponse().getStatusLine().getStatusCode();
if (statusCode != 204) {
throw new BssException(response, "Error activating subscriber {0} caused by {1}", subscriberId, statusCode);
}
} catch (Exception e) {
throw new BssException(e, "Error activating subscriber {0} caused by {1}", subscriberId, e.getMessage());
}
}
/**
* Delete a subscriber from an organization.
* This action also frees the assigned seats to the subscribers.
* The subscriber must be owned by the organization of the authenticated user.
*
* @param subscriberId
* @throws BssException
*/
public void deleteSubscriber(String subscriberId) throws BssException {
try {
String serviceUrl = BssUrls.API_RESOURCE_SUBSCRIBER_SUBSCRIBERID.format(this, BssUrls.subscriberId(subscriberId));
Response response = deleteData(serviceUrl, null, null);
// expect a 204
int statusCode = response.getResponse().getStatusLine().getStatusCode();
if (statusCode != 204) {
throw new BssException(response, "Error deleting subscriber {0}", subscriberId);
}
} catch (Exception e) {
throw new BssException(e, "Error deleting subscriber {0} caused by {1}", subscriberId, e.getMessage());
}
}
/**
* Update the profile of a registered subscriber. Update details such as name, location, and contact information.
* Important: Mutable attributes that are not in the payload that you submit are deleted from the database.
* To avoid inadvertently deleting information, retrieve the most current subscriber profile for the subscriber that you intend to update.
*
* @param subscriberObject
* @throws BssException
*/
public void updateSubscribeProfile(JsonJavaObject subscriberObject) throws BssException {
try {
String subscriberId = getSubscriberId(subscriberObject);
String serviceUrl = BssUrls.API_RESOURCE_SUBSCRIBER_SUBSCRIBERID.format(this, BssUrls.subscriberId(subscriberId));
Response response = updateData(serviceUrl, null, JsonHeader, subscriberObject, null);
// expect a 204
int statusCode = response.getResponse().getStatusLine().getStatusCode();
if (statusCode != 204) {
throw new BssException(response, "Error updating subscriber profile {0} caused by {1}", subscriberObject, statusCode);
}
} catch (Exception e) {
throw new BssException(e, "Error updating subscriber profile {0} caused by {1]", subscriberObject, e.getMessage());
}
}
/**
* Get a list of subscribers who are in the same organization as the API caller.
* Subscribers from the caller's immediate organization and subscribers from all child organizations are returned in a single list.
*
* @return {EntityList<JsonEntity>}
* @throws BssException
*/
public EntityList<JsonEntity> getSubscribers() throws BssException {
try {
String serviceUrl = BssUrls.API_RESOURCE_SUBSCRIBER.format(this);
return (EntityList<JsonEntity>)getEntities(serviceUrl, null, getJsonFeedHandler());
} catch (Exception e) {
throw new BssException(e, "Error retrieving subscriber list caused by {0}", e.getMessage());
}
}
/**
* Get a list of subscribers who are in the same organization as the API caller.
* Subscribers from the caller's immediate organization and subscribers from all child organizations are returned in a single list.
*
* @param pageNumber
* @param pageSize
* @return {EntityList<JsonEntity>}
* @throws BssException
*/
public EntityList<JsonEntity> getSubscribers(int pageNumber, int pageSize) throws BssException {
try {
String serviceUrl = BssUrls.API_RESOURCE_SUBSCRIBER.format(this);
HashMap<String, String> params = new HashMap<String, String>();
params.put("_pageNumber", String.valueOf(pageNumber));
params.put("_pageSize", String.valueOf(pageSize));
return (EntityList<JsonEntity>)getEntities(serviceUrl, params, getJsonFeedHandler());
} catch (Exception e) {
throw new BssException(e, "Error retrieving subscriber list page {0},{1} caused by {2}", pageNumber, pageNumber, e.getMessage());
}
}
/**
* Get a list of subscribers with a given email address.
*
* @param email
* @return {EntityList<JsonEntity>}
* @throws BssException
* @throws {@link IllegalArgumentException}
*/
public EntityList<JsonEntity> getSubscribersByEmail(String email) throws BssException {
return getSubscribersByEmail(email, new HashMap<String, String>());
}
/**
* Get a list of subscribers with a given email address.
*
* @param email
* @return {EntityList<JsonEntity>}
* @throws BssException
* @throws {@link IllegalArgumentException}
*/
public EntityList<JsonEntity> getSubscribersByEmail(String email, HashMap<String, String> params) throws BssException {
if (StringUtil.isEmpty(email)) {
throw new IllegalArgumentException("Invalid email address");
}
try {
String serviceUrl = BssUrls.API_RESOURCE_GET_SUBSCRIBERS_BY_EMAIL_ADDRESS.format(this, new NamedUrlPart("emailAddress", email));
return (EntityList<JsonEntity>)getEntities(serviceUrl, params, getJsonFeedHandler());
} catch (Exception e) {
throw new BssException(e, "Error retrieving subscriber list by email {0} caused by {1}", email, e.getMessage());
}
}
/**
* Get a list of all subscribers for a customer with a given ID.
*
* @param customerId
* @return {EntityList<JsonEntity>}
* @throws BssException
* @throws {@link IllegalArgumentException}
*/
public EntityList<JsonEntity> getSubscribersById(String customerId) throws BssException {
return getSubscribersById(customerId, new HashMap<String, String>());
}
/**
* Get a list of all subscribers for a customer with a given ID.
*
* @param customerId
* @param params
* @return {EntityList<JsonEntity>}
* @throws BssException
* @throws {@link IllegalArgumentException}
*/
public EntityList<JsonEntity> getSubscribersById(String customerId, Map<String, String> params) throws BssException {
if (StringUtil.isEmpty(customerId)) {
throw new IllegalArgumentException("Invalid id");
}
try {
String serviceUrl = BssUrls.API_RESOURCE_GET_SUBSCRIBER_BY_CUSTOMER.format(this, new NamedUrlPart("customerId", customerId));
return (EntityList<JsonEntity>)getEntities(serviceUrl, params, getJsonFeedHandler());
} catch (Exception e) {
throw new BssException(e, "Error retrieving subscriber list by customer id {0} caused by {1}", customerId, e.getMessage());
}
}
/**
* Suspend a subscriber.
* Suspended subscribers are no longer active and cannot use services to which they are entitled.
*
* @param subscriberId
* @param force
* @throws BssException
*/
public void suspendSubscriber(String subscriberId, boolean force) throws BssException {
try {
Map<String, String> params = new HashMap<String, String>();
params.put("_force", force ? "true" : "false");
String serviceUrl = BssUrls.API_RESOURCE_SUBSCRIBER_SUBSCRIBERID.format(this, BssUrls.subscriberId(subscriberId));
Response response = createData(serviceUrl, params, SuspendSubscriberHeader, (Object)null);
// expect a 204
int statusCode = response.getResponse().getStatusLine().getStatusCode();
if (statusCode != 204) {
throw new BssException(response, "Error suspending subscriber {0} caused {1}", subscriberId, statusCode);
}
} catch (Exception e) {
throw new BssException(e, "Error suspending subscriber {0} with force {1} caused by {2}", subscriberId, force, e.getMessage());
}
}
/**
* Unsuspend a subscriber.
* This action returns subscribers to active state so they can use the services to which they are entitled.
*
* @param subscriberId
* @throws BssException
*/
public void unsuspendSubscriber(String subscriberId) throws BssException {
try {
String serviceUrl = BssUrls.API_RESOURCE_SUBSCRIBER_SUBSCRIBERID.format(this, BssUrls.subscriberId(subscriberId));
Response response = createData(serviceUrl, (Map<String, String>)null, UnsuspendSubscriberHeader, (Object)null);
// expect a 204
int statusCode = response.getResponse().getStatusLine().getStatusCode();
if (statusCode != 204) {
throw new BssException(response, "Error unsuspending subscriber {0} caused by {1}", subscriberId, statusCode);
}
} catch (Exception e) {
throw new BssException(e, "Error unsuspending subscriber {0} caused by {1}", subscriberId, e.getMessage());
}
}
/**
* Entitle a subscriber to a subscription.
* This action assigns a seat for the subscriber in the subscription.
*
* @param subscriberId
* @param subscriptionId
* @param acceptTOU
* @throws BssException
*/
public JsonEntity entitleSubscriber(String subscriberId, String subscriptionId, boolean acceptTOU) throws BssException {
try {
String serviceUrl = BssUrls.API_RESOURCE_ENTITLE_SUBSCRIBER.format(this,
new NamedUrlPart("subscriberId", subscriberId),
new NamedUrlPart("subscriptionId", subscriptionId),
new NamedUrlPart("acceptTOU", acceptTOU ? "true" : "false"));
Response response = createData(serviceUrl, null, EntitleSubscriberHeader, (Object)null);
return getJsonFeedHandler().createEntity(response);
} catch (Exception e) {
throw new BssException(e, "Error entitling subscriber {0} to {1} with {2} caused by {3}", subscriberId, subscriptionId, acceptTOU, e.getMessage());
}
}
/**
* Revoke a subscriber from a given subscription.
* When revoking subscribers, the seats that they currently occupy in the subscription become available.
* This action does not delete subscribers from the system, however.
*
* @param subscriberId
* @param seatId
* @param force
* @throws BssException
*/
public void revokeSubscriber(String subscriberId, String seatId, boolean force) throws BssException {
try {
String serviceUrl = BssUrls.API_RESOURCE_REVOKE_SUBSCRIBER.format(this,
new NamedUrlPart("subscriberId", subscriberId),
new NamedUrlPart("seatId", seatId),
new NamedUrlPart("_force", force ? "true" : "false"));
Response response = createData(serviceUrl, null, RevokeSubscriberHeader, (Object)null);
// expect a 204
int statusCode = response.getResponse().getStatusLine().getStatusCode();
if (statusCode != 204) {
throw new BssException(response, "Error revoking subscriber {0} to {1} with force {2} caused by {3}", subscriberId, seatId, force, statusCode);
}
} catch (Exception e) {
throw new BssException(e, "Error revoking subscriber {0} to {1} with force {2} caused by {3}", subscriberId, seatId, force, e.getMessage());
}
}
/**
* Wait for the subscriber to change to the specified state and then call the state change listener.
*
* @param subscriberId
* @param state
* @param maxAttempts
* @param waitInterval
* @param listener
*
* @throws BssException
*/
public boolean waitSubscriberState(String subscriberId, String state, int maxAttempts, long waitInterval, StateChangeListener listener) throws BssException {
for (int i=0; i<maxAttempts; i++) {
JsonEntity subscriber = getSubscriberById(subscriberId);
String currentState = subscriber.getAsString("Subscriber/SubscriberState");
if (state.equalsIgnoreCase(currentState)) {
try {
if (listener != null) {
listener.stateChanged(subscriber);
}
return true;
} catch (Exception e) {
logger.log(Level.WARNING, "Error invoking subscriber state listener", e);
}
}
// wait the specified interval
try {
Thread.sleep(waitInterval);
} catch (InterruptedException ie) {}
}
return false;
}
/**
* Wait for the subscriber seat to change to the specified state and then call the state change listener.
*
* @param subscriberId
* @param state
* @param maxAttempts
* @param waitInterval
* @param listener
*
* @throws BssException
*/
public boolean waitSeatState(String subscriberId, String subscriptionId, String state, int maxAttempts, long waitInterval, StateChangeListener listener) throws BssException {
for (int i=0; i<maxAttempts; i++) {
JsonEntity subscriber = getSubscriberById(subscriberId);
JsonJavaObject subscriberJson = subscriber.getJsonObject().getAsObject("Subscriber");
List<Object> seatSet = subscriberJson.getAsList("SeatSet");
JsonJavaObject seatJson = findSeat(seatSet, subscriptionId);
if (seatJson != null) {
String currentState = seatJson.getAsString("SeatState");
if (state.equalsIgnoreCase(currentState)) {
try {
if (listener != null) {
listener.stateChanged(subscriber);
}
return true;
} catch (Exception e) {
logger.log(Level.WARNING, "Error invoking subscriber state listener", e);
}
}
}
// wait the specified interval
try {
Thread.sleep(waitInterval);
} catch (InterruptedException ie) {}
}
return false;
}
private JsonJavaObject findSeat(List<Object> seatSet, String subscriptionId) {
for (Object seat : seatSet) {
String nextSubscriptionId = "" + (long)((JsonJavaObject)seat).getAsDouble("SubscriptionId");
if (subscriptionId.equals(nextSubscriptionId)) {
return (JsonJavaObject)seat;
}
}
return null;
}
}