package org.molgenis.data.rest.v2;
import org.molgenis.data.*;
import org.molgenis.data.aggregation.AggregateQuery;
import org.molgenis.data.aggregation.AggregateResult;
import org.molgenis.data.i18n.LanguageService;
import org.molgenis.data.meta.AttributeType;
import org.molgenis.data.meta.NameValidator;
import org.molgenis.data.meta.model.Attribute;
import org.molgenis.data.meta.model.EntityType;
import org.molgenis.data.meta.model.Package;
import org.molgenis.data.rest.EntityPager;
import org.molgenis.data.rest.service.RestService;
import org.molgenis.data.support.EntityTypeUtils;
import org.molgenis.data.support.Href;
import org.molgenis.data.support.QueryImpl;
import org.molgenis.data.support.RepositoryCopier;
import org.molgenis.security.core.MolgenisPermissionService;
import org.molgenis.security.core.Permission;
import org.molgenis.security.core.runas.RunAsSystemProxy;
import org.molgenis.security.permission.PermissionSystemService;
import org.molgenis.util.ErrorMessageResponse;
import org.molgenis.util.ErrorMessageResponse.ErrorMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.convert.ConversionFailedException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriComponentsBuilder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.google.common.collect.Lists.transform;
import static java.util.Objects.requireNonNull;
import static org.molgenis.data.meta.model.AttributeMetadata.ATTRIBUTE_META_DATA;
import static org.molgenis.data.rest.v2.AttributeFilterToFetchConverter.createDefaultAttributeFetch;
import static org.molgenis.data.rest.v2.RestControllerV2.BASE_URI;
import static org.molgenis.util.EntityUtils.getTypedValue;
import static org.molgenis.util.MolgenisDateFormat.getDateFormat;
import static org.molgenis.util.MolgenisDateFormat.getDateTimeFormat;
import static org.springframework.http.HttpStatus.*;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.web.bind.annotation.RequestMethod.*;
@Controller
@RequestMapping(BASE_URI)
class RestControllerV2
{
private static final Logger LOG = LoggerFactory.getLogger(RestControllerV2.class);
static final int MAX_ENTITIES = 1000;
public static final String BASE_URI = "/api/v2";
private final DataService dataService;
private final RestService restService;
private final MolgenisPermissionService permissionService;
private final PermissionSystemService permissionSystemService;
private final LanguageService languageService;
private final RepositoryCopier repoCopier;
static UnknownEntityException createUnknownEntityException(String entityName)
{
return new UnknownEntityException("Operation failed. Unknown entity: '" + entityName + "'");
}
static MolgenisDataAccessException createNoReadPermissionOnEntityException(String entityName)
{
return new MolgenisDataAccessException("No read permission on entity " + entityName);
}
static MolgenisDataException createNoWriteCapabilitiesOnEntityException(String entityName)
{
return new MolgenisRepositoryCapabilitiesException("No write capabilities for entity " + entityName);
}
static DuplicateEntityException createDuplicateEntityException(String entityName)
{
return new DuplicateEntityException("Operation failed. Duplicate entity: '" + entityName + "'");
}
static UnknownAttributeException createUnknownAttributeException(String entityName, String attributeName)
{
return new UnknownAttributeException(
"Operation failed. Unknown attribute: '" + attributeName + "', of entity: '" + entityName + "'");
}
static MolgenisDataAccessException createMolgenisDataAccessExceptionReadOnlyAttribute(String entityName,
String attributeName)
{
return new MolgenisDataAccessException(
"Operation failed. Attribute '" + attributeName + "' of entity '" + entityName + "' is readonly");
}
static MolgenisDataException createMolgenisDataExceptionUnknownIdentifier(int count)
{
return new MolgenisDataException("Operation failed. Unknown identifier on index " + count);
}
static MolgenisDataException createMolgenisDataExceptionIdentifierAndValue()
{
return new MolgenisDataException("Operation failed. Entities must provide only an identifier and a value");
}
static UnknownEntityException createUnknownEntityExceptionNotValidId(Object id)
{
return new UnknownEntityException(
"The entity you are trying to update [" + id.toString() + "] does not exist.");
}
@Autowired
public RestControllerV2(DataService dataService, MolgenisPermissionService permissionService,
RestService restService, LanguageService languageService, PermissionSystemService permissionSystemService,
RepositoryCopier repoCopier)
{
this.dataService = requireNonNull(dataService);
this.permissionService = requireNonNull(permissionService);
this.restService = requireNonNull(restService);
this.languageService = requireNonNull(languageService);
this.permissionSystemService = requireNonNull(permissionSystemService);
this.repoCopier = requireNonNull(repoCopier);
}
@Autowired
@RequestMapping(value = "/version", method = GET)
@ResponseBody
public Map<String, String> getVersion(@Value("${molgenis.version:@null}") String molgenisVersion,
@Value("${molgenis.build.date:@null}") String molgenisBuildDate)
{
if (molgenisVersion == null) throw new IllegalArgumentException("molgenisVersion is null");
if (molgenisBuildDate == null) throw new IllegalArgumentException("molgenisBuildDate is null");
molgenisBuildDate = molgenisBuildDate.equals("${maven.build.timestamp}") ?
new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new java.util.Date())
+ " by IntelliJ" : molgenisBuildDate;
Map<String, String> result = new HashMap<>();
result.put("molgenisVersion", molgenisVersion);
result.put("buildDate", molgenisBuildDate);
return result;
}
/**
* Retrieve an entity instance by id, optionally specify which attributes to include in the response.
*
* @param entityName
* @param untypedId
* @param attributeFilter
* @return
*/
@RequestMapping(value = "/{entityName}/{id:.+}", method = GET)
@ResponseBody
public Map<String, Object> retrieveEntity(@PathVariable("entityName") String entityName,
@PathVariable("id") String untypedId,
@RequestParam(value = "attrs", required = false) AttributeFilter attributeFilter)
{
return getEntityResponse(entityName, untypedId, attributeFilter);
}
/**
* Tunnel retrieveEntity through a POST request
*
* @param entityName
* @param untypedId
* @param attributeFilter
* @return
*/
@RequestMapping(value = "/{entityName}/{id:.+}", method = POST, params = "_method=GET")
@ResponseBody
public Map<String, Object> retrieveEntityPost(@PathVariable("entityName") String entityName,
@PathVariable("id") String untypedId,
@RequestParam(value = "attrs", required = false) AttributeFilter attributeFilter)
{
return getEntityResponse(entityName, untypedId, attributeFilter);
}
private Map<String, Object> getEntityResponse(String entityName, String untypedId, AttributeFilter attributeFilter)
{
EntityType entityType = dataService.getEntityType(entityName);
Object id = getTypedValue(untypedId, entityType.getIdAttribute());
Fetch fetch = AttributeFilterToFetchConverter
.convert(attributeFilter, entityType, languageService.getCurrentUserLanguageCode());
Entity entity = dataService.findOneById(entityName, id, fetch);
if (entity == null)
{
throw new UnknownEntityException(entityName + " [" + untypedId + "] not found");
}
return createEntityResponse(entity, fetch, true);
}
@RequestMapping(value = "/{entityName}/{id:.+}", method = DELETE)
@ResponseStatus(NO_CONTENT)
public void deleteEntity(@PathVariable("entityName") String entityName, @PathVariable("id") String untypedId)
{
EntityType entityType = dataService.getEntityType(entityName);
Object id = getTypedValue(untypedId, entityType.getIdAttribute());
if (ATTRIBUTE_META_DATA.equals(entityName))
{
dataService.getMeta().deleteAttributeById(id);
}
else
{
dataService.deleteById(entityName, id);
}
}
/**
* Retrieve an entity collection, optionally specify which attributes to include in the response.
*
* @param entityName
* @param request
* @param httpRequest
* @return
*/
@RequestMapping(value = "/{entityName}", method = GET)
@ResponseBody
public EntityCollectionResponseV2 retrieveEntityCollection(@PathVariable("entityName") String entityName,
@Valid EntityCollectionRequestV2 request, HttpServletRequest httpRequest)
{
return createEntityCollectionResponse(entityName, request, httpRequest);
}
@RequestMapping(value = "/{entityName}", method = POST, params = "_method=GET")
@ResponseBody
public EntityCollectionResponseV2 retrieveEntityCollectionPost(@PathVariable("entityName") String entityName,
@Valid EntityCollectionRequestV2 request, HttpServletRequest httpRequest)
{
return createEntityCollectionResponse(entityName, request, httpRequest);
}
/**
* Retrieve attribute meta data
*
* @param entityName
* @param attributeName
* @return
*/
@RequestMapping(value = "/{entityName}/meta/{attributeName}", method = GET, produces = APPLICATION_JSON_VALUE)
@ResponseBody
public AttributeResponseV2 retrieveEntityAttributeMeta(@PathVariable("entityName") String entityName,
@PathVariable("attributeName") String attributeName)
{
return createAttributeResponse(entityName, attributeName);
}
@RequestMapping(value = "/{entityName}/meta/{attributeName}", method = POST, params = "_method=GET", produces = APPLICATION_JSON_VALUE)
@ResponseBody
public AttributeResponseV2 retrieveEntityAttributeMetaPost(@PathVariable("entityName") String entityName,
@PathVariable("attributeName") String attributeName)
{
return createAttributeResponse(entityName, attributeName);
}
/**
* Try to create multiple entities in one transaction. If one fails all fails.
*
* @param entityName name of the entity where the entities are going to be added.
* @param request EntityCollectionCreateRequestV2
* @param response HttpServletResponse
* @return EntityCollectionCreateResponseBodyV2
* @throws Exception
*/
@RequestMapping(value = "/{entityName}", method = POST, produces = APPLICATION_JSON_VALUE)
@ResponseBody
public EntityCollectionBatchCreateResponseBodyV2 createEntities(@PathVariable("entityName") String entityName,
@RequestBody @Valid EntityCollectionBatchRequestV2 request, HttpServletResponse response) throws Exception
{
final EntityType meta = dataService.getEntityType(entityName);
if (meta == null)
{
throw createUnknownEntityException(entityName);
}
try
{
final List<Entity> entities = request.getEntities().stream().map(e -> this.restService.toEntity(meta, e))
.collect(Collectors.toList());
final EntityCollectionBatchCreateResponseBodyV2 responseBody = new EntityCollectionBatchCreateResponseBodyV2();
final List<String> ids = new ArrayList<String>();
// Add all entities
if (ATTRIBUTE_META_DATA.equals(entityName))
{
this.dataService.getMeta().addAttributes(entityName, entities.stream().map(a -> (Attribute) a));
}
else
{
this.dataService.add(entityName, entities.stream());
}
entities.forEach(entity ->
{
restService.updateMappedByEntities(entity);
String id = entity.getIdValue().toString();
ids.add(id.toString());
responseBody.getResources().add(new AutoValue_ResourcesResponseV2(
Href.concatEntityHref(RestControllerV2.BASE_URI, entityName, id)));
});
responseBody.setLocation(Href.concatEntityCollectionHref(RestControllerV2.BASE_URI, entityName,
meta.getIdAttribute().getName(), ids));
response.setStatus(HttpServletResponse.SC_CREATED);
return responseBody;
}
catch (Exception e)
{
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
throw e;
}
}
/**
* Copy an entity.
*
* @param entityName name of the entity that will be copied.
* @param request CopyEntityRequestV2
* @param response HttpServletResponse
* @return String name of the new entity
* @throws Exception
*/
@RequestMapping(value = "copy/{entityName}", method = POST, produces = APPLICATION_JSON_VALUE)
@ResponseBody
public String copyEntity(@PathVariable("entityName") String entityName,
@RequestBody @Valid CopyEntityRequestV2 request, HttpServletResponse response) throws Exception
{
// No repo
if (!dataService.hasRepository(entityName)) throw createUnknownEntityException(entityName);
Repository<Entity> repositoryToCopyFrom = dataService.getRepository(entityName);
// Validate the new name
NameValidator.validateName(request.getNewEntityName());
// Check if the entity already exists
String newFullName = EntityTypeUtils
.buildFullName(repositoryToCopyFrom.getEntityType().getPackage(), request.getNewEntityName());
if (dataService.hasRepository(newFullName)) throw createDuplicateEntityException(newFullName);
// Permission
boolean readPermission = permissionService
.hasPermissionOnEntity(repositoryToCopyFrom.getName(), Permission.READ);
if (!readPermission) throw createNoReadPermissionOnEntityException(entityName);
// Capabilities
boolean writableCapabilities = dataService.getCapabilities(repositoryToCopyFrom.getName())
.contains(RepositoryCapability.WRITABLE);
if (!writableCapabilities) throw createNoWriteCapabilitiesOnEntityException(entityName);
// Copy
this.copyRepositoryRunAsSystem(repositoryToCopyFrom, request.getNewEntityName(),
repositoryToCopyFrom.getEntityType().getPackage(), request.getNewEntityName());
// Retrieve new repo
Repository<Entity> repository = dataService.getRepository(newFullName);
permissionSystemService.giveUserEntityPermissions(SecurityContextHolder.getContext(),
Collections.singletonList(repository.getName()));
response.addHeader("Location", Href.concatMetaEntityHrefV2(RestControllerV2.BASE_URI, repository.getName()));
response.setStatus(HttpServletResponse.SC_CREATED);
return repository.getName();
}
private void copyRepositoryRunAsSystem(Repository<Entity> repositoryToCopyFrom, String simpleName, Package pack,
String label)
{
RunAsSystemProxy.runAsSystem(() -> repoCopier.copyRepository(repositoryToCopyFrom, simpleName, pack, label));
}
/**
* Try to update multiple entities in one transaction. If one fails all fails.
*
* @param entityName name of the entity where the entities are going to be added.
* @param request EntityCollectionCreateRequestV2
* @param response HttpServletResponse
* @throws Exception
*/
@RequestMapping(value = "/{entityName}", method = PUT)
public synchronized void updateEntities(@PathVariable("entityName") String entityName,
@RequestBody @Valid EntityCollectionBatchRequestV2 request, HttpServletResponse response) throws Exception
{
final EntityType meta = dataService.getEntityType(entityName);
if (meta == null)
{
throw createUnknownEntityException(entityName);
}
try
{
final Stream<Entity> entities = request.getEntities().stream().map(e -> this.restService.toEntity(meta, e));
// update all entities
this.dataService.update(entityName, entities);
entities.forEach(entity -> restService
.updateMappedByEntities(entity, dataService.findOneById(entityName, entity.getIdValue())));
response.setStatus(HttpServletResponse.SC_OK);
}
catch (Exception e)
{
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
throw e;
}
}
/**
* @param entityName The name of the entity to update
* @param attributeName The name of the attribute to update
* @param request EntityCollectionBatchRequestV2
* @param response HttpServletResponse
* @throws Exception
*/
@RequestMapping(value = "/{entityName}/{attributeName}", method = PUT)
@ResponseStatus(OK)
public synchronized void updateAttribute(@PathVariable("entityName") String entityName,
@PathVariable("attributeName") String attributeName,
@RequestBody @Valid EntityCollectionBatchRequestV2 request, HttpServletResponse response) throws Exception
{
final EntityType meta = dataService.getEntityType(entityName);
if (meta == null)
{
throw createUnknownEntityException(entityName);
}
try
{
Attribute attr = meta.getAttribute(attributeName);
if (attr == null)
{
throw createUnknownAttributeException(entityName, attributeName);
}
if (attr.isReadOnly())
{
throw createMolgenisDataAccessExceptionReadOnlyAttribute(entityName, attributeName);
}
final List<Entity> entities = request.getEntities().stream().filter(e -> e.size() == 2)
.map(e -> this.restService.toEntity(meta, e)).collect(Collectors.toList());
if (entities.size() != request.getEntities().size())
{
throw createMolgenisDataExceptionIdentifierAndValue();
}
final List<Entity> updatedEntities = new ArrayList<Entity>();
int count = 0;
for (Entity entity : entities)
{
Object id = checkForEntityId(entity, count);
Entity originalEntity = dataService.findOneById(entityName, id);
if (originalEntity == null)
{
throw createUnknownEntityExceptionNotValidId(id);
}
Object value = this.restService.toEntityValue(attr, entity.get(attributeName));
originalEntity.set(attributeName, value);
updatedEntities.add(originalEntity);
count++;
}
// update all entities
this.dataService.update(entityName, updatedEntities.stream());
response.setStatus(HttpServletResponse.SC_OK);
}
catch (Exception e)
{
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
throw e;
}
}
/**
* Get the i18n resource strings in the language of the current user
*/
@RequestMapping(value = "/i18n", method = GET, produces = APPLICATION_JSON_VALUE)
@ResponseBody
public Map<String, String> getI18nStrings()
{
Map<String, String> translations = new HashMap<>();
ResourceBundle bundle = languageService.getBundle();
for (String key : bundle.keySet())
{
translations.put(key, bundle.getString(key));
}
return translations;
}
/**
* Get entity id and perform a check, throwing an MolgenisDataException when necessary
*
* @param entity
* @param count
* @return
*/
private static Object checkForEntityId(Entity entity, int count)
{
Object id = entity.getIdValue();
if (null == id)
{
throw createMolgenisDataExceptionUnknownIdentifier(count);
}
return id;
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(BAD_REQUEST)
public
@ResponseBody
ErrorMessageResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException exception)
{
LOG.info("Invalid method arguments.", exception);
return new ErrorMessageResponse(transform(exception.getBindingResult().getFieldErrors(),
error -> new ErrorMessage(error.getDefaultMessage())));
}
@ExceptionHandler(MolgenisDataException.class)
@ResponseStatus(BAD_REQUEST)
@ResponseBody
public ErrorMessageResponse handleMolgenisDataException(MolgenisDataException e)
{
LOG.info("Operation failed.", e);
return new ErrorMessageResponse(new ErrorMessage(e.getMessage()));
}
@ExceptionHandler(MolgenisDataAccessException.class)
@ResponseStatus(UNAUTHORIZED)
@ResponseBody
public ErrorMessageResponse handleMolgenisDataAccessException(MolgenisDataAccessException e)
{
LOG.debug("Data access exception occurred.", e);
return new ErrorMessageResponse(new ErrorMessage(e.getMessage()));
}
@ExceptionHandler(RuntimeException.class)
@ResponseStatus(INTERNAL_SERVER_ERROR)
@ResponseBody
public ErrorMessageResponse handleRuntimeException(RuntimeException e)
{
LOG.error("Runtime exception occurred.", e);
return new ErrorMessageResponse(new ErrorMessage(e.getMessage()));
}
@ExceptionHandler(ConversionFailedException.class)
@ResponseStatus(BAD_REQUEST)
@ResponseBody
public ErrorMessageResponse handleConversionFailedException(ConversionFailedException e)
{
LOG.info("ConversionFailedException occurred", e);
return new ErrorMessageResponse(new ErrorMessage(e.getMessage()));
}
private AttributeResponseV2 createAttributeResponse(String entityName, String attributeName)
{
EntityType entity = dataService.getEntityType(entityName);
if (entity == null)
{
throw new UnknownEntityException(entityName + " not found");
}
Attribute attribute = entity.getAttribute(attributeName);
if (attribute == null)
{
throw new RuntimeException("attribute : " + attributeName + " does not exist!");
}
return new AttributeResponseV2(entityName, entity, attribute, null, permissionService, dataService,
languageService);
}
private EntityCollectionResponseV2 createEntityCollectionResponse(String entityName,
EntityCollectionRequestV2 request, HttpServletRequest httpRequest)
{
EntityType meta = dataService.getEntityType(entityName);
Query<Entity> q = request.getQ() != null ? request.getQ().createQuery(meta) : new QueryImpl<>();
q.pageSize(request.getNum()).offset(request.getStart()).sort(request.getSort());
Fetch fetch = AttributeFilterToFetchConverter
.convert(request.getAttrs(), meta, languageService.getCurrentUserLanguageCode());
if (fetch != null)
{
q.fetch(fetch);
}
if (request.getAggs() != null)
{
// return aggregates for aggregate query
AggregateQuery aggsQ = request.getAggs().createAggregateQuery(meta, q);
Attribute xAttr = aggsQ.getAttributeX();
Attribute yAttr = aggsQ.getAttributeY();
if (xAttr == null && yAttr == null)
{
throw new MolgenisQueryException("Aggregate query is missing 'x' or 'y' attribute");
}
AggregateResult aggs = dataService.aggregate(entityName, aggsQ);
AttributeResponseV2 xAttrResponse =
xAttr != null ? new AttributeResponseV2(entityName, meta, xAttr, fetch, permissionService,
dataService, languageService) : null;
AttributeResponseV2 yAttrResponse =
yAttr != null ? new AttributeResponseV2(entityName, meta, yAttr, fetch, permissionService,
dataService, languageService) : null;
return new EntityAggregatesResponse(aggs, xAttrResponse, yAttrResponse, BASE_URI + '/' + entityName);
}
else
{
Long count = dataService.count(entityName, q);
Iterable<Entity> it;
if (count > 0)
{
it = () -> dataService.findAll(entityName, q).iterator();
}
else
{
it = Collections.emptyList();
}
EntityPager pager = new EntityPager(request.getStart(), request.getNum(), count, it);
List<Map<String, Object>> entities = new ArrayList<>();
for (Entity entity : it)
{
Map<String, Object> responseData = new LinkedHashMap<String, Object>();
createEntityValuesResponse(entity, fetch, responseData);
entities.add(responseData);
}
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(getFullURL(httpRequest));
String prevHref = null;
if (pager.getPrevStart() != null)
{
builder.replaceQueryParam("start", pager.getPrevStart());
prevHref = builder.build(false).toUriString();
}
String nextHref = null;
if (pager.getNextStart() != null)
{
builder.replaceQueryParam("start", pager.getNextStart());
nextHref = builder.build(false).toUriString();
}
return new EntityCollectionResponseV2(pager, entities, fetch, BASE_URI + '/' + entityName, meta,
permissionService, dataService, languageService, prevHref, nextHref);
}
}
private String getFullURL(HttpServletRequest request)
{
StringBuffer requestURL = request.getRequestURL();
String queryString = request.getQueryString();
if (queryString == null)
{
return requestURL.toString();
}
else
{
return requestURL.append('?').append(queryString).toString();
}
}
private Map<String, Object> createEntityResponse(Entity entity, Fetch fetch, boolean includeMetaData)
{
Map<String, Object> responseData = new LinkedHashMap<String, Object>();
if (includeMetaData)
{
createEntityTypeResponse(entity.getEntityType(), fetch, responseData);
}
createEntityValuesResponse(entity, fetch, responseData);
return responseData;
}
private void createEntityTypeResponse(EntityType entityType, Fetch fetch, Map<String, Object> responseData)
{
responseData.put("_meta",
new EntityTypeResponseV2(entityType, fetch, permissionService, dataService, languageService));
}
private void createEntityValuesResponse(Entity entity, Fetch fetch, Map<String, Object> responseData)
{
Iterable<Attribute> attrs = entity.getEntityType().getAtomicAttributes();
createEntityValuesResponseRec(entity, attrs, fetch, responseData);
}
private void createEntityValuesResponseRec(Entity entity, Iterable<Attribute> attrs, Fetch fetch,
Map<String, Object> responseData)
{
responseData
.put("_href", Href.concatEntityHref(BASE_URI, entity.getEntityType().getName(), entity.getIdValue()));
for (Attribute attr : attrs) // TODO performance use fetch instead of attrs
{
String attrName = attr.getName();
if (fetch == null || fetch.hasField(attr))
{
AttributeType dataType = attr.getDataType();
switch (dataType)
{
case BOOL:
responseData.put(attrName, entity.getBoolean(attrName));
break;
case CATEGORICAL:
case XREF:
case FILE:
Entity refEntity = entity.getEntity(attrName);
Map<String, Object> refEntityResponse;
if (refEntity != null)
{
Fetch refAttrFetch =
fetch != null ? fetch.getFetch(attr) : createDefaultAttributeFetch(attr,
languageService.getCurrentUserLanguageCode());
;
refEntityResponse = createEntityResponse(refEntity, refAttrFetch, false);
}
else
{
refEntityResponse = null;
}
responseData.put(attrName, refEntityResponse);
break;
case CATEGORICAL_MREF:
case MREF:
case ONE_TO_MANY:
Iterable<Entity> refEntities = entity.getEntities(attrName);
List<Map<String, Object>> refEntityResponses;
if (refEntities != null)
{
refEntityResponses = new ArrayList<Map<String, Object>>();
Fetch refAttrFetch =
fetch != null ? fetch.getFetch(attrName) : createDefaultAttributeFetch(attr,
languageService.getCurrentUserLanguageCode());
;
for (Entity refEntitiesEntity : refEntities)
{
refEntityResponses.add(createEntityResponse(refEntitiesEntity, refAttrFetch, false));
}
}
else
{
refEntityResponses = null;
}
responseData.put(attrName, refEntityResponses);
break;
case COMPOUND:
throw new RuntimeException("Invalid data type [" + dataType + "]");
case DATE:
Date dateValue = entity.getUtilDate(attrName);
String dateValueStr = dateValue != null ? getDateFormat().format(dateValue) : null;
responseData.put(attrName, dateValueStr);
break;
case DATE_TIME:
Date dateTimeValue = entity.getUtilDate(attrName);
String dateTimeValueStr =
dateTimeValue != null ? getDateTimeFormat().format(dateTimeValue) : null;
responseData.put(attrName, dateTimeValueStr);
break;
case DECIMAL:
responseData.put(attrName, entity.getDouble(attrName));
break;
case EMAIL:
case ENUM:
case HTML:
case HYPERLINK:
case SCRIPT:
case STRING:
case TEXT:
responseData.put(attrName, entity.getString(attrName));
break;
case INT:
responseData.put(attrName, entity.getInt(attrName));
break;
case LONG:
responseData.put(attrName, entity.getLong(attrName));
break;
default:
throw new RuntimeException("Unknown data type [" + dataType + "]");
}
}
}
}
}