package controllers;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.apache.chemistry.opencmis.client.api.ObjectType;
import org.apache.chemistry.opencmis.client.api.Session;
import org.apache.chemistry.opencmis.client.api.Tree;
import org.apache.chemistry.opencmis.commons.definitions.DocumentTypeDefinition;
import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.enums.Cardinality;
import org.apache.chemistry.opencmis.commons.enums.ContentStreamAllowed;
import org.apache.chemistry.opencmis.commons.enums.DateTimeResolution;
import org.apache.chemistry.opencmis.commons.enums.PropertyType;
import org.apache.chemistry.opencmis.commons.enums.Updatability;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AbstractPropertyDefinition;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AbstractTypeDefinition;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.DocumentTypeDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.FolderTypeDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ItemTypeDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyBooleanDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDateTimeDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDecimalDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyHtmlDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIdDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIntegerDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyUriDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.TypeMutabilityImpl;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import play.data.DynamicForm;
import play.data.Form;
import play.mvc.Controller;
import play.mvc.Result;
import play.mvc.Http.MultipartFormData;
import play.mvc.Http.MultipartFormData.FilePart;
import play.mvc.Security.Authenticated;
import scala.xml.Elem;
import util.Util;
public class Type extends Controller {
private static Session getCmisSession(String repositoryId){
return CmisSessions.getCmisSession(repositoryId, session());
}
public static Result index(String repositoryId) {
Session session = Util.createCmisSession(repositoryId, session());
List<ObjectType> list = new ArrayList<ObjectType>();
List<Tree<ObjectType>> descendants = session.getTypeDescendants(null, -1, true);
for(Tree<ObjectType> _type : descendants){
ObjectType type = _type.getItem();
list.add(type);
}
return ok(views.html.objecttype.list.render(repositoryId, list));
}
public static Result download(String repositoryId, String id){
Session session = getCmisSession(repositoryId);
ObjectType objectType = session.getTypeDefinition(id);
ObjectMapper mapper = new ObjectMapper();
ObjectNode json = mapper.createObjectNode();
json.put("id", escape(objectType.getId()));
json.put("localName", escape(objectType.getLocalName()));
json.put("localNamespace", escape(objectType.getLocalNamespace()));
json.put("displayName", escape(objectType.getDisplayName()));
json.put("queryName", escape(objectType.getQueryName()));
json.put("description", escape(objectType.getDescription()));
json.put("baseId", escape(objectType.getBaseTypeId().value()));
if(StringUtils.isNotBlank(objectType.getParentTypeId())){
json.put("parentId", escape(objectType.getParentTypeId()));
}
json.put("creatable", objectType.isCreatable());
json.put("fileable", objectType.isFileable());
json.put("queryable", objectType.isQueryable());
json.put("fulltextIndexed", objectType.isFulltextIndexed());
json.put("includedInSupertypeQuery", objectType.isIncludedInSupertypeQuery());
json.put("controllablePolicy", objectType.isControllablePolicy());
json.put("controllableACL", objectType.isControllableAcl());
ObjectNode typeMutability = mapper.createObjectNode();
typeMutability.put("create", objectType.getTypeMutability().canCreate());
typeMutability.put("update", objectType.getTypeMutability().canUpdate());
typeMutability.put("delete", objectType.getTypeMutability().canDelete());
json.put("typeMutability", typeMutability);
if(objectType instanceof DocumentTypeDefinition){
DocumentTypeDefinition documentType = (DocumentTypeDefinition)objectType;
json.put("versionable", documentType.isVersionable());
json.put("contentStreamAllowed", documentType.getContentStreamAllowed().value());
}
//Property definitions
Map<String, PropertyDefinition<?>> map = objectType.getPropertyDefinitions();
ObjectNode propertyDefinitions = mapper.createObjectNode();
for(String key : map.keySet()){
PropertyDefinition<?> pdf = map.get(key);
ObjectNode propertyDefinition = mapper.createObjectNode();
propertyDefinition.put("id", escape(pdf.getId()));
propertyDefinition.put("localName", escape(pdf.getLocalName()));
propertyDefinition.put("localNamespace", escape(pdf.getLocalNamespace()));
propertyDefinition.put("displayName", escape(pdf.getDisplayName()));
propertyDefinition.put("queryName", escape(pdf.getQueryName()));
propertyDefinition.put("description", escape(pdf.getDescription()));
propertyDefinition.put("propertyType", pdf.getPropertyType().value());
propertyDefinition.put("cardinality", pdf.getCardinality().value());
propertyDefinition.put("updatability", pdf.getUpdatability().value());
propertyDefinition.put("inherited", pdf.isInherited());
propertyDefinition.put("required", pdf.isRequired());
propertyDefinition.put("queryable", pdf.isQueryable());
propertyDefinition.put("orderable", pdf.isOrderable());
propertyDefinition.put("openChoice", pdf.isOpenChoice());
//TODO implement "choice"
propertyDefinitions.put(pdf.getId(), propertyDefinition);
}
json.put("propertyDefinitions", propertyDefinitions);
File file;
try {
file = File.createTempFile(
String.valueOf(System.currentTimeMillis()), null);
mapper.writeValue(file, json);
try {
if (request().getHeader("User-Agent").indexOf("MSIE") == -1) {
// Firefox, Opera 11
response().setHeader(
"Content-Disposition",
String.format(Locale.JAPAN,
"attachment; filename*=utf-8'jp'%s",
URLEncoder.encode(objectType.getId() + ".json", "utf-8")));
} else {
// IE7, 8, 9
response().setHeader(
"Content-Disposition",
String.format(Locale.JAPAN,
"attachment; filename=\"%s\"", new String((objectType.getId() + ".json").getBytes("MS932"),
"ISO8859_1")));
}
} catch (Exception e) {
e.printStackTrace();
}
response().setContentType("application/json");
return ok(file);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return noContent();
}
private static String escape(String str){
//TODO is this way to escape a string really desirable?
return StringEscapeUtils.escapeEcmaScript(str);
}
public static Result showBlank(String repositoryId){
return ok(views.html.objecttype.blank.render(repositoryId));
}
public static Result create(String repositoryId){
DynamicForm input = Form.form();
input = input.bindFromRequest();
MultipartFormData body = request().body().asMultipartFormData();
List<FilePart> files = body.getFiles();
for (FilePart file : files) {
//parse json file
ObjectMapper mapper = new ObjectMapper();
try {
JsonNode json = mapper.readTree(file.getFile());
//Call CMIS API
TypeDefinition tdf = parseType(json);
Session session = getCmisSession(repositoryId);
ObjectType newType = session.createType(tdf);
System.out.println();
} catch (JsonProcessingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return redirect(routes.Type.index(repositoryId));
}
public static Result edit(String repositoryId){
return ok(views.html.objecttype.edit.render(repositoryId));
}
public static Result update(String repositoryId){
DynamicForm input = Form.form();
input = input.bindFromRequest();
MultipartFormData body = request().body().asMultipartFormData();
List<FilePart> files = body.getFiles();
for (FilePart file : files) {
//parse json file
ObjectMapper mapper = new ObjectMapper();
try {
JsonNode json = mapper.readTree(file.getFile());
//Call CMIS API
TypeDefinition tdf = parseType(json);
Session session = getCmisSession(repositoryId);
ObjectType udpatedType = session.updateType(tdf);
} catch (JsonProcessingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return redirect(routes.Type.index(repositoryId));
}
public static Result delete(String repositoryId, String id){
Session session = getCmisSession(repositoryId);
session.deleteType(id);
return redirect(routes.Type.index(repositoryId));
}
private static TypeDefinition parseType(JsonNode json){
String baseId = json.get("baseId").textValue();
if(BaseTypeId.CMIS_DOCUMENT.value().equals(baseId)){
return parseDocumentType(json);
}else if(BaseTypeId.CMIS_FOLDER.value().equals(baseId)){
return parseFolder(json);
}else if(BaseTypeId.CMIS_ITEM.value().equals(baseId)){
return parseItem(json);
}
return null;
}
private static void parseCommonType(AbstractTypeDefinition tdf, JsonNode json){
tdf.setId(getString(json, "id"));
tdf.setLocalName(getString(json, "localName"));
tdf.setLocalNamespace(getString(json, "localNamespace"));
tdf.setDisplayName(getString(json, "displayName"));
tdf.setQueryName(getString(json, "queryName"));
tdf.setDescription(getString(json, "description"));
String baseId = getString(json, "baseId");
if(baseId != null){
tdf.setBaseTypeId(BaseTypeId.fromValue(baseId));
}
tdf.setParentTypeId(getString(json, "parentId"));
tdf.setIsCreatable(getBoolean(json, "creatable"));
tdf.setIsFileable(getBoolean(json, "fileable"));
tdf.setIsQueryable(getBoolean(json, "queryable"));
tdf.setIsFulltextIndexed(getBoolean(json, "fulltextIndexed"));
tdf.setIsIncludedInSupertypeQuery(getBoolean(json, "includedInSupertypeQuery"));
tdf.setIsControllablePolicy(getBoolean(json, "controllablePolicy"));
tdf.setIsControllableAcl(getBoolean(json, "controllableACL"));
TypeMutabilityImpl typeMutability = new TypeMutabilityImpl();
JsonNode tmJson = json.get("typeMutability");
typeMutability.setCanCreate(getBoolean(tmJson, "create"));
typeMutability.setCanUpdate(getBoolean(tmJson, "update"));
typeMutability.setCanDelete(getBoolean(tmJson, "delete"));
tdf.setTypeMutability(typeMutability);
//TODO property definitions
Map<String, PropertyDefinition<?>> newPropertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
JsonNode propertyDefinitions = json.get("propertyDefinitions");
if(propertyDefinitions != null){
Iterator<JsonNode> itr = propertyDefinitions.iterator();
while(itr.hasNext()){
JsonNode propertyDefinition = itr.next();
PropertyDefinition<?> newPropertyDefinition = parseProperty(propertyDefinition);
newPropertyDefinitions.put(newPropertyDefinition.getId(), newPropertyDefinition);
}
tdf.setPropertyDefinitions(newPropertyDefinitions);
}
}
private static TypeDefinition parseDocumentType(JsonNode json){
DocumentTypeDefinitionImpl pdf = new DocumentTypeDefinitionImpl();
parseCommonType(pdf, json);
pdf.setIsVersionable(getBoolean(json, "versionable"));
String contentStreamAllowed = getString(json, "contentStreamAllowed");
if(contentStreamAllowed != null){
pdf.setContentStreamAllowed(ContentStreamAllowed.fromValue(contentStreamAllowed));
}
return pdf;
}
private static TypeDefinition parseFolder(JsonNode json){
FolderTypeDefinitionImpl pdf = new FolderTypeDefinitionImpl();
parseCommonType(pdf, json);
return pdf;
}
private static TypeDefinition parseItem(JsonNode json){
ItemTypeDefinitionImpl pdf = new ItemTypeDefinitionImpl();
parseCommonType(pdf, json);
return pdf;
}
private static PropertyDefinition<?> parseProperty(JsonNode json){
PropertyType propertyType =PropertyType.fromValue(json.get("propertyType").textValue());
switch(propertyType){
case BOOLEAN:
return parseBooleanProperty(json);
case DATETIME:
return parseDateTimeProperty(json);
case DECIMAL:
return parseDecimalProperty(json);
case HTML:
return parseHtmlProperty(json);
case ID:
return parseIdProperty(json);
case INTEGER:
return parseIntegerProperty(json);
case STRING:
return parseStringProperty(json);
case URI:
return parseUriProperty(json);
}
return null;
}
private static void parseCommon(AbstractPropertyDefinition<?> pdf, JsonNode json){
pdf.setId(getString(json, "id"));
pdf.setLocalName(getString(json, "localName"));
//TODO
pdf.setLocalNamespace(getString(json, "localNamespace"));
pdf.setDisplayName(getString(json, "displayName"));
pdf.setQueryName(getString(json, "queryName"));
pdf.setDescription(getString(json, "description"));
String cardinality = getString(json, "cardinality");
if(cardinality != null){
pdf.setCardinality(Cardinality.fromValue(cardinality));
}
String updatability = getString(json, "updatability");
if(updatability != null){
pdf.setUpdatability(Updatability.fromValue(updatability));
}
pdf.setIsInherited(getBoolean(json, "inherited"));
pdf.setIsRequired(getBoolean(json, "required"));
pdf.setIsQueryable(getBoolean(json, "queryable"));
pdf.setIsOrderable(getBoolean(json, "orderable"));
pdf.setIsOpenChoice(getBoolean(json, "openChoice"));
//TODO defaultValues, choices
}
private static PropertyDefinition<?> parseBooleanProperty(JsonNode json){
PropertyBooleanDefinitionImpl pdf = new PropertyBooleanDefinitionImpl();
pdf.setPropertyType(PropertyType.BOOLEAN);
setDefaultValue(pdf, json);
parseCommon(pdf, json);
return pdf;
}
private static PropertyDefinition<?> parseDateTimeProperty(JsonNode json){
PropertyDateTimeDefinitionImpl pdf = new PropertyDateTimeDefinitionImpl();
pdf.setPropertyType(PropertyType.DATETIME);
setDefaultValue(pdf, json);
if(json.get("dateTimeResolution") != null){
String resolution = json.get("dateTimeResolution").textValue();
pdf.setDateTimeResolution(DateTimeResolution.fromValue(resolution));
}
parseCommon(pdf, json);
return pdf;
}
private static PropertyDefinition<?> parseDecimalProperty(JsonNode json){
PropertyDecimalDefinitionImpl pdf = new PropertyDecimalDefinitionImpl();
pdf.setPropertyType(PropertyType.DECIMAL);
setDefaultValue(pdf, json);
pdf.setMaxValue(parseBigDecimal(json, "maxValue"));
pdf.setMinValue(parseBigDecimal(json, "minValue"));
parseCommon(pdf, json);
return pdf;
}
private static PropertyDefinition<?> parseHtmlProperty(JsonNode json){
PropertyHtmlDefinitionImpl pdf = new PropertyHtmlDefinitionImpl();
pdf.setPropertyType(PropertyType.HTML);
setDefaultValue(pdf, json);
parseCommon(pdf, json);
return pdf;
}
private static PropertyDefinition<?> parseIdProperty(JsonNode json){
PropertyIdDefinitionImpl pdf = new PropertyIdDefinitionImpl();
pdf.setPropertyType(PropertyType.ID);
setDefaultValue(pdf, json);
parseCommon(pdf, json);
return pdf;
}
private static PropertyDefinition<?> parseIntegerProperty(JsonNode json){
PropertyIntegerDefinitionImpl pdf = new PropertyIntegerDefinitionImpl();
pdf.setPropertyType(PropertyType.INTEGER);
setDefaultValue(pdf, json);
pdf.setMaxValue(parseBigInteger(json, "maxValue"));
pdf.setMinValue(parseBigInteger(json, "minValue"));
parseCommon(pdf, json);
return pdf;
}
private static PropertyDefinition<?> parseStringProperty(JsonNode json){
PropertyStringDefinitionImpl pdf = new PropertyStringDefinitionImpl();
pdf.setPropertyType(PropertyType.STRING);
setDefaultValue(pdf, json);
pdf.setMaxLength(parseBigInteger(json, "maxLength"));
parseCommon(pdf, json);
return pdf;
}
private static PropertyDefinition<?> parseUriProperty(JsonNode json){
PropertyUriDefinitionImpl pdf = new PropertyUriDefinitionImpl();
pdf.setPropertyType(PropertyType.URI);
setDefaultValue(pdf, json);
parseCommon(pdf, json);
return pdf;
}
private static BigInteger parseBigInteger(JsonNode json, String key){
JsonNode node = json.get(key);
if(node == null){
return null;
}else{
String str = node.textValue();
try{
BigInteger result = BigInteger.valueOf(Long.valueOf(str));
return result;
}catch(Exception e){
//TODO logging
e.printStackTrace();
return null;
}
}
}
private static BigDecimal parseBigDecimal(JsonNode json, String key){
JsonNode node = json.get(key);
if(node == null){
return null;
}else{
String str = node.textValue();
try{
BigDecimal result = BigDecimal.valueOf(Long.valueOf(str));
return result;
}catch(Exception e){
//TODO logging
e.printStackTrace();
return null;
}
}
}
private static String getString(JsonNode json, String key){
JsonNode node = json.get(key);
if(node == null){
return null;
}else{
return node.textValue();
}
}
private static Boolean getBoolean(JsonNode json, String key){
JsonNode node = json.get(key);
if(node == null){
return null;
}else{
return node.asBoolean();
}
}
private static void setDefaultValue(AbstractPropertyDefinition<?> pdf, JsonNode json){
JsonNode defaultValue = json.get("defaultValue");
if(defaultValue != null && defaultValue.isArray()){
Iterator<JsonNode> itr = defaultValue.iterator();
if(pdf instanceof PropertyIdDefinitionImpl){
if(((PropertyIdDefinitionImpl)pdf).getDefaultValue() == null){
((PropertyIdDefinitionImpl)pdf).setDefaultValue(new ArrayList<String>());
}
while(itr.hasNext()){
((PropertyIdDefinitionImpl)pdf).getDefaultValue().add(itr.next().asText());
}
}else if(pdf instanceof PropertyHtmlDefinitionImpl){
if(((PropertyHtmlDefinitionImpl)pdf).getDefaultValue() == null){
((PropertyHtmlDefinitionImpl)pdf).setDefaultValue(new ArrayList<String>());
}
while(itr.hasNext()){
((PropertyHtmlDefinitionImpl)pdf).getDefaultValue().add(itr.next().asText());
}
}else if(pdf instanceof PropertyUriDefinitionImpl){
if(((PropertyUriDefinitionImpl)pdf).getDefaultValue() == null){
((PropertyUriDefinitionImpl)pdf).setDefaultValue(new ArrayList<String>());
}
while(itr.hasNext()){
((PropertyUriDefinitionImpl)pdf).getDefaultValue().add(itr.next().asText());
}
}else if(pdf instanceof PropertyStringDefinitionImpl){
if(((PropertyStringDefinitionImpl)pdf).getDefaultValue() == null){
((PropertyStringDefinitionImpl)pdf).setDefaultValue(new ArrayList<String>());
}
while(itr.hasNext()){
((PropertyStringDefinitionImpl)pdf).getDefaultValue().add(itr.next().asText());
}
}else if(pdf instanceof PropertyBooleanDefinitionImpl){
if(((PropertyBooleanDefinitionImpl)pdf).getDefaultValue() == null){
((PropertyBooleanDefinitionImpl)pdf).setDefaultValue(new ArrayList<Boolean>());
}
while(itr.hasNext()){
((PropertyBooleanDefinitionImpl)pdf).getDefaultValue().add(itr.next().asBoolean());
}
}else if(pdf instanceof PropertyDateTimeDefinitionImpl){
if(((PropertyDateTimeDefinitionImpl)pdf).getDefaultValue() == null){
((PropertyDateTimeDefinitionImpl)pdf).setDefaultValue(new ArrayList<GregorianCalendar>());
}
while(itr.hasNext()){
String str = itr.next().textValue();
//TODO other locale, other formats
SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss", Locale.JAPAN);
Date d;
try {
d = sdf.parse(str);
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(d);
((PropertyDateTimeDefinitionImpl)pdf).getDefaultValue().add(cal);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}else if(pdf instanceof PropertyIntegerDefinitionImpl){
if(((PropertyIntegerDefinitionImpl)pdf).getDefaultValue() == null){
((PropertyIntegerDefinitionImpl)pdf).setDefaultValue(new ArrayList<BigInteger>());
}
while(itr.hasNext()){
Long i = itr.next().asLong();
BigInteger bi = BigInteger.valueOf(i);
((PropertyIntegerDefinitionImpl)pdf).getDefaultValue().add(bi);
}
}else if(pdf instanceof PropertyDecimalDefinitionImpl){
if(((PropertyDecimalDefinitionImpl)pdf).getDefaultValue() == null){
((PropertyDecimalDefinitionImpl)pdf).setDefaultValue(new ArrayList<BigDecimal>());
}
while(itr.hasNext()){
Double d = itr.next().asDouble();
BigDecimal bd = BigDecimal.valueOf(d);
((PropertyDecimalDefinitionImpl)pdf).getDefaultValue().add(bd);
}
}
}
}
}