package org.betaconceptframework.astroboa.resourceapi.resource;
import java.net.HttpURLConnection;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.betaconceptframework.astroboa.api.model.BinaryChannel.ContentDispositionType;
import org.betaconceptframework.astroboa.api.model.CalendarProperty;
import org.betaconceptframework.astroboa.api.model.ContentObject;
import org.betaconceptframework.astroboa.api.model.SimpleCmsProperty;
import org.betaconceptframework.astroboa.api.model.StringProperty;
import org.betaconceptframework.astroboa.api.model.Topic;
import org.betaconceptframework.astroboa.client.AstroboaClient;
import org.betaconceptframework.astroboa.resourceapi.utility.ContentApiUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SimplePropertyResource extends AstroboaResource{
private final Logger logger = LoggerFactory.getLogger(getClass());
private final static String DATE_WITH_TIME_FORMAT_PATTERN = "dd-MM-yyyy HH:mm:ss z";
private SimpleCmsProperty property;
private int valueIndex;
private ContentObject contentObject;
public SimplePropertyResource (
AstroboaClient astroboaClient,
ContentObject contentObject,
SimpleCmsProperty property,
int valueIndex) {
super(astroboaClient);
this.contentObject = contentObject;
this.property = property;
this.valueIndex = valueIndex;
}
// This will be called through the content object resource. The contentObjectIdOrName, propertyPath have been already consumed and the requested
// property and value index are passed through the class constructor.
// The API call always returns a single value even if the property is multivalue.
// This means that for multivalue properties you should provide a value index (between brackets) at the end of the path,
// e.g. departments.department[0] or departments.department[0].jobPositions.jobPosition[0]
//If the value index is omitted, the first value is always returned
@GET
@Path("/")
public Response getContentObjectSimplePropertyValue(
@QueryParam("contentDispositionType") String contentDispositionType,
@QueryParam("callback") String callback) {
if (property == null) {
logger.warn("The property passed through the class constructor is null");
throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND);
}
if (StringUtils.isBlank(contentDispositionType) || ! ContentDispositionType.ATTACHMENT.toString().equals(contentDispositionType.toUpperCase())){
contentDispositionType = ContentDispositionType.INLINE.toString();
}
else {
contentDispositionType = contentDispositionType.toUpperCase();
}
try{
if (property.hasNoValues()){
logger.warn("Content Object name: {}. The provided property {} does not have any values", contentObject.getSystemName(), property.getPath());
throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND);
}
Object propertyValue;
if (property.getPropertyDefinition().isMultiple()){
try{
propertyValue = property.getSimpleTypeValues().get(valueIndex);
}
catch(Exception e){
logger.warn("Content Object name: " + contentObject.getSystemName() + ". Unable to retrieve value from property "+ property.getPath() + " for index "+ valueIndex, e);
throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND);
}
}
else{
if (valueIndex != 0){
logger.warn("Content Object name: {}. A value index greater than 0 has been provided but the property {} is a single value property. You will get back the value but you should avoid to specify a value index for single value properties", contentObject.getSystemName(), property.getPath());
}
propertyValue = property.getSimpleTypeValue();
}
if (propertyValue == null) {
logger.warn("Content Object name: {}. The property value does not exist in path {}. Check if the value index you provided is correct", contentObject.getSystemName(), property.getPath());
throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND);
}
// now that we have the value lets typecast it and convert it to string in order to generate the response
String propertyValueAsString = null;
switch (property.getValueType()) {
case String:
propertyValueAsString = (String) propertyValue;
break;
case Date:
propertyValueAsString = convertDateToString(((Calendar) propertyValue).getTime(), DATE_WITH_TIME_FORMAT_PATTERN);
break;
case Boolean:
propertyValueAsString = ((Boolean) propertyValue).toString();
break;
case Long:
propertyValueAsString = ((Long) propertyValue).toString();
break;
case Double:
propertyValueAsString = ((Double) propertyValue).toString();
break;
case ObjectReference:
propertyValueAsString = ((ContentObject) propertyValue).getId(); // when values are references to cms entities the id of the entity is returned
break;
case TopicReference:
propertyValueAsString = ((Topic) propertyValue).getId(); // when values are references to cms entities the id of the entity is returned
break;
default:
logger.warn("Content Object name: " + contentObject.getSystemName() + ". The provided property " + property.getPath() + " has the value type " + property.getValueType().toString() + " which is not supported by the current astroboa resource api version");
throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND);
}
if (StringUtils.isNotBlank(callback)) {
propertyValueAsString = callback + "('" + StringEscapeUtils.escapeJavaScript(propertyValueAsString) + "')" + ";";
}
ResponseBuilder responseForPropertyValue = null;
String responseFileName = contentObject.getSystemName() + "-" + property.getPath();
responseForPropertyValue = Response.ok(propertyValueAsString);
responseForPropertyValue.type(MediaType.TEXT_PLAIN + "; charset=utf-8");
// in some special cases we need to return a different mime type
if ("cascadingStyleSheetObject".equals(contentObject.getContentObjectType())) {
responseForPropertyValue.type("text/css; charset=utf-8");
responseFileName = responseFileName + ".css";
}
else if ("scriptObject".equals(contentObject.getContentObjectType())) {
StringProperty scriptLanguageProperty = (StringProperty) contentObject.getCmsProperty("scriptLanguage");
if (scriptLanguageProperty != null && scriptLanguageProperty.hasValues()) {
String scriptLanguage = scriptLanguageProperty.getFirstValue();
if ("javascript".equals(scriptLanguage)) {
responseForPropertyValue.type("text/javascript; charset=utf-8");
responseFileName = responseFileName + ".js";
}
else {
responseFileName = responseFileName + scriptLanguage;
}
}
}
ContentApiUtils.addContentDispositionHeaderToResponse(responseForPropertyValue, ContentDispositionType.valueOf(contentDispositionType), responseFileName);
ContentApiUtils.addLastModifiedAndETagHeaderToResponse(responseForPropertyValue,
((CalendarProperty)contentObject.getCmsProperty("profile.modified")).getSimpleTypeValueAsDate(),
propertyValueAsString.length());
return responseForPropertyValue.build();
}
catch (WebApplicationException e) {
throw e;
}
catch (Exception e) {
logger.error("A problem occured while connecting repository client to Astroboa Repository", e);
throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND);
}
}
private String convertDateToString(Date date, String dateFormatPattern) {
SimpleDateFormat dateFormat = (SimpleDateFormat) DateFormat.getDateInstance();
dateFormat.setLenient(false); // be strict in the formatting
// apply accepted pattern
dateFormat.applyPattern(dateFormatPattern);
return dateFormat.format(date);
}
}