package org.odata4j.test.integration.producer.custom;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.ws.rs.core.HttpHeaders;
import org.odata4j.core.OCollection.Builder;
import org.odata4j.core.OCollections;
import org.odata4j.core.OComplexObject;
import org.odata4j.core.OComplexObjects;
import org.odata4j.core.OEntities;
import org.odata4j.core.OEntity;
import org.odata4j.core.OEntityId;
import org.odata4j.core.OEntityKey;
import org.odata4j.core.OExtension;
import org.odata4j.core.OFunctionParameter;
import org.odata4j.core.OLink;
import org.odata4j.core.OLinks;
import org.odata4j.core.OObject;
import org.odata4j.core.OProperties;
import org.odata4j.core.OProperty;
import org.odata4j.core.OSimpleObjects;
import org.odata4j.edm.EdmCollectionType;
import org.odata4j.edm.EdmComplexType;
import org.odata4j.edm.EdmDataServices;
import org.odata4j.edm.EdmEntitySet;
import org.odata4j.edm.EdmFunctionImport;
import org.odata4j.edm.EdmProperty.CollectionKind;
import org.odata4j.edm.EdmSimpleType;
import org.odata4j.exceptions.BadRequestException;
import org.odata4j.exceptions.NotFoundException;
import org.odata4j.exceptions.NotImplementedException;
import org.odata4j.producer.BaseResponse;
import org.odata4j.producer.ContextStream;
import org.odata4j.producer.CountResponse;
import org.odata4j.producer.EntitiesResponse;
import org.odata4j.producer.EntityIdResponse;
import org.odata4j.producer.EntityQueryInfo;
import org.odata4j.producer.EntityResponse;
import org.odata4j.producer.ODataContext;
import org.odata4j.producer.ODataProducer;
import org.odata4j.producer.OMediaLinkExtension;
import org.odata4j.producer.OMediaLinkExtensions;
import org.odata4j.producer.PropertyPathHelper;
import org.odata4j.producer.QueryInfo;
import org.odata4j.producer.Responses;
import org.odata4j.producer.edm.MetadataProducer;
/**
* A custom producer for various test scenarios that aren't possible with
* stock producers
*/
public class CustomProducer implements ODataProducer {
private final EdmDataServices edm = new CustomEdm().generateEdm(null).build();
private final MetadataProducer metadataProducer;
public CustomProducer() {
this.metadataProducer = new MetadataProducer(this, null);
this.initResources();
}
@Override
public EdmDataServices getMetadata() {
return edm;
}
@Override
public MetadataProducer getMetadataProducer() {
return metadataProducer;
}
@Override
public EntitiesResponse getEntities(ODataContext context, String entitySetName, QueryInfo queryInfo) {
if (entitySetName.equals("Type1s")) {
return Responses.entities(getType1s(), edm.findEdmEntitySet(entitySetName), null, null);
} else if (entitySetName.equals("FileSystemItems")) {
return Responses.entities(getFileSystemItems(queryInfo), edm.findEdmEntitySet(entitySetName), null, null);
} else if (entitySetName.equals("Directories")) {
return Responses.entities(getDirectories(queryInfo), edm.findEdmEntitySet(entitySetName), null, null);
} else if (entitySetName.equals("Files")) {
return Responses.entities(getFiles(queryInfo), edm.findEdmEntitySet(entitySetName), null, null);
} else {
throw new NotFoundException("Unknown entity set: " + entitySetName);
}
}
@Override
public CountResponse getEntitiesCount(ODataContext context, String entitySetName, QueryInfo queryInfo) {
throw new NotImplementedException();
}
private int nDirs = 5;
private Map<String, OEntity> dirs = new HashMap<String, OEntity>();
private List<OEntity> getDirectories(QueryInfo queryInfo) {
LinkedList<OEntity> l = new LinkedList<OEntity>();
for (int i = 0; i < nDirs; i++) {
getDirectory(i, queryInfo);
}
l.addAll(dirs.values());
return l;
}
@Override
public CountResponse getNavPropertyCount(ODataContext context, String entitySetName, OEntityKey entityKey, String navProp, QueryInfo queryInfo) {
throw new NotImplementedException();
}
private boolean isExpanded(String navprop, QueryInfo q) {
if (q == null || q.expand == null) {
return false;
}
PropertyPathHelper h = new PropertyPathHelper(q.select, q.expand);
return h.isExpanded(navprop);
}
private OEntity getDirectory(int n, QueryInfo queryInfo) {
String name = "Dir-" + Integer.toString(n);
List<OProperty<?>> props = new ArrayList<OProperty<?>>(2);
props.add(OProperties.string("Name", name));
props.add(OProperties.string("DirProp1", name + "-DirProp1Value"));
List<OLink> links = new ArrayList<OLink>();
List<OEntity> items = null;
if (isExpanded("Items", queryInfo)) {
items = getFiles(name, queryInfo);
int subdir = n * 2 + 1;
items.add(getDirectory(subdir, null));
items.add(getDirectory(subdir + 1, null));
links.add(OLinks.relatedEntitiesInline("Items", "Items", null, items));
} else {
links.add(OLinks.relatedEntities("Items", "Items", null));
}
if (isExpanded("NewestItem", queryInfo)) {
links.add(OLinks.relatedEntityInline("NewestItem", "NewestItem", null, items.get(0)));
} else {
links.add(OLinks.relatedEntity("NewestItem", "NewestItem", null));
}
OEntity e = OEntities.create(
edm.findEdmEntitySet("Directories"),
OEntityKey.create("Name", name),
props,
links == null ? new ArrayList<OLink>() : links);
dirs.put(name, e);
return e;
}
private List<OEntity> getFileSystemItems(QueryInfo queryInfo) {
List<OEntity> l = new ArrayList<OEntity>();
for (OEntity dir : this.getDirectories(queryInfo)) {
l.add(dir);
l.addAll(getFiles(dir.getProperty("Name", String.class).getValue(), queryInfo));
}
return l;
}
private List<OEntity> getFiles(String dirName, QueryInfo queryInfo) {
EdmEntitySet fileSet = edm.findEdmEntitySet("Files");
List<OEntity> l = new ArrayList<OEntity>();
for (int i = 0; i < 3; i++) {
List<OProperty<?>> props = new ArrayList<OProperty<?>>(2);
String name = "File-" + Integer.toString(i) + "-" + dirName;
props.add(OProperties.string("Name", name));
props.add(OProperties.string("FileProp1", name + "-FileProp1Value"));
l.add(OEntities.create(
fileSet,
OEntityKey.create("Name", name),
props,
new ArrayList<OLink>()));
}
return l;
}
private List<OEntity> getFiles(QueryInfo queryInfo) {
List<OEntity> l = new ArrayList<OEntity>();
for (OEntity dir : this.getDirectories(queryInfo)) {
l.addAll(getFiles(dir.getProperty("Name", String.class).getValue(), queryInfo));
}
return l;
}
private List<OEntity> getType1s() {
List<OEntity> l = new ArrayList<OEntity>(3);
for (int i = 0; i < 3; i++) {
l.add(getType1(0));
}
return l;
}
private OEntity getType1(int i) {
List<OProperty<?>> props = new ArrayList<OProperty<?>>(3);
String id = Integer.toString(i);
props.add(OProperties.string("Id", id));
Builder<OObject> builder = OCollections.newBuilder(EdmSimpleType.STRING);
props.add(OProperties.collection("EmptyStrings", new EdmCollectionType(CollectionKind.Bag, EdmSimpleType.STRING), builder.build()));
builder = OCollections.newBuilder(EdmSimpleType.STRING);
for (int j = 0; j < 3; j++) {
builder.add(OSimpleObjects.create(EdmSimpleType.STRING, "bagstring-" + j));
}
props.add(OProperties.collection("BagOStrings", new EdmCollectionType(CollectionKind.Bag, EdmSimpleType.STRING), builder.build()));
builder = OCollections.newBuilder(EdmSimpleType.STRING);
for (int j = 0; j < 5; j++) {
builder.add(OSimpleObjects.create(EdmSimpleType.STRING, "liststring-" + j));
}
props.add(OProperties.collection("ListOStrings", new EdmCollectionType(CollectionKind.List, EdmSimpleType.STRING), builder.build()));
builder = OCollections.newBuilder(EdmSimpleType.INT32);
for (int j = 0; j < 5; j++) {
builder.add(OSimpleObjects.create(EdmSimpleType.INT32, j));
}
props.add(OProperties.collection("BagOInts", new EdmCollectionType(CollectionKind.List, EdmSimpleType.INT32), builder.build()));
EdmComplexType ct1 = this.getMetadata().findEdmComplexType("myns.ComplexType1");
OComplexObject.Builder cb = OComplexObjects.newBuilder(ct1);
cb.add(OProperties.string("Prop1", "Val1")).add(OProperties.string("Prop2", "Val2"));
// hmmh, I swear I put a form of OProperties.complex that took an OComplexObject....
props.add(OProperties.complex("Complex1", ct1, cb.build().getProperties()));
builder = OCollections.newBuilder(ct1);
for (int j = 0; j < 2; j++) {
cb = OComplexObjects.newBuilder(ct1);
cb.add(OProperties.string("Prop1", "Val" + j)).add(OProperties.string("Prop2", "Val" + j));
builder.add(cb.build());
}
props.add(OProperties.collection("ListOComplex", new EdmCollectionType(CollectionKind.List, ct1), builder.build()));
return OEntities.create(
edm.findEdmEntitySet("Type1s"),
OEntityKey.create("Id", id),
props,
new ArrayList<OLink>());
}
public OEntity getFileSystemItem(OEntityKey entityKey, QueryInfo queryInfo) {
List<OEntity> es = this.getFileSystemItems(queryInfo);
for (OEntity e : es) {
if (e.getEntityKey().equals(entityKey)) {
return e;
}
}
throw new NotFoundException("nope");
}
public OEntity getMLE(OEntityKey entityKey, QueryInfo queryInfo) {
String id = entityKey.asSingleValue().toString();
if (!mediaResources.containsKey(id)) {
throw new NotFoundException("can't find MLE with id: " + id);
}
return getMLE(getMetadata().findEdmEntitySet("MLEs"), id, mediaResources.get(id));
}
@Override
public EntityResponse getEntity(ODataContext context, String entitySetName, OEntityKey entityKey, EntityQueryInfo queryInfo) {
if (entitySetName.equals("Type1s")) {
return Responses.entity(getType1(Integer.parseInt((String) entityKey.asSingleValue())));
}
if (entitySetName.equals("FileSystemItems")) {
return Responses.entity(getFileSystemItem(entityKey, queryInfo));
} else if (entitySetName.equals("MLEs")) {
return Responses.entity(getMLE(entityKey, queryInfo));
} else {
throw new NotFoundException("Unknown entity set: " + entitySetName);
}
}
@Override
public BaseResponse getNavProperty(ODataContext context, String entitySetName, OEntityKey entityKey, String navProp, QueryInfo queryInfo) {
throw new NotImplementedException();
}
@Override
public void close() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public EntityResponse createEntity(ODataContext context, String entitySetName, OEntity entity) {
if (entitySetName.equals("MLEs")) {
// just got done uploading a blob
return Responses.entity(entity);
} else {
throw new UnsupportedOperationException("Not supported yet.");
}
}
@Override
public EntityResponse createEntity(ODataContext context, String entitySetName, OEntityKey entityKey, String navProp, OEntity entity) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void deleteEntity(ODataContext context, String entitySetName, OEntityKey entityKey) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void mergeEntity(ODataContext context, String entitySetName, OEntity entity) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void updateEntity(ODataContext context, String entitySetName, OEntity entity) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public EntityIdResponse getLinks(ODataContext context, OEntityId sourceEntity, String targetNavProp) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void createLink(ODataContext context, OEntityId sourceEntity, String targetNavProp, OEntityId targetEntity) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void updateLink(ODataContext context, OEntityId sourceEntity, String targetNavProp, OEntityKey oldTargetEntityKey, OEntityId newTargetEntity) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void deleteLink(ODataContext context, OEntityId sourceEntity, String targetNavProp, OEntityKey targetEntityKey) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public BaseResponse callFunction(ODataContext context, EdmFunctionImport name, Map<String, OFunctionParameter> params, QueryInfo queryInfo) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public <TExtension extends OExtension<ODataProducer>> TExtension findExtension(Class<TExtension> clazz) {
if (clazz.equals(OMediaLinkExtensions.class))
return clazz.cast(extensionFactory);
return null;
}
public OMediaLinkExtensions extensionFactory = new MediaLinkExtensionFactory();
private final Map<String, String> mediaResources = new HashMap<String, String>();
public void initResources() {
mediaResources.put("foobar", "here we have some content for the mle with id: ('foobar')");
mediaResources.put("blatfoo", "please delete this useless mle asap...");
}
protected OEntity getMLE(EdmEntitySet entitySet, String id, String content) {
List<OProperty<?>> props = new ArrayList<OProperty<?>>();
props.add(OProperties.string("MLEProp1", "content length is " + content.length()));
return OEntities.create(entitySet, OEntityKey.create("Id", id), props, Collections.<OLink> emptyList());
}
private class MediaLinkExtensionFactory implements OMediaLinkExtensions {
@Override
public OMediaLinkExtension create(ODataContext context) {
return new MediaLinkExtension();
}
}
private class MediaLinkExtension implements OMediaLinkExtension {
@Override
public InputStream getInputStreamForMediaLinkEntry(ODataContext odataContext, OEntity mle, String etag, EntityQueryInfo query) {
if (null == odataContext) {
throw new IllegalArgumentException("no odataContext?");
}
String id = mle.getEntityKey().asSingleValue().toString();
String content = mediaResources.get(id); // "here we have some content for the mle with id: " +;
if (content == null) {
throw new NotFoundException();
}
return new ByteArrayInputStream(content.getBytes());
}
@Override
public String getMediaLinkContentType(ODataContext odataContext, OEntity mle) {
if (null == odataContext) {
throw new IllegalArgumentException("no odataContext?");
}
return "text/plain";
}
@Override
public OutputStream getOutputStreamForMediaLinkEntryCreate(ODataContext odataContext, OEntity mle, String etag, QueryInfo query) {
if (null == odataContext) {
throw new IllegalArgumentException("no odataContext?");
}
// create:
String id = mle.getEntityKey().asSingleValue().toString();
if (mediaResources.containsKey(id)) {
throw new BadRequestException("MLE with id: " + id + " already exists");
}
return new MRStream(id);
}
@Override
public OutputStream getOutputStreamForMediaLinkEntryUpdate(ODataContext odataContext, OEntity mle, String etag, QueryInfo query) {
if (null == odataContext) {
throw new IllegalArgumentException("no odataContext?");
}
String id = mle.getEntityKey().asSingleValue().toString();
if (!mediaResources.containsKey(id)) {
throw new NotFoundException("MLE with id: " + id + " not found");
}
return new MRStream(id);
}
@Override
public OEntity getMediaLinkEntryForUpdateOrDelete(ODataContext odataContext, EdmEntitySet entitySet, OEntityKey key, HttpHeaders httpHeaders) {
if (null == odataContext) {
throw new IllegalArgumentException("no odataContext?");
}
String id = key.asSingleValue().toString();
if (!mediaResources.containsKey(id)) {
throw new NotFoundException("MLE with id: " + id + " not found");
}
return getMLE(entitySet, id, mediaResources.get(id));
}
@Override
public String getMediaLinkContentDisposition(ODataContext odataContext, OEntity mle) {
if (null == odataContext) {
throw new IllegalArgumentException("no odataContext?");
}
return "inline";
}
private class MRStream extends ByteArrayOutputStream {
public MRStream(String id) {
this.id = id;
}
@Override
public void close() throws IOException {
super.close();
mediaResources.put(id, toString());
}
private String id;
}
@Override
public void deleteStream(ODataContext odataContext, OEntity mle, QueryInfo query) {
if (null == odataContext) {
throw new IllegalArgumentException("no odataContext?");
}
String id = mle.getEntityKey().asSingleValue().toString();
if (mediaResources.containsKey(id)) {
mediaResources.remove(id);
} else {
throw new NotFoundException("MLE with id: " + id + " not found");
}
}
@Override
public OEntity createMediaLinkEntry(ODataContext odataContext, EdmEntitySet entitySet, HttpHeaders httpHeaders) {
if (null == odataContext) {
throw new IllegalArgumentException("no odataContext?");
}
List<String> slugs = httpHeaders.getRequestHeader("Slug");
if (slugs == null || slugs.isEmpty()) {
throw new BadRequestException("missing Slug header");
}
// slug is the id
List<OProperty<?>> props = new ArrayList<OProperty<?>>();
props.add(OProperties.string("MLEProp1", "prop1 initial value"));
return OEntities.create(entitySet, OEntityKey.create("Id", slugs.get(0)), props, Collections.<OLink> emptyList());
}
@Override
public OEntity updateMediaLinkEntry(ODataContext odataContext, OEntity mle, OutputStream outStream) {
if (null == odataContext) {
throw new IllegalArgumentException("no odataContext?");
}
// sometimes after processing the blob we know more about the entity...
String id = mle.getEntityKey().asSingleValue().toString();
return getMLE(mle.getEntitySet(), id, mediaResources.get(id));
}
}
@Override
public void beginChangeSetBoundary() {
// TODO Auto-generated method stub
}
@Override
public void commitChangeSetBoundary() {
// TODO Auto-generated method stub
}
@Override
public void rollbackChangeSetBoundary() {
// TODO Auto-generated method stub
}
@Override
public EntityResponse createResponseForBatchPostOperation(String entitySetName, OEntity entity) {
// TODO Auto-generated method stub
return null;
}
@Override
public InputStream getInputStreamForMediaLink(String entitySetName, OEntityKey entityKey, EntityQueryInfo queryInfo) {
// TODO Auto-generated method stub
return null;
}
@Override
public void updateEntityWithStream(String entitySetName, OEntity entity) {
// TODO Auto-generated method stub
}
@Override
public ContextStream getInputStreamForNamedStream(String entitySetName, OEntityKey entityKey, String columnName, QueryInfo queryInfo) {
// TODO Auto-generated method stub
return null;
}
@Override
public void updateEntityWithNamedStream(String entitySetName, OEntityKey entityKey, String columnName, ContextStream streamContext) {
// TODO Auto-generated method stub
}
}