[OLINGO-175] using commons (de-)serializers to add some capabilities to fit
This commit is contained in:
parent
ba791fac39
commit
450ccfd4e3
12
fit/pom.xml
12
fit/pom.xml
|
@ -40,6 +40,18 @@
|
|||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.olingo</groupId>
|
||||
<artifactId>olingo-commons-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.fasterxml</groupId>
|
||||
<artifactId>aalto-xml</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Stax -->
|
||||
<dependency>
|
||||
<groupId>stax</groupId>
|
||||
|
|
|
@ -18,15 +18,35 @@
|
|||
*/
|
||||
package org.apache.olingo.fit;
|
||||
|
||||
import org.apache.olingo.commons.api.data.Container;
|
||||
import org.apache.olingo.commons.api.data.Feed;
|
||||
import org.apache.olingo.commons.api.data.Link;
|
||||
import org.apache.olingo.commons.api.data.Property;
|
||||
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
|
||||
import org.apache.olingo.commons.api.format.ContentType;
|
||||
import org.apache.olingo.commons.core.data.AtomDeserializer;
|
||||
import org.apache.olingo.commons.core.data.AtomFeedImpl;
|
||||
import org.apache.olingo.commons.core.data.LinkImpl;
|
||||
import org.apache.olingo.fit.metadata.Metadata;
|
||||
import org.apache.olingo.fit.serializer.JsonFeedContainer;
|
||||
import org.apache.olingo.fit.serializer.JsonEntryContainer;
|
||||
import org.apache.olingo.fit.utils.ConstantKey;
|
||||
import org.apache.olingo.fit.utils.Constants;
|
||||
import org.apache.olingo.fit.utils.DataBinder;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -51,18 +71,28 @@ import javax.ws.rs.core.UriInfo;
|
|||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.olingo.commons.api.data.Entry;
|
||||
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
|
||||
import org.apache.olingo.commons.core.data.AtomEntryImpl;
|
||||
import org.apache.olingo.commons.core.data.AtomPropertyImpl;
|
||||
import org.apache.olingo.commons.core.data.AtomSerializer;
|
||||
import org.apache.olingo.commons.core.data.JSONEntryImpl;
|
||||
import org.apache.olingo.commons.core.data.JSONFeedImpl;
|
||||
import org.apache.olingo.commons.core.data.NullValueImpl;
|
||||
import org.apache.olingo.commons.core.data.PrimitiveValueImpl;
|
||||
import org.apache.olingo.fit.metadata.EntitySet;
|
||||
import org.apache.olingo.fit.metadata.EntityType;
|
||||
import org.apache.olingo.fit.metadata.NavigationProperty;
|
||||
import org.apache.olingo.fit.utils.Accept;
|
||||
import org.apache.olingo.fit.utils.FSManager;
|
||||
|
||||
import org.apache.olingo.fit.utils.Commons;
|
||||
import org.apache.olingo.fit.methods.MERGE;
|
||||
import org.apache.olingo.fit.methods.PATCH;
|
||||
import org.apache.olingo.fit.utils.AbstractJSONUtilities;
|
||||
import org.apache.olingo.fit.utils.AbstractUtilities;
|
||||
import org.apache.olingo.fit.utils.AbstractXMLUtilities;
|
||||
import org.apache.olingo.fit.utils.Accept;
|
||||
import org.apache.olingo.fit.utils.Commons;
|
||||
import org.apache.olingo.fit.utils.ConstantKey;
|
||||
import org.apache.olingo.fit.utils.Constants;
|
||||
import org.apache.olingo.fit.utils.FSManager;
|
||||
import org.apache.olingo.fit.utils.LinkInfo;
|
||||
import org.apache.olingo.fit.utils.ODataVersion;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -73,9 +103,7 @@ public abstract class AbstractServices {
|
|||
*/
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(AbstractServices.class);
|
||||
|
||||
private static final Set<ODataVersion> INITIALIZED = EnumSet.noneOf(ODataVersion.class);
|
||||
|
||||
protected final ODataVersion version;
|
||||
protected final ODataServiceVersion version;
|
||||
|
||||
protected final AbstractXMLUtilities xml;
|
||||
|
||||
|
@ -84,9 +112,11 @@ public abstract class AbstractServices {
|
|||
@Context
|
||||
protected UriInfo uriInfo;
|
||||
|
||||
public AbstractServices(final ODataVersion version) throws Exception {
|
||||
protected Metadata metadata;
|
||||
|
||||
public AbstractServices(final ODataServiceVersion version) throws Exception {
|
||||
this.version = version;
|
||||
if (ODataVersion.v3 == version) {
|
||||
if (version.compareTo(ODataServiceVersion.V30) <= 0) {
|
||||
this.xml = new org.apache.olingo.fit.utils.v3.XMLUtilities();
|
||||
this.json = new org.apache.olingo.fit.utils.v3.JSONUtilities();
|
||||
} else {
|
||||
|
@ -94,10 +124,7 @@ public abstract class AbstractServices {
|
|||
this.json = new org.apache.olingo.fit.utils.v4.JSONUtilities();
|
||||
}
|
||||
|
||||
if (!INITIALIZED.contains(version)) {
|
||||
xml.retrieveLinkInfoFromMetadata();
|
||||
INITIALIZED.add(version);
|
||||
}
|
||||
metadata = Commons.getMetadata(version);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -169,7 +196,7 @@ public abstract class AbstractServices {
|
|||
|
||||
return utils.getValue().createResponse(
|
||||
FSManager.instance(version).readFile(Constants.get(version, ConstantKey.REF)
|
||||
+ File.separatorChar + filename, utils.getKey()),
|
||||
+ File.separatorChar + filename, utils.getKey()),
|
||||
null,
|
||||
utils.getKey());
|
||||
} catch (Exception e) {
|
||||
|
@ -216,9 +243,32 @@ public abstract class AbstractServices {
|
|||
InputStream res =
|
||||
util.patchEntity(entitySetName, entityId, IOUtils.toInputStream(changes), acceptType, ifMatch);
|
||||
|
||||
|
||||
final AtomDeserializer atomDeserializer = Commons.getAtomDeserializer(version);
|
||||
|
||||
final ObjectMapper mapper = Commons.getJsonMapper(version);
|
||||
|
||||
final Container<AtomEntryImpl> cres;
|
||||
if (acceptType == Accept.ATOM) {
|
||||
cres = atomDeserializer.read(res, AtomEntryImpl.class);
|
||||
} else {
|
||||
final Container<JSONEntryImpl> jcont = mapper.readValue(res, new TypeReference<JSONEntryImpl>() {
|
||||
});
|
||||
cres = new Container<AtomEntryImpl>(jcont.getContextURL(), jcont.getMetadataETag(),
|
||||
(new DataBinder(version)).getAtomEntry(jcont.getObject()));
|
||||
}
|
||||
|
||||
normalizeAtomEntry(cres.getObject(), entitySetName, entityId);
|
||||
|
||||
final String path = Commons.getEntityBasePath(entitySetName, entityId);
|
||||
FSManager.instance(version).putInMemory(
|
||||
cres, path + File.separatorChar + Constants.get(version, ConstantKey.ENTITY));
|
||||
|
||||
final Response response;
|
||||
if ("return-content".equalsIgnoreCase(prefer)) {
|
||||
response = xml.createResponse(res, null, acceptType, Response.Status.OK);
|
||||
response = xml.createResponse(
|
||||
util.readEntity(entitySetName, entityId, acceptType).getValue(),
|
||||
null, acceptType, Response.Status.OK);
|
||||
} else {
|
||||
res.close();
|
||||
response = xml.createResponse(null, null, acceptType, Response.Status.NO_CONTENT);
|
||||
|
@ -258,9 +308,28 @@ public abstract class AbstractServices {
|
|||
res = json.addOrReplaceEntity(entityId, entitySetName, IOUtils.toInputStream(entity));
|
||||
}
|
||||
|
||||
final AtomDeserializer atomDeserializer = Commons.getAtomDeserializer(version);
|
||||
final ObjectMapper mapper = Commons.getJsonMapper(version);
|
||||
|
||||
final Container<AtomEntryImpl> cres;
|
||||
if (acceptType == Accept.ATOM) {
|
||||
cres = atomDeserializer.read(res, AtomEntryImpl.class);
|
||||
} else {
|
||||
final Container<JSONEntryImpl> jcont = mapper.readValue(res, new TypeReference<JSONEntryImpl>() {
|
||||
});
|
||||
cres = new Container<AtomEntryImpl>(jcont.getContextURL(), jcont.getMetadataETag(),
|
||||
(new DataBinder(version)).getAtomEntry(jcont.getObject()));
|
||||
}
|
||||
|
||||
final String path = Commons.getEntityBasePath(entitySetName, entityId);
|
||||
FSManager.instance(version).putInMemory(
|
||||
cres, path + File.separatorChar + Constants.get(version, ConstantKey.ENTITY));
|
||||
|
||||
final Response response;
|
||||
if ("return-content".equalsIgnoreCase(prefer)) {
|
||||
response = xml.createResponse(res, null, acceptType, Response.Status.OK);
|
||||
response = xml.createResponse(
|
||||
getUtilities(acceptType).readEntity(entitySetName, entityId, acceptType).getValue(),
|
||||
null, acceptType, Response.Status.OK);
|
||||
} else {
|
||||
res.close();
|
||||
response = xml.createResponse(null, null, acceptType, Response.Status.NO_CONTENT);
|
||||
|
@ -282,6 +351,7 @@ public abstract class AbstractServices {
|
|||
@Consumes({MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_OCTET_STREAM})
|
||||
public Response postNewEntity(
|
||||
@HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
|
||||
@HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) String contentType,
|
||||
@HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) String prefer,
|
||||
@PathParam("entitySetName") String entitySetName,
|
||||
final String entity) {
|
||||
|
@ -297,20 +367,89 @@ public abstract class AbstractServices {
|
|||
|
||||
utils = getUtilities(acceptType);
|
||||
|
||||
final InputStream res;
|
||||
final AtomDeserializer atomDeserializer = Commons.getAtomDeserializer(version);
|
||||
final AtomSerializer atomSerializer = Commons.getAtomSerializer(version);
|
||||
final ObjectMapper mapper = Commons.getJsonMapper(version);
|
||||
|
||||
final Container<AtomEntryImpl> container;
|
||||
|
||||
final EntitySet entitySet = metadata.getEntitySet(entitySetName);
|
||||
final AtomEntryImpl entry;
|
||||
|
||||
final String entityKey;
|
||||
|
||||
if (utils.isMediaContent(entitySetName)) {
|
||||
res = utils.addMediaEntity(entitySetName, IOUtils.toInputStream(entity));
|
||||
entityKey = xml.getDefaultEntryKey(entitySetName, null);
|
||||
|
||||
utils.addMediaEntityValue(entitySetName, entityKey, IOUtils.toInputStream(entity));
|
||||
|
||||
entry = new AtomEntryImpl();
|
||||
entry.setMediaContentType(ContentType.WILDCARD);
|
||||
entry.setType(entitySet.getType());
|
||||
|
||||
final String id = Commons.getMediaContent().get(entitySetName);
|
||||
if (StringUtils.isNotBlank(id)) {
|
||||
final AtomPropertyImpl prop = new AtomPropertyImpl();
|
||||
prop.setName(id);
|
||||
prop.setType(EdmPrimitiveTypeKind.Int32.toString());
|
||||
prop.setValue(new PrimitiveValueImpl(entityKey));
|
||||
entry.getProperties().add(prop);
|
||||
}
|
||||
|
||||
final Link editLink = new LinkImpl();
|
||||
editLink.setHref(Commons.getEntityURI(entitySetName, entityKey));
|
||||
editLink.setRel("edit");
|
||||
editLink.setTitle(entitySetName);
|
||||
entry.setEditLink(editLink);
|
||||
|
||||
entry.setMediaContentSource(editLink.getHref() + "/$value");
|
||||
|
||||
container = new Container<AtomEntryImpl>(null, null, entry);
|
||||
} else {
|
||||
res = utils.addOrReplaceEntity(entitySetName, IOUtils.toInputStream(entity));
|
||||
final Accept contentTypeValue = Accept.parse(contentType, version);
|
||||
entityKey = getUtilities(contentTypeValue).getDefaultEntryKey(entitySetName, IOUtils.toInputStream(entity));
|
||||
|
||||
if (Accept.ATOM == contentTypeValue) {
|
||||
container = atomDeserializer.read(IOUtils.toInputStream(entity), AtomEntryImpl.class);
|
||||
entry = container.getObject();
|
||||
} else {
|
||||
final Container<JSONEntryImpl> jcontainer =
|
||||
mapper.readValue(IOUtils.toInputStream(entity), new TypeReference<JSONEntryImpl>() {
|
||||
});
|
||||
|
||||
entry = (new DataBinder(version)).
|
||||
getAtomEntry(jcontainer.getObject());
|
||||
|
||||
container = new Container<AtomEntryImpl>(
|
||||
jcontainer.getContextURL(),
|
||||
jcontainer.getMetadataETag(),
|
||||
entry);
|
||||
}
|
||||
}
|
||||
|
||||
normalizeAtomEntry(entry, entitySetName, entityKey);
|
||||
|
||||
final ByteArrayOutputStream content = new ByteArrayOutputStream();
|
||||
OutputStreamWriter writer = new OutputStreamWriter(content, Constants.encoding);
|
||||
atomSerializer.write(writer, container);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
|
||||
final InputStream serialization =
|
||||
xml.addOrReplaceEntity(entitySetName, new ByteArrayInputStream(content.toByteArray()));
|
||||
|
||||
final Container<AtomEntryImpl> cres = atomDeserializer.read(serialization, AtomEntryImpl.class);
|
||||
|
||||
final String path = Commons.getEntityBasePath(entitySetName, entityKey);
|
||||
FSManager.instance(version).putInMemory(
|
||||
cres, path + File.separatorChar + Constants.get(version, ConstantKey.ENTITY));
|
||||
|
||||
final Response response;
|
||||
if ("return-no-content".equalsIgnoreCase(prefer)) {
|
||||
IOUtils.closeQuietly(res);
|
||||
response = utils.createResponse(null, null, acceptType, Response.Status.NO_CONTENT);
|
||||
} else {
|
||||
response = utils.createResponse(res, null, acceptType, Response.Status.CREATED);
|
||||
response = utils.createResponse(utils.readEntity(entitySetName, entityKey, acceptType).getValue(),
|
||||
null, acceptType, Response.Status.CREATED);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(prefer)) {
|
||||
|
@ -349,13 +488,13 @@ public abstract class AbstractServices {
|
|||
replaceAll("\"Salary\":[0-9]*,", "\"Salary\":0,").
|
||||
replaceAll("\"Title\":\".*\"", "\"Title\":\"[Sacked]\"").
|
||||
replaceAll("\\<d:Salary m:type=\"Edm.Int32\"\\>.*\\</d:Salary\\>",
|
||||
"<d:Salary m:type=\"Edm.Int32\">0</d:Salary>").
|
||||
"<d:Salary m:type=\"Edm.Int32\">0</d:Salary>").
|
||||
replaceAll("\\<d:Title\\>.*\\</d:Title\\>", "<d:Title>[Sacked]</d:Title>");
|
||||
|
||||
final FSManager fsManager = FSManager.instance(version);
|
||||
fsManager.putInMemory(IOUtils.toInputStream(newContent, "UTF-8"),
|
||||
fsManager.getAbsolutePath(Commons.getEntityBasePath("Person", entityId) + Constants.get(version,
|
||||
ConstantKey.ENTITY), utils.getKey()));
|
||||
ConstantKey.ENTITY), utils.getKey()));
|
||||
|
||||
return utils.getValue().createResponse(null, null, utils.getKey(), Response.Status.NO_CONTENT);
|
||||
} catch (Exception e) {
|
||||
|
@ -387,7 +526,8 @@ public abstract class AbstractServices {
|
|||
final StringBuilder path = new StringBuilder(name).
|
||||
append(File.separatorChar).append(type).
|
||||
append(File.separatorChar);
|
||||
path.append(Commons.getLinkInfo().get(version).isSingleton(name)
|
||||
|
||||
path.append(metadata.getEntitySet(name).isSingleton()
|
||||
? Constants.get(version, ConstantKey.ENTITY)
|
||||
: Constants.get(version, ConstantKey.FEED));
|
||||
|
||||
|
@ -406,9 +546,9 @@ public abstract class AbstractServices {
|
|||
final Long newSalary = Long.valueOf(salaryMatcher.group(1)) + n;
|
||||
newContent = newContent.
|
||||
replaceAll("\"Salary\":" + salaryMatcher.group(1) + ",",
|
||||
"\"Salary\":" + newSalary + ",").
|
||||
"\"Salary\":" + newSalary + ",").
|
||||
replaceAll("\\<d:Salary m:type=\"Edm.Int32\"\\>" + salaryMatcher.group(1) + "</d:Salary\\>",
|
||||
"<d:Salary m:type=\"Edm.Int32\">" + newSalary + "</d:Salary>");
|
||||
"<d:Salary m:type=\"Edm.Int32\">" + newSalary + "</d:Salary>");
|
||||
}
|
||||
|
||||
FSManager.instance(version).putInMemory(IOUtils.toInputStream(newContent, "UTF-8"),
|
||||
|
@ -445,7 +585,8 @@ public abstract class AbstractServices {
|
|||
final StringBuilder path = new StringBuilder(name).
|
||||
append(File.separatorChar).append(type).
|
||||
append(File.separatorChar);
|
||||
path.append(Commons.getLinkInfo().get(version).isSingleton(name)
|
||||
|
||||
path.append(metadata.getEntitySet(name).isSingleton()
|
||||
? Constants.get(version, ConstantKey.ENTITY)
|
||||
: Constants.get(version, ConstantKey.FEED));
|
||||
|
||||
|
@ -462,7 +603,7 @@ public abstract class AbstractServices {
|
|||
* @param accept Accept header.
|
||||
* @param name entity set or function name.
|
||||
* @param format format query option.
|
||||
* @param inlinecount inlinecount query option.
|
||||
* @param count inlinecount query option.
|
||||
* @param filter filter query option.
|
||||
* @param orderby orderby query option.
|
||||
* @param skiptoken skiptoken query option.
|
||||
|
@ -474,7 +615,7 @@ public abstract class AbstractServices {
|
|||
@HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
|
||||
@PathParam("name") String name,
|
||||
@QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format,
|
||||
@QueryParam("$inlinecount") @DefaultValue(StringUtils.EMPTY) String inlinecount,
|
||||
@QueryParam("$inlinecount") @DefaultValue(StringUtils.EMPTY) String count,
|
||||
@QueryParam("$filter") @DefaultValue(StringUtils.EMPTY) String filter,
|
||||
@QueryParam("$orderby") @DefaultValue(StringUtils.EMPTY) String orderby,
|
||||
@QueryParam("$skiptoken") @DefaultValue(StringUtils.EMPTY) String skiptoken) {
|
||||
|
@ -514,35 +655,55 @@ public abstract class AbstractServices {
|
|||
builder.append(Constants.get(version, ConstantKey.SKIP_TOKEN)).append(File.separatorChar).
|
||||
append(skiptoken);
|
||||
} else {
|
||||
builder.append(Commons.getLinkInfo().get(version).isSingleton(name)
|
||||
builder.append(metadata.getEntitySet(name).isSingleton()
|
||||
? Constants.get(version, ConstantKey.ENTITY)
|
||||
: Constants.get(version, ConstantKey.FEED));
|
||||
}
|
||||
|
||||
InputStream feed = FSManager.instance(version).readFile(builder.toString(), acceptType);
|
||||
if ("allpages".equals(inlinecount)) {
|
||||
int count = xml.countAllElements(name);
|
||||
feed.close();
|
||||
if (acceptType == Accept.ATOM) {
|
||||
feed = xml.addAtomInlinecount(
|
||||
FSManager.instance(version).readFile(builder.toString(), acceptType),
|
||||
count,
|
||||
acceptType);
|
||||
} else {
|
||||
feed = json.addJsonInlinecount(
|
||||
FSManager.instance(version).readFile(builder.toString(), acceptType),
|
||||
count,
|
||||
acceptType);
|
||||
}
|
||||
final InputStream feed = FSManager.instance(version).readFile(builder.toString(), Accept.ATOM);
|
||||
|
||||
final AtomDeserializer atomDeserializer = Commons.getAtomDeserializer(version);
|
||||
final AtomSerializer atomSerializer = Commons.getAtomSerializer(version);
|
||||
final Container<Feed> container = atomDeserializer.read(feed, AtomFeedImpl.class);
|
||||
|
||||
setInlineCount(container.getObject(), count);
|
||||
|
||||
final ByteArrayOutputStream content = new ByteArrayOutputStream();
|
||||
final OutputStreamWriter writer = new OutputStreamWriter(content, Constants.encoding);
|
||||
|
||||
if (acceptType == Accept.ATOM) {
|
||||
atomSerializer.write(writer, container);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
} else {
|
||||
final ObjectMapper mapper = Commons.getJsonMapper(version);
|
||||
|
||||
mapper.writeValue(
|
||||
writer, new JsonFeedContainer<JSONFeedImpl>(container.getContextURL(), container.getMetadataETag(),
|
||||
(new DataBinder(version)).getJsonFeed((AtomFeedImpl) container.getObject())));
|
||||
}
|
||||
|
||||
return xml.createResponse(feed, Commons.getETag(basePath, version), acceptType);
|
||||
return xml.createResponse(new ByteArrayInputStream(content.toByteArray()),
|
||||
Commons.getETag(basePath, version), acceptType);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return xml.createFaultResponse(accept, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void setInlineCount(final Feed feed, final String count);
|
||||
|
||||
/**
|
||||
* Retrieve entity with key as segment.
|
||||
*
|
||||
* @param accept Accept header.
|
||||
* @param entitySetName Entity set name.
|
||||
* @param entityId entity id.
|
||||
* @param format format query option.
|
||||
* @param expand expand query option.
|
||||
* @param select select query option.
|
||||
* @return entity.
|
||||
*/
|
||||
@GET
|
||||
@Path("/Person({entityId})")
|
||||
public Response getEntity(
|
||||
|
@ -615,31 +776,101 @@ public abstract class AbstractServices {
|
|||
}
|
||||
|
||||
final Map.Entry<String, InputStream> entityInfo =
|
||||
utils.getValue().readEntity(entitySetName, entityId, utils.getKey());
|
||||
utils.getValue().readEntity(entitySetName, entityId, Accept.ATOM);
|
||||
|
||||
InputStream entity = entityInfo.getValue();
|
||||
|
||||
final AtomDeserializer atomDeserializer = Commons.getAtomDeserializer(version);
|
||||
final AtomSerializer atomSerializer = Commons.getAtomSerializer(version);
|
||||
|
||||
final Container<Entry> container = atomDeserializer.<Entry, AtomEntryImpl>read(entity, AtomEntryImpl.class);
|
||||
final Entry entry = container.getObject();
|
||||
|
||||
if (keyAsSegment) {
|
||||
entity = utils.getValue().addEditLink(
|
||||
entity, entitySetName,
|
||||
Constants.get(version, ConstantKey.DEFAULT_SERVICE_URL) + entitySetName + "/" + entityId);
|
||||
final Link editLink = new LinkImpl();
|
||||
editLink.setRel("edit");
|
||||
editLink.setTitle(entitySetName);
|
||||
editLink.setHref(Constants.get(version, ConstantKey.DEFAULT_SERVICE_URL) + entitySetName + "/" + entityId);
|
||||
|
||||
entry.setEditLink(editLink);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(select)) {
|
||||
entity = utils.getValue().selectEntity(entity, select.split(","));
|
||||
final List<String> properties = Arrays.asList(select.split(","));
|
||||
final Set<Property> toBeRemoved = new HashSet<Property>();
|
||||
|
||||
for (Property property : entry.getProperties()) {
|
||||
if (!properties.contains(property.getName())) {
|
||||
toBeRemoved.add(property);
|
||||
}
|
||||
}
|
||||
|
||||
entry.getProperties().removeAll(toBeRemoved);
|
||||
|
||||
final Set<Link> linkToBeRemoved = new HashSet<Link>();
|
||||
|
||||
for (Link link : entry.getNavigationLinks()) {
|
||||
if (!properties.contains(link.getTitle().replaceAll("@.*$", "")) && !properties.contains(link.getTitle())) {
|
||||
linkToBeRemoved.add(link);
|
||||
}
|
||||
}
|
||||
|
||||
entry.getNavigationLinks().removeAll(linkToBeRemoved);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(expand)) {
|
||||
for (String exp : expand.split(",")) {
|
||||
entity = utils.getValue().expandEntity(
|
||||
entitySetName,
|
||||
entityId,
|
||||
entity,
|
||||
exp);
|
||||
final List<String> links = Arrays.asList(expand.split(","));
|
||||
|
||||
final Map<Link, Link> replace = new HashMap<Link, Link>();
|
||||
|
||||
for (Link link : entry.getNavigationLinks()) {
|
||||
if (links.contains(link.getTitle())) {
|
||||
// expand link
|
||||
final Link rep = new LinkImpl();
|
||||
rep.setHref(link.getHref());
|
||||
rep.setRel(link.getRel());
|
||||
rep.setTitle(link.getTitle());
|
||||
rep.setType(link.getType());
|
||||
if (link.getType().equals(Constants.get(ConstantKey.ATOM_LINK_ENTRY))) {
|
||||
// inline entry
|
||||
final Entry inline = atomDeserializer.<Entry, AtomEntryImpl>read(
|
||||
xml.expandEntity(entitySetName, entityId, link.getTitle()),
|
||||
AtomEntryImpl.class).getObject();
|
||||
rep.setInlineEntry(inline);
|
||||
} else if (link.getType().equals(Constants.get(ConstantKey.ATOM_LINK_FEED))) {
|
||||
// inline feed
|
||||
final Feed inline = atomDeserializer.<Feed, AtomFeedImpl>read(
|
||||
xml.expandEntity(entitySetName, entityId, link.getTitle()),
|
||||
AtomFeedImpl.class).getObject();
|
||||
rep.setInlineFeed(inline);
|
||||
}
|
||||
replace.put(link, rep);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<Link, Link> link : replace.entrySet()) {
|
||||
entry.getNavigationLinks().remove(link.getKey());
|
||||
entry.getNavigationLinks().add(link.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return utils.getValue().createResponse(entity, Commons.getETag(entityInfo.getKey(), version), utils.getKey());
|
||||
final ByteArrayOutputStream content = new ByteArrayOutputStream();
|
||||
final OutputStreamWriter writer = new OutputStreamWriter(content, Constants.encoding);
|
||||
|
||||
if (utils.getKey() == Accept.ATOM) {
|
||||
atomSerializer.write(writer, container);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
} else {
|
||||
final ObjectMapper mapper = Commons.getJsonMapper(version);
|
||||
mapper.writeValue(
|
||||
writer, new JsonEntryContainer<JSONEntryImpl>(container.getContextURL(), container.getMetadataETag(),
|
||||
(new DataBinder(version)).getJsonEntry((AtomEntryImpl) container.getObject())));
|
||||
}
|
||||
|
||||
return xml.createResponse(new ByteArrayInputStream(content.toByteArray()),
|
||||
Commons.getETag(entityInfo.getKey(), version), utils.getKey());
|
||||
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error retrieving entity", e);
|
||||
return xml.createFaultResponse(accept, e);
|
||||
|
@ -1384,4 +1615,37 @@ public abstract class AbstractServices {
|
|||
|
||||
return utils;
|
||||
}
|
||||
|
||||
private void normalizeAtomEntry(final AtomEntryImpl entry, final String entitySetName, final String entityKey) {
|
||||
final EntitySet entitySet = metadata.getEntitySet(entitySetName);
|
||||
final EntityType entityType = metadata.getEntityType(entitySet.getType());
|
||||
for (Map.Entry<String, org.apache.olingo.fit.metadata.Property> property
|
||||
: entityType.getPropertyMap().entrySet()) {
|
||||
if (entry.getProperty(property.getKey()) == null && property.getValue().isNullable()) {
|
||||
final AtomPropertyImpl prop = new AtomPropertyImpl();
|
||||
prop.setName(property.getKey());
|
||||
prop.setValue(new NullValueImpl());
|
||||
entry.getProperties().add(prop);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<String, NavigationProperty> property : entityType.getNavigationPropertyMap().entrySet()) {
|
||||
boolean found = false;
|
||||
for (Link link : entry.getNavigationLinks()) {
|
||||
if (link.getTitle().equals(property.getKey())) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
final LinkImpl link = new LinkImpl();
|
||||
link.setTitle(property.getKey());
|
||||
link.setType(property.getValue().isFeed()
|
||||
? Constants.get(ConstantKey.ATOM_LINK_FEED) : Constants.get(ConstantKey.ATOM_LINK_ENTRY));
|
||||
link.setRel(Constants.get(ConstantKey.ATOM_LINK_REL) + property.getKey());
|
||||
link.setHref(entitySetName + "(" + entityKey + ")/" + property.getKey());
|
||||
entry.getNavigationLinks().add(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@ import javax.ws.rs.core.Response;
|
|||
import static javax.ws.rs.core.Response.status;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.olingo.commons.api.data.Feed;
|
||||
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
|
||||
import static org.apache.olingo.fit.AbstractServices.LOG;
|
||||
import org.apache.olingo.fit.utils.AbstractUtilities;
|
||||
import org.apache.olingo.fit.utils.Accept;
|
||||
|
@ -42,7 +44,6 @@ import org.apache.olingo.fit.utils.Commons;
|
|||
import org.apache.olingo.fit.utils.ConstantKey;
|
||||
import org.apache.olingo.fit.utils.Constants;
|
||||
import org.apache.olingo.fit.utils.FSManager;
|
||||
import org.apache.olingo.fit.utils.ODataVersion;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
|
@ -50,7 +51,7 @@ import org.springframework.stereotype.Service;
|
|||
public class V3ActionOverloading extends AbstractServices {
|
||||
|
||||
public V3ActionOverloading() throws Exception {
|
||||
super(ODataVersion.v3);
|
||||
super(ODataServiceVersion.V30);
|
||||
}
|
||||
|
||||
private Response replaceServiceName(final Response response) {
|
||||
|
@ -84,7 +85,7 @@ public class V3ActionOverloading extends AbstractServices {
|
|||
@Produces(MediaType.APPLICATION_XML)
|
||||
public Response getLargeMetadata() {
|
||||
return super.getMetadata("actionOverloading"
|
||||
+ StringUtils.capitalize(Constants.get(ODataVersion.v3, ConstantKey.METADATA)));
|
||||
+ StringUtils.capitalize(Constants.get(ODataServiceVersion.V30, ConstantKey.METADATA)));
|
||||
}
|
||||
|
||||
@POST
|
||||
|
@ -98,14 +99,14 @@ public class V3ActionOverloading extends AbstractServices {
|
|||
if (StringUtils.isNotBlank(format)) {
|
||||
acceptType = Accept.valueOf(format.toUpperCase());
|
||||
} else {
|
||||
acceptType = Accept.parse(accept, ODataVersion.v3);
|
||||
acceptType = Accept.parse(accept, ODataServiceVersion.V30);
|
||||
}
|
||||
if (acceptType == Accept.XML || acceptType == Accept.TEXT) {
|
||||
throw new UnsupportedMediaTypeException("Unsupported media type");
|
||||
}
|
||||
|
||||
try {
|
||||
final InputStream result = FSManager.instance(ODataVersion.v3).
|
||||
final InputStream result = FSManager.instance(ODataServiceVersion.V30).
|
||||
readFile("actionOverloadingRetrieveProduct", acceptType);
|
||||
return replaceServiceName(xml.createResponse(result, null, acceptType));
|
||||
} catch (Exception e) {
|
||||
|
@ -137,7 +138,7 @@ public class V3ActionOverloading extends AbstractServices {
|
|||
}
|
||||
|
||||
return replaceServiceName(utils.getValue().createResponse(
|
||||
entity, Commons.getETag(entityInfo.getKey(), ODataVersion.v3), utils.getKey()));
|
||||
entity, Commons.getETag(entityInfo.getKey(), ODataServiceVersion.V30), utils.getKey()));
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error retrieving entity", e);
|
||||
return replaceServiceName(xml.createFaultResponse(accept, e));
|
||||
|
@ -180,7 +181,7 @@ public class V3ActionOverloading extends AbstractServices {
|
|||
}
|
||||
|
||||
return replaceServiceName(utils.getValue().createResponse(
|
||||
entity, Commons.getETag(entityInfo.getKey(), ODataVersion.v3), utils.getKey()));
|
||||
entity, Commons.getETag(entityInfo.getKey(), ODataServiceVersion.V30), utils.getKey()));
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error retrieving entity", e);
|
||||
return replaceServiceName(xml.createFaultResponse(accept, e));
|
||||
|
@ -197,4 +198,8 @@ public class V3ActionOverloading extends AbstractServices {
|
|||
return unboundRetrieveProduct(accept, format, contentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setInlineCount(Feed feed, String count) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -150,10 +150,11 @@ public class V3KeyAsSegment {
|
|||
@Consumes({MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_OCTET_STREAM})
|
||||
public Response postNewEntity(
|
||||
@HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
|
||||
@HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) String contentType,
|
||||
@HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) String prefer,
|
||||
@PathParam("entitySetName") String entitySetName,
|
||||
final String entity) {
|
||||
|
||||
return replaceServiceName(services.postNewEntity(accept, prefer, entitySetName, entity));
|
||||
return replaceServiceName(services.postNewEntity(accept, contentType, prefer, entitySetName, entity));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import java.io.InputStream;
|
|||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.HeaderParam;
|
||||
import org.apache.olingo.fit.utils.ODataVersion;
|
||||
import org.apache.olingo.fit.utils.XHTTPMethodInterceptor;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
|
@ -31,6 +30,8 @@ import javax.ws.rs.core.MediaType;
|
|||
import javax.ws.rs.core.Response;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.cxf.interceptor.InInterceptors;
|
||||
import org.apache.olingo.commons.api.data.Feed;
|
||||
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
|
||||
import org.apache.olingo.fit.utils.Accept;
|
||||
import org.apache.olingo.fit.utils.ConstantKey;
|
||||
import org.apache.olingo.fit.utils.Constants;
|
||||
|
@ -43,7 +44,7 @@ import org.springframework.stereotype.Service;
|
|||
public class V3Services extends AbstractServices {
|
||||
|
||||
public V3Services() throws Exception {
|
||||
super(ODataVersion.v3);
|
||||
super(ODataServiceVersion.V30);
|
||||
}
|
||||
|
||||
@GET
|
||||
|
@ -63,7 +64,7 @@ public class V3Services extends AbstractServices {
|
|||
final InputStream error = FSManager.instance(version).readFile("InStreamErrorGetCustomer", acceptType);
|
||||
|
||||
return Response.ok(error).
|
||||
header(Constants.get(version, ConstantKey.ODATA_SERVICE_VERSION), version.getVersion() + ";").
|
||||
header(Constants.get(version, ConstantKey.ODATA_SERVICE_VERSION), version + ";").
|
||||
header("Content-Type", acceptType.toString(version)).
|
||||
build();
|
||||
} catch (Exception e) {
|
||||
|
@ -99,4 +100,10 @@ public class V3Services extends AbstractServices {
|
|||
return getMetadata("openType" + StringUtils.capitalize(Constants.get(version, ConstantKey.METADATA)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setInlineCount(final Feed feed, final String count) {
|
||||
if ("allpages".equals(count)) {
|
||||
feed.setCount(feed.getEntries().size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
package org.apache.olingo.fit;
|
||||
|
||||
import org.apache.olingo.fit.utils.ODataVersion;
|
||||
import org.apache.olingo.fit.utils.XHTTPMethodInterceptor;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
@ -30,15 +29,14 @@ import org.springframework.stereotype.Service;
|
|||
@Service
|
||||
@Path("/V40/NorthWind.svc")
|
||||
@InInterceptors(classes = XHTTPMethodInterceptor.class)
|
||||
public class V4NorthWind extends AbstractServices {
|
||||
public class V4NorthWind extends V4Services {
|
||||
|
||||
public V4NorthWind() throws Exception {
|
||||
super(ODataVersion.v4);
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response getMetadata() {
|
||||
return getMetadata("northwind-" + Constants.get(version, ConstantKey.METADATA));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
package org.apache.olingo.fit;
|
||||
|
||||
import org.apache.olingo.fit.utils.ODataVersion;
|
||||
import org.apache.olingo.fit.utils.XHTTPMethodInterceptor;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
@ -31,15 +30,14 @@ import org.springframework.stereotype.Service;
|
|||
@Service
|
||||
@Path("/V40/NorthWindExt.svc")
|
||||
@InInterceptors(classes = {XHTTPMethodInterceptor.class, ResolvingReferencesInterceptor.class})
|
||||
public class V4NorthWindExt extends AbstractServices {
|
||||
public class V4NorthWindExt extends V4Services {
|
||||
|
||||
public V4NorthWindExt() throws Exception {
|
||||
super(ODataVersion.v4);
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response getMetadata() {
|
||||
return getMetadata("northwindExt-" + Constants.get(version, ConstantKey.METADATA));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,10 +18,11 @@
|
|||
*/
|
||||
package org.apache.olingo.fit;
|
||||
|
||||
import org.apache.olingo.fit.utils.ODataVersion;
|
||||
import org.apache.olingo.fit.utils.XHTTPMethodInterceptor;
|
||||
import javax.ws.rs.Path;
|
||||
import org.apache.cxf.interceptor.InInterceptors;
|
||||
import org.apache.olingo.commons.api.data.Feed;
|
||||
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
|
||||
import org.apache.olingo.fit.utils.ResolvingReferencesInterceptor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
@ -31,6 +32,13 @@ import org.springframework.stereotype.Service;
|
|||
public class V4Services extends AbstractServices {
|
||||
|
||||
public V4Services() throws Exception {
|
||||
super(ODataVersion.v4);
|
||||
super(ODataServiceVersion.V40);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setInlineCount(final Feed feed, final String count) {
|
||||
if ("true".equals(count)) {
|
||||
feed.setCount(feed.getEntries().size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,20 +16,14 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.olingo.fit.utils;
|
||||
package org.apache.olingo.fit.metadata;
|
||||
|
||||
public enum ODataVersion {
|
||||
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
|
||||
|
||||
v3("3.0"),
|
||||
v4("4.0");
|
||||
public class AbstractMetadataElement {
|
||||
|
||||
private final String version;
|
||||
|
||||
private ODataVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
@Override
|
||||
public String toString() {
|
||||
return ReflectionToStringBuilder.toString(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 org.apache.olingo.fit.metadata;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Association extends AbstractMetadataElement {
|
||||
|
||||
private final String name;
|
||||
|
||||
private Map<String, Role> roles;
|
||||
|
||||
public Association(final String name) {
|
||||
this.name = name;
|
||||
roles = new LinkedHashMap<String, Role>();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Association addRole(final String name, final String type, final String multiplicity) {
|
||||
roles.put(name, new Role(name, type, multiplicity));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Role getRole(final String name) {
|
||||
return roles.get(name);
|
||||
}
|
||||
|
||||
public static class Role {
|
||||
|
||||
final String name;
|
||||
|
||||
final String type;
|
||||
|
||||
final String multiplicity;
|
||||
|
||||
public Role(final String name, final String type, final String multiplicity) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.multiplicity = multiplicity;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getMultiplicity() {
|
||||
return multiplicity;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 org.apache.olingo.fit.metadata;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class AssociationSet extends AbstractMetadataElement {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final String association;
|
||||
|
||||
private Map<String, Role> roles;
|
||||
|
||||
public AssociationSet(final String name, final String association) {
|
||||
this.name = name;
|
||||
this.association = association;
|
||||
roles = new LinkedHashMap<String, Role>();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getAssociation() {
|
||||
return association;
|
||||
}
|
||||
|
||||
public AssociationSet addRole(final String name, final String entitySet) {
|
||||
roles.put(name, new Role(name, entitySet));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Role getRole(final String name) {
|
||||
return roles.get(name);
|
||||
}
|
||||
|
||||
public static class Role {
|
||||
|
||||
final String name;
|
||||
|
||||
final String entitySet;
|
||||
|
||||
public Role(final String name, final String entitySet) {
|
||||
this.name = name;
|
||||
this.entitySet = entitySet;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getEntitySet() {
|
||||
return entitySet;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 org.apache.olingo.fit.metadata;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
public class Container extends AbstractMetadataElement {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final Map<String, EntitySet> entitySets;
|
||||
|
||||
private final Map<String, AssociationSet> associationSets;
|
||||
|
||||
public Container(final String name) {
|
||||
this.name = name;
|
||||
entitySets = new HashMap<String, EntitySet>();
|
||||
associationSets = new HashMap<String, AssociationSet>();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public AssociationSet getAssociationSet(final String association) {
|
||||
return associationSets.get(association);
|
||||
}
|
||||
|
||||
public Collection<EntitySet> getEntitySets() {
|
||||
return entitySets.values();
|
||||
}
|
||||
|
||||
public Collection<EntitySet> getEntitySets(final String namespace, final String entityTypeName) {
|
||||
final Collection<EntitySet> res = new HashSet<EntitySet>();
|
||||
for (EntitySet entitySet : entitySets.values()) {
|
||||
if ((namespace + "." + entityTypeName).equals(entitySet.getType())) {
|
||||
res.add(entitySet);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public EntitySet getEntitySet(final String name) {
|
||||
return entitySets.get(name);
|
||||
}
|
||||
|
||||
public Container addEntitySet(final String name, final EntitySet entitySet) {
|
||||
entitySets.put(name, entitySet);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Container addAssociationSet(final String name, final AssociationSet associationSet) {
|
||||
associationSets.put(name, associationSet);
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 org.apache.olingo.fit.metadata;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class EntitySet extends AbstractMetadataElement {
|
||||
|
||||
private final String name;
|
||||
|
||||
private String type;
|
||||
|
||||
private final boolean singleton;
|
||||
|
||||
// --------------------------
|
||||
// V4 only
|
||||
// --------------------------
|
||||
private final Map<String, String> binding;
|
||||
// --------------------------
|
||||
|
||||
public EntitySet(final String name, final boolean singleton) {
|
||||
this.name = name;
|
||||
this.singleton = singleton;
|
||||
this.binding = new LinkedHashMap<String, String>();
|
||||
}
|
||||
|
||||
public EntitySet(final String name) {
|
||||
this(name, false);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return singleton;
|
||||
}
|
||||
|
||||
public EntitySet addBinding(final String path, final String target) {
|
||||
this.binding.put(path, target);
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getTarget(final String path) {
|
||||
return this.binding.get(path);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 org.apache.olingo.fit.metadata;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
public class EntityType extends AbstractMetadataElement {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final Map<String, Property> properties;
|
||||
|
||||
private final Map<String, NavigationProperty> navigationProperties;
|
||||
|
||||
public EntityType(final String name) {
|
||||
this.name = name;
|
||||
properties = new HashMap<String, Property>();
|
||||
navigationProperties = new HashMap<String, NavigationProperty>();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Collection<NavigationProperty> getNavigationProperties() {
|
||||
return new HashSet<NavigationProperty>(navigationProperties.values());
|
||||
}
|
||||
|
||||
public Map<String, NavigationProperty> getNavigationPropertyMap() {
|
||||
return new HashMap<String, NavigationProperty>(navigationProperties);
|
||||
}
|
||||
|
||||
public Map<String, Property> getPropertyMap() {
|
||||
return new HashMap<String, Property>(properties);
|
||||
}
|
||||
|
||||
public Collection<Property> getProperties() {
|
||||
return new HashSet<Property>(properties.values());
|
||||
}
|
||||
|
||||
public Property getProperty(final String name) {
|
||||
return properties.get(name);
|
||||
}
|
||||
|
||||
public EntityType addProperty(final String name, final Property property) {
|
||||
properties.put(name, property);
|
||||
return this;
|
||||
}
|
||||
|
||||
public NavigationProperty getNavigationProperty(final String name) {
|
||||
return navigationProperties.get(name);
|
||||
}
|
||||
|
||||
public EntityType addNavigationProperty(final String name, final NavigationProperty property) {
|
||||
navigationProperties.put(name, property);
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 org.apache.olingo.fit.metadata;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.events.Attribute;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
import javax.xml.stream.events.XMLEvent;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.codehaus.plexus.util.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Metadata extends AbstractMetadataElement {
|
||||
|
||||
/**
|
||||
* Logger.
|
||||
*/
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(Metadata.class);
|
||||
|
||||
private final Map<String, Schema> schemas;
|
||||
|
||||
public Metadata(final InputStream is) {
|
||||
this.schemas = new HashMap<String, Schema>();
|
||||
|
||||
try {
|
||||
final XMLInputFactory ifactory = XMLInputFactory.newInstance();
|
||||
ifactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, false);
|
||||
final XMLEventReader reader = ifactory.createXMLEventReader(is, "utf-8");
|
||||
|
||||
try {
|
||||
while (reader.hasNext()) {
|
||||
XMLEvent event = reader.nextEvent();
|
||||
|
||||
if (event.isStartElement() && event.asStartElement().getName().equals(new QName("Schema"))) {
|
||||
final Schema schema = getSchema(event.asStartElement(), reader);
|
||||
schemas.put(schema.getNamespace(), schema);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception ignore) {
|
||||
// ignore
|
||||
} finally {
|
||||
reader.close();
|
||||
IOUtils.closeQuietly(is);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error parsing metadata", e);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Schema> schemaEntry : schemas.entrySet()) {
|
||||
for (EntityType entityType : schemaEntry.getValue().getEntityTypes()) {
|
||||
for (NavigationProperty property : entityType.getNavigationProperties()) {
|
||||
if (StringUtils.isNotBlank(property.getReleationship())) {
|
||||
// V3 ...
|
||||
final Association association = schemaEntry.getValue().getAssociation(
|
||||
property.getReleationship().replaceAll(schemaEntry.getKey() + "\\.", ""));
|
||||
final Association.Role role = association.getRole(property.getToRole());
|
||||
property.setFeed(role.getMultiplicity().equals("*"));
|
||||
property.setType(property.isFeed() ? "Collection(" + role.getType() + ")" : role.getType());
|
||||
|
||||
// let me assume that it will be just a single container
|
||||
final AssociationSet associationSet = schemaEntry.getValue().getContainers().iterator().next().
|
||||
getAssociationSet(property.getReleationship());
|
||||
|
||||
final AssociationSet.Role associationSetRole = associationSet.getRole(property.getToRole());
|
||||
property.setTarget(associationSetRole.getEntitySet());
|
||||
} else {
|
||||
// V4 ...
|
||||
property.setFeed(property.getType().startsWith("Collection("));
|
||||
|
||||
final Collection<EntitySet> entitySets = schemaEntry.getValue().getContainers().iterator().next().
|
||||
getEntitySets(schemaEntry.getKey(), entityType.getName());
|
||||
|
||||
final Iterator<EntitySet> iter = entitySets.iterator();
|
||||
boolean found = false;
|
||||
|
||||
while (!found && iter.hasNext()) {
|
||||
final EntitySet entitySet = iter.next();
|
||||
final String target = entitySet.getTarget(property.getName());
|
||||
if (StringUtils.isNotBlank(target)) {
|
||||
property.setTarget(entitySet.getTarget(property.getName()));
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public EntitySet getEntitySet(final String name) {
|
||||
for (Schema schema : getSchemas()) {
|
||||
for (Container container : schema.getContainers()) {
|
||||
final EntitySet entitySet = container.getEntitySet(name);
|
||||
if (entitySet != null) {
|
||||
return entitySet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public EntityType getEntityType(final String fqn) {
|
||||
int lastDotIndex = fqn.lastIndexOf('.');
|
||||
final String ns = fqn.substring(0, lastDotIndex).replaceAll("^#", "");
|
||||
final String name = fqn.substring(lastDotIndex + 1);
|
||||
return getSchema(ns).getEntityType(name);
|
||||
}
|
||||
|
||||
public Map<String, NavigationProperty> getNavigationProperties(final String entitySetName) {
|
||||
|
||||
for (Schema schema : getSchemas()) {
|
||||
for (Container container : schema.getContainers()) {
|
||||
final EntitySet entitySet = container.getEntitySet(entitySetName);
|
||||
if (entitySet != null) {
|
||||
final String entityTypeFQN = entitySet.getType();
|
||||
final int lastDotIndex = entityTypeFQN.lastIndexOf('.');
|
||||
final String entityTypeNS = entityTypeFQN.substring(0, lastDotIndex);
|
||||
final String entityTypeName = entityTypeFQN.substring(lastDotIndex + 1);
|
||||
|
||||
final EntityType entityType = getSchema(entityTypeNS).getEntityType(entityTypeName);
|
||||
|
||||
return entityType.getNavigationPropertyMap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Collection<Schema> getSchemas() {
|
||||
return schemas.values();
|
||||
}
|
||||
|
||||
public Schema getSchema(final String namespace) {
|
||||
return schemas.get(namespace);
|
||||
}
|
||||
|
||||
public Metadata addSchema(final String namespace, final Schema schema) {
|
||||
schemas.put(namespace, schema);
|
||||
return this;
|
||||
}
|
||||
|
||||
private Schema getSchema(final StartElement start, final XMLEventReader reader) throws XMLStreamException {
|
||||
final Schema schema = new Schema(start.getAttributeByName(new QName("Namespace")).getValue());
|
||||
|
||||
boolean completed = false;
|
||||
|
||||
while (!completed && reader.hasNext()) {
|
||||
XMLEvent event = reader.nextEvent();
|
||||
|
||||
if (event.isStartElement() && event.asStartElement().getName().equals(new QName("EntityType"))
|
||||
|| event.isStartElement() && event.asStartElement().getName().equals(new QName("ComplexType"))) {
|
||||
final EntityType entityType = getEntityType(event.asStartElement(), reader);
|
||||
schema.addEntityType(entityType.getName(), entityType);
|
||||
} else if (event.isStartElement() && event.asStartElement().getName().equals(new QName("EntityContainer"))) {
|
||||
final org.apache.olingo.fit.metadata.Container container = getContainer(event.asStartElement(), reader);
|
||||
schema.addContainer(container.getName(), container);
|
||||
} else if (event.isStartElement() && event.asStartElement().getName().equals(new QName("Association"))) {
|
||||
// just for V3
|
||||
final Association association = getAssociation(event.asStartElement(), reader);
|
||||
schema.addAssociation(association.getName(), association);
|
||||
} else if (event.isEndElement() && event.asEndElement().getName().equals(start.getName())) {
|
||||
completed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return schema;
|
||||
}
|
||||
|
||||
private org.apache.olingo.fit.metadata.Container getContainer(
|
||||
final StartElement start, final XMLEventReader reader) throws XMLStreamException {
|
||||
final org.apache.olingo.fit.metadata.Container container =
|
||||
new org.apache.olingo.fit.metadata.Container(start.getAttributeByName(new QName("Name")).getValue());
|
||||
|
||||
boolean completed = false;
|
||||
|
||||
while (!completed && reader.hasNext()) {
|
||||
XMLEvent event = reader.nextEvent();
|
||||
|
||||
if (event.isStartElement()
|
||||
&& (event.asStartElement().getName().equals(new QName("EntitySet"))
|
||||
|| event.asStartElement().getName().equals(new QName("Singleton")))) {
|
||||
final EntitySet entitySet = getEntitySet(event.asStartElement(), reader);
|
||||
container.addEntitySet(entitySet.getName(), entitySet);
|
||||
} else if (event.isStartElement() && event.asStartElement().getName().equals(new QName("AssociationSet"))) {
|
||||
// just for V3
|
||||
final AssociationSet associationSet = getAssociationSet(event.asStartElement(), reader);
|
||||
container.addAssociationSet(associationSet.getAssociation(), associationSet);
|
||||
} else if (event.isEndElement() && event.asEndElement().getName().equals(start.getName())) {
|
||||
completed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
private Association getAssociation(
|
||||
final StartElement start, final XMLEventReader reader) throws XMLStreamException {
|
||||
final Association association = new Association(start.getAttributeByName(new QName("Name")).getValue());
|
||||
|
||||
boolean completed = false;
|
||||
|
||||
while (!completed && reader.hasNext()) {
|
||||
XMLEvent event = reader.nextEvent();
|
||||
|
||||
if (event.isStartElement() && event.asStartElement().getName().equals(new QName("End"))) {
|
||||
final String role = event.asStartElement().getAttributeByName(new QName("Role")).getValue();
|
||||
final String type = event.asStartElement().getAttributeByName(new QName("Type")).getValue();
|
||||
final String multiplicity = event.asStartElement().getAttributeByName(new QName("Multiplicity")).getValue();
|
||||
association.addRole(role, type, multiplicity);
|
||||
} else if (event.isEndElement() && event.asEndElement().getName().equals(start.getName())) {
|
||||
completed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return association;
|
||||
}
|
||||
|
||||
private AssociationSet getAssociationSet(
|
||||
final StartElement start, final XMLEventReader reader) throws XMLStreamException {
|
||||
final AssociationSet associationSet = new AssociationSet(
|
||||
start.getAttributeByName(new QName("Name")).getValue(),
|
||||
start.getAttributeByName(new QName("Association")).getValue());
|
||||
|
||||
boolean completed = false;
|
||||
|
||||
while (!completed && reader.hasNext()) {
|
||||
XMLEvent event = reader.nextEvent();
|
||||
|
||||
if (event.isStartElement() && event.asStartElement().getName().equals(new QName("End"))) {
|
||||
final String role = event.asStartElement().getAttributeByName(new QName("Role")).getValue();
|
||||
final String entitySet = event.asStartElement().getAttributeByName(new QName("EntitySet")).getValue();
|
||||
associationSet.addRole(role, entitySet);
|
||||
} else if (event.isEndElement() && event.asEndElement().getName().equals(start.getName())) {
|
||||
completed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return associationSet;
|
||||
}
|
||||
|
||||
private EntityType getEntityType(final StartElement start, final XMLEventReader reader) throws XMLStreamException {
|
||||
final EntityType entityType = new EntityType(start.getAttributeByName(new QName("Name")).getValue());
|
||||
|
||||
boolean completed = false;
|
||||
|
||||
while (!completed && reader.hasNext()) {
|
||||
XMLEvent event = reader.nextEvent();
|
||||
|
||||
if (event.isStartElement() && event.asStartElement().getName().equals(new QName("Property"))) {
|
||||
final org.apache.olingo.fit.metadata.Property property = getProperty(event.asStartElement());
|
||||
entityType.addProperty(property.getName(), property);
|
||||
} else if (event.isStartElement() && event.asStartElement().getName().equals(new QName("NavigationProperty"))) {
|
||||
final NavigationProperty property = getNavigationProperty(event.asStartElement());
|
||||
entityType.addNavigationProperty(property.getName(), property);
|
||||
} else if (event.isEndElement() && event.asEndElement().getName().equals(start.getName())) {
|
||||
completed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return entityType;
|
||||
}
|
||||
|
||||
private org.apache.olingo.fit.metadata.Property getProperty(final StartElement start) throws XMLStreamException {
|
||||
final org.apache.olingo.fit.metadata.Property property =
|
||||
new org.apache.olingo.fit.metadata.Property(start.getAttributeByName(new QName("Name")).getValue());
|
||||
|
||||
final Attribute type = start.getAttributeByName(new QName("Type"));
|
||||
property.setType(type == null ? "Edm.String" : type.getValue());
|
||||
|
||||
final Attribute nullable = start.getAttributeByName(new QName("Nullable"));
|
||||
property.setNullable(nullable == null || !"false".equals(nullable.getValue()));
|
||||
|
||||
return property;
|
||||
}
|
||||
|
||||
private NavigationProperty getNavigationProperty(final StartElement start) throws XMLStreamException {
|
||||
final NavigationProperty property = new NavigationProperty(start.getAttributeByName(new QName("Name")).getValue());
|
||||
|
||||
final Attribute type = start.getAttributeByName(new QName("Type"));
|
||||
if (type != null) {
|
||||
property.setType(type.getValue());
|
||||
}
|
||||
|
||||
final Attribute relationship = start.getAttributeByName(new QName("Relationship"));
|
||||
if (relationship != null) {
|
||||
property.setReleationship(relationship.getValue());
|
||||
}
|
||||
|
||||
final Attribute toRole = start.getAttributeByName(new QName("ToRole"));
|
||||
if (toRole != null) {
|
||||
property.setToRole(toRole.getValue());
|
||||
}
|
||||
|
||||
return property;
|
||||
}
|
||||
|
||||
private EntitySet getEntitySet(final StartElement start, final XMLEventReader reader) throws XMLStreamException {
|
||||
final EntitySet entitySet = "Singleton".equals(start.getName().getLocalPart())
|
||||
? new EntitySet(start.getAttributeByName(new QName("Name")).getValue(), true)
|
||||
: new EntitySet(start.getAttributeByName(new QName("Name")).getValue());
|
||||
|
||||
Attribute type = start.getAttributeByName(new QName("EntityType"));
|
||||
if (type == null) {
|
||||
type = start.getAttributeByName(new QName("Type"));
|
||||
entitySet.setType(type == null ? null : type.getValue());
|
||||
} else {
|
||||
entitySet.setType(type.getValue());
|
||||
}
|
||||
|
||||
boolean completed = false;
|
||||
|
||||
while (!completed && reader.hasNext()) {
|
||||
XMLEvent event = reader.nextEvent();
|
||||
|
||||
if (event.isStartElement() && event.asStartElement().getName().equals(new QName("NavigationPropertyBinding"))) {
|
||||
final String path = event.asStartElement().getAttributeByName(new QName("Path")).getValue();
|
||||
final String target = event.asStartElement().getAttributeByName(new QName("Target")).getValue();
|
||||
entitySet.addBinding(path, target);
|
||||
} else if (event.isEndElement() && event.asEndElement().getName().equals(start.getName())) {
|
||||
completed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return entitySet;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 org.apache.olingo.fit.metadata;
|
||||
|
||||
public class NavigationProperty extends AbstractMetadataElement {
|
||||
|
||||
private final String name;
|
||||
|
||||
// -----------------------
|
||||
// just for v3
|
||||
// -----------------------
|
||||
private String releationship;
|
||||
|
||||
private String toRole;
|
||||
// -----------------------
|
||||
|
||||
private String type;
|
||||
|
||||
private String target;
|
||||
|
||||
private boolean feed;
|
||||
|
||||
public NavigationProperty(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getReleationship() {
|
||||
return releationship;
|
||||
}
|
||||
|
||||
public void setReleationship(String releationship) {
|
||||
this.releationship = releationship;
|
||||
}
|
||||
|
||||
public String getToRole() {
|
||||
return toRole;
|
||||
}
|
||||
|
||||
public void setToRole(String toRole) {
|
||||
this.toRole = toRole;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public void setTarget(String target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public boolean isFeed() {
|
||||
return feed;
|
||||
}
|
||||
|
||||
public void setFeed(boolean feed) {
|
||||
this.feed = feed;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 org.apache.olingo.fit.metadata;
|
||||
|
||||
public class Property extends AbstractMetadataElement {
|
||||
|
||||
private final String name;
|
||||
|
||||
private String type;
|
||||
|
||||
private boolean nullable;
|
||||
|
||||
public Property(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public boolean isNullable() {
|
||||
return nullable;
|
||||
}
|
||||
|
||||
public void setNullable(boolean nullable) {
|
||||
this.nullable = nullable;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 org.apache.olingo.fit.metadata;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Schema extends AbstractMetadataElement {
|
||||
|
||||
private final String namespace;
|
||||
|
||||
private final Map<String, Container> containers;
|
||||
|
||||
private final Map<String, Association> associations;
|
||||
|
||||
private final Map<String, EntityType> entityTypes;
|
||||
|
||||
public Schema(final String namespace) {
|
||||
this.namespace = namespace;
|
||||
entityTypes = new HashMap<String, EntityType>();
|
||||
this.containers = new HashMap<String, Container>();
|
||||
this.associations = new HashMap<String, Association>();
|
||||
}
|
||||
|
||||
public String getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
public Collection<EntityType> getEntityTypes() {
|
||||
return entityTypes.values();
|
||||
}
|
||||
|
||||
public EntityType getEntityType(final String name) {
|
||||
return entityTypes.get(name);
|
||||
}
|
||||
|
||||
public Schema addEntityType(final String name, final EntityType entityType) {
|
||||
entityTypes.put(name, entityType);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Collection<Container> getContainers() {
|
||||
return containers.values();
|
||||
}
|
||||
|
||||
public Container getContainer(final String name) {
|
||||
return containers.get(name);
|
||||
}
|
||||
|
||||
public Schema addContainer(final String name, final Container container) {
|
||||
containers.put(name, container);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Association getAssociation(final String name) {
|
||||
return associations.get(name);
|
||||
}
|
||||
|
||||
public Schema addAssociation(final String name, final Association association) {
|
||||
associations.put(name, association);
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 org.apache.olingo.fit.serializer;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import java.net.URI;
|
||||
import org.apache.olingo.commons.api.data.Container;
|
||||
import org.apache.olingo.commons.core.data.JSONEntryDeserializer;
|
||||
import org.apache.olingo.commons.core.data.JSONEntrySerializer;
|
||||
|
||||
@JsonDeserialize(using = JSONEntryDeserializer.class)
|
||||
@JsonSerialize(using = JSONEntrySerializer.class)
|
||||
public class JsonEntryContainer<T> extends Container<T> {
|
||||
|
||||
public JsonEntryContainer(final URI contextURL, final String metadataETag, final T object) {
|
||||
super(contextURL, metadataETag, object);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 org.apache.olingo.fit.serializer;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import java.net.URI;
|
||||
import org.apache.olingo.commons.api.data.Container;
|
||||
import org.apache.olingo.commons.core.data.JSONFeedDeserializer;
|
||||
import org.apache.olingo.commons.core.data.JSONFeedSerializer;
|
||||
|
||||
@JsonDeserialize(using = JSONFeedDeserializer.class)
|
||||
@JsonSerialize(using = JSONFeedSerializer.class)
|
||||
public class JsonFeedContainer<T> extends Container<T> {
|
||||
|
||||
public JsonFeedContainer(final URI contextURL, final String metadataETag, final T object) {
|
||||
super(contextURL, metadataETag, object);
|
||||
}
|
||||
}
|
|
@ -38,10 +38,13 @@ import java.util.Set;
|
|||
import javax.ws.rs.NotFoundException;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
|
||||
import org.apache.olingo.fit.metadata.Metadata;
|
||||
import org.apache.olingo.fit.metadata.NavigationProperty;
|
||||
|
||||
public abstract class AbstractJSONUtilities extends AbstractUtilities {
|
||||
|
||||
public AbstractJSONUtilities(final ODataVersion version) throws Exception {
|
||||
public AbstractJSONUtilities(final ODataServiceVersion version) throws Exception {
|
||||
super(version);
|
||||
}
|
||||
|
||||
|
@ -109,6 +112,9 @@ public abstract class AbstractJSONUtilities extends AbstractUtilities {
|
|||
|
||||
final Iterator<Map.Entry<String, JsonNode>> fieldIter = srcNode.fields();
|
||||
|
||||
final Metadata metadata = Commons.getMetadata(version);
|
||||
final Map<String, NavigationProperty> navigationProperties = metadata.getNavigationProperties(entitySetName);
|
||||
|
||||
while (fieldIter.hasNext()) {
|
||||
final Map.Entry<String, JsonNode> field = fieldIter.next();
|
||||
if (field.getKey().endsWith(Constants.get(version, ConstantKey.JSON_NAVIGATION_BIND_SUFFIX))) {
|
||||
|
@ -125,7 +131,7 @@ public abstract class AbstractJSONUtilities extends AbstractUtilities {
|
|||
}
|
||||
|
||||
links.addLinks(title, hrefs);
|
||||
} else if (Commons.linkInfo.get(version).exists(entitySetName, field.getKey())) {
|
||||
} else if (navigationProperties.containsKey(field.getKey())) {
|
||||
links.addInlines(field.getKey(), IOUtils.toInputStream(field.getValue().toString(), "UTf-8"));
|
||||
}
|
||||
}
|
||||
|
@ -170,7 +176,7 @@ public abstract class AbstractJSONUtilities extends AbstractUtilities {
|
|||
|
||||
srcNode.set(
|
||||
Constants.get(version, ConstantKey.JSON_EDITLINK_NAME), new TextNode(
|
||||
Constants.get(version, ConstantKey.DEFAULT_SERVICE_URL) + entitySetName + "(" + entityKey + ")"));
|
||||
Constants.get(version, ConstantKey.DEFAULT_SERVICE_URL) + entitySetName + "(" + entityKey + ")"));
|
||||
|
||||
return IOUtils.toInputStream(srcNode.toString(), "UTf-8");
|
||||
}
|
||||
|
|
|
@ -40,7 +40,10 @@ import javax.ws.rs.core.Response;
|
|||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.vfs2.FileObject;
|
||||
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
|
||||
import org.apache.olingo.fit.UnsupportedMediaTypeException;
|
||||
import org.apache.olingo.fit.metadata.Metadata;
|
||||
import org.apache.olingo.fit.metadata.NavigationProperty;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -51,13 +54,13 @@ public abstract class AbstractUtilities {
|
|||
*/
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(AbstractUtilities.class);
|
||||
|
||||
protected final ODataVersion version;
|
||||
protected final ODataServiceVersion version;
|
||||
|
||||
protected final FSManager fsManager;
|
||||
|
||||
protected final static Pattern entityUriPattern = Pattern.compile(".*\\/.*\\(.*\\)");
|
||||
|
||||
public AbstractUtilities(final ODataVersion version) throws Exception {
|
||||
public AbstractUtilities(final ODataServiceVersion version) throws Exception {
|
||||
this.version = version;
|
||||
this.fsManager = FSManager.instance(version);
|
||||
}
|
||||
|
@ -168,12 +171,15 @@ public abstract class AbstractUtilities {
|
|||
IOUtils.copy(is, bos);
|
||||
IOUtils.closeQuietly(is);
|
||||
|
||||
final Map<String, NavigationProperty> navigationProperties =
|
||||
Commons.getMetadata(version).getNavigationProperties(entitySetName);
|
||||
|
||||
// -----------------------------------------
|
||||
// 0. Retrieve navigation links to be mantained
|
||||
// -----------------------------------------
|
||||
Set<String> linksToBeMantained;
|
||||
try {
|
||||
linksToBeMantained = Commons.linkInfo.get(version).getNavigationLinkNames(entitySetName);
|
||||
linksToBeMantained = new HashSet<String>(navigationProperties.keySet());
|
||||
} catch (Exception e) {
|
||||
linksToBeMantained = Collections.<String>emptySet();
|
||||
}
|
||||
|
@ -195,7 +201,7 @@ public abstract class AbstractUtilities {
|
|||
// 1. Get default entry key and path (N.B. operation will consume/close the stream; use a copy instead)
|
||||
// -----------------------------------------
|
||||
final String entityKey = key == null ? getDefaultEntryKey(
|
||||
entitySetName, new ByteArrayInputStream(bos.toByteArray()), getDefaultFormat()) : key;
|
||||
entitySetName, new ByteArrayInputStream(bos.toByteArray())) : key;
|
||||
|
||||
final String path = Commons.getEntityBasePath(entitySetName, entityKey);
|
||||
// -----------------------------------------
|
||||
|
@ -236,14 +242,13 @@ public abstract class AbstractUtilities {
|
|||
|
||||
// -----------------------------------------
|
||||
// 4. Create links file and provided inlines
|
||||
// -----------------------------------------
|
||||
// -----------------------------------------
|
||||
for (Map.Entry<String, List<String>> link : links.getLinks()) {
|
||||
putLinksInMemory(path, entitySetName, entityKey, link.getKey(), link.getValue());
|
||||
}
|
||||
|
||||
for (Map.Entry<String, List<InputStream>> inlineEntry : links.getInlines()) {
|
||||
final String inlineEntitySetName =
|
||||
Commons.linkInfo.get(version).getTargetName(entitySetName, inlineEntry.getKey());
|
||||
final String inlineEntitySetName = navigationProperties.get(inlineEntry.getKey()).getTarget();
|
||||
|
||||
final List<String> hrefs = new ArrayList<String>();
|
||||
|
||||
|
@ -253,7 +258,7 @@ public abstract class AbstractUtilities {
|
|||
IOUtils.closeQuietly(stream);
|
||||
|
||||
final String inlineEntryKey = getDefaultEntryKey(
|
||||
inlineEntitySetName, new ByteArrayInputStream(inlineBos.toByteArray()), getDefaultFormat());
|
||||
inlineEntitySetName, new ByteArrayInputStream(inlineBos.toByteArray()));
|
||||
|
||||
addOrReplaceEntity(
|
||||
inlineEntryKey,
|
||||
|
@ -270,14 +275,14 @@ public abstract class AbstractUtilities {
|
|||
return fo.getContent().getInputStream();
|
||||
}
|
||||
|
||||
public InputStream addMediaEntity(
|
||||
public void addMediaEntityValue(
|
||||
final String entitySetName,
|
||||
final String entityKey,
|
||||
final InputStream is) throws Exception {
|
||||
|
||||
// -----------------------------------------
|
||||
// 0. Get default entry key and path (N.B. operation will consume/close the stream; use a copy instead)
|
||||
// -----------------------------------------
|
||||
final String entityKey = getDefaultEntryKey(entitySetName, null, getDefaultFormat());
|
||||
final String path = Commons.getEntityBasePath(entitySetName, entityKey);
|
||||
// -----------------------------------------
|
||||
|
||||
|
@ -288,6 +293,17 @@ public abstract class AbstractUtilities {
|
|||
+ Constants.get(version, ConstantKey.MEDIA_CONTENT_FILENAME), null));
|
||||
IOUtils.closeQuietly(is);
|
||||
// -----------------------------------------
|
||||
}
|
||||
|
||||
public InputStream addMediaEntity(
|
||||
final String entitySetName,
|
||||
final InputStream is) throws Exception {
|
||||
|
||||
final String entityKey = getDefaultEntryKey(entitySetName, null);
|
||||
|
||||
addMediaEntityValue(entitySetName, entityKey, is);
|
||||
|
||||
final String path = Commons.getEntityBasePath(entitySetName, entityKey);
|
||||
|
||||
// -----------------------------------------
|
||||
// 2. save entity as atom
|
||||
|
@ -334,7 +350,7 @@ public abstract class AbstractUtilities {
|
|||
|
||||
fsManager.putInMemory(
|
||||
IOUtils.toInputStream(entity), fsManager.getAbsolutePath(path + Constants.get(version, ConstantKey.ENTITY),
|
||||
Accept.JSON_FULLMETA));
|
||||
Accept.JSON_FULLMETA));
|
||||
// -----------------------------------------
|
||||
|
||||
return readEntity(entitySetName, entityKey, getDefaultFormat()).getValue();
|
||||
|
@ -349,7 +365,10 @@ public abstract class AbstractUtilities {
|
|||
|
||||
final HashSet<String> uris = new HashSet<String>();
|
||||
|
||||
if (Commons.linkInfo.get(version).isFeed(entitySetName, linkName)) {
|
||||
final Metadata metadata = Commons.getMetadata(version);
|
||||
final Map<String, NavigationProperty> navigationProperties = metadata.getNavigationProperties(entitySetName);
|
||||
|
||||
if (navigationProperties.get(linkName).isFeed()) {
|
||||
try {
|
||||
final Map.Entry<String, List<String>> currents = extractLinkURIs(entitySetName, entityKey, linkName);
|
||||
uris.addAll(currents.getValue());
|
||||
|
@ -383,8 +402,8 @@ public abstract class AbstractUtilities {
|
|||
public Response createResponse(
|
||||
final InputStream entity, final String etag, final Accept accept, final Response.Status status) {
|
||||
final Response.ResponseBuilder builder = Response.ok();
|
||||
if (version == ODataVersion.v3) {
|
||||
builder.header(Constants.get(version, ConstantKey.ODATA_SERVICE_VERSION), version.getVersion() + ";");
|
||||
if (version.compareTo(ODataServiceVersion.V30) <= 0) {
|
||||
builder.header(Constants.get(version, ConstantKey.ODATA_SERVICE_VERSION), version.toString() + ";");
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(etag)) {
|
||||
|
@ -432,7 +451,7 @@ public abstract class AbstractUtilities {
|
|||
LOG.debug("Create fault response about .... ", e);
|
||||
|
||||
final Response.ResponseBuilder builder = Response.serverError();
|
||||
if (version == ODataVersion.v3) {
|
||||
if (version.compareTo(ODataServiceVersion.V30) <= 0) {
|
||||
builder.header(Constants.get(version, ConstantKey.ODATA_SERVICE_VERSION), version + ";");
|
||||
}
|
||||
|
||||
|
@ -441,7 +460,7 @@ public abstract class AbstractUtilities {
|
|||
if (accept.startsWith("application/json")) {
|
||||
ext = ".json";
|
||||
contentType = Accept.JSON;
|
||||
} else if (accept.startsWith("application/xml") || version == ODataVersion.v3) {
|
||||
} else if (accept.startsWith("application/xml") || version.compareTo(ODataServiceVersion.V30) <= 0) {
|
||||
ext = ".xml";
|
||||
contentType = Accept.XML;
|
||||
} else {
|
||||
|
@ -470,8 +489,8 @@ public abstract class AbstractUtilities {
|
|||
return builder.build();
|
||||
}
|
||||
|
||||
protected String getDefaultEntryKey(
|
||||
final String entitySetName, final InputStream entity, final Accept accept) throws IOException {
|
||||
public String getDefaultEntryKey(
|
||||
final String entitySetName, final InputStream entity) throws IOException {
|
||||
try {
|
||||
String res;
|
||||
|
||||
|
@ -649,7 +668,10 @@ public abstract class AbstractUtilities {
|
|||
|
||||
final LinkInfo linkInfo = new LinkInfo(fsManager.readFile(basePath + linkName, accept));
|
||||
linkInfo.setEtag(Commons.getETag(basePath, version));
|
||||
linkInfo.setFeed(Commons.linkInfo.get(version).isFeed(entitySetName, linkName));
|
||||
final Metadata metadata = Commons.getMetadata(version);
|
||||
final Map<String, NavigationProperty> navigationProperties = metadata.getNavigationProperties(entitySetName);
|
||||
|
||||
linkInfo.setFeed(navigationProperties.get(linkName.replaceAll("\\(.*\\)", "")).isFeed());
|
||||
|
||||
return linkInfo;
|
||||
}
|
||||
|
@ -695,31 +717,38 @@ public abstract class AbstractUtilities {
|
|||
public InputStream expandEntity(
|
||||
final String entitySetName,
|
||||
final String entityId,
|
||||
final InputStream entity,
|
||||
final String linkName)
|
||||
throws Exception {
|
||||
|
||||
// --------------------------------
|
||||
// 0. Retrieve all 'linkName' navigation link uris (NotFoundException if missing)
|
||||
// --------------------------------
|
||||
final LinkInfo linkInfo = readLinks(entitySetName, entityId, linkName, Accept.XML);
|
||||
final Map.Entry<String, List<String>> links = extractLinkURIs(entitySetName, entityId, linkName);
|
||||
// --------------------------------
|
||||
|
||||
// --------------------------------
|
||||
// 1. Retrieve expanded object (entry or feed)
|
||||
// --------------------------------
|
||||
final InputStream expanded = readEntities(
|
||||
final Metadata metadata = Commons.getMetadata(version);
|
||||
final Map<String, NavigationProperty> navigationProperties = metadata.getNavigationProperties(entitySetName);
|
||||
|
||||
return readEntities(
|
||||
links.getValue(),
|
||||
linkName,
|
||||
links.getKey(),
|
||||
linkInfo.isFeed());
|
||||
// --------------------------------
|
||||
navigationProperties.get(linkName).isFeed());
|
||||
}
|
||||
|
||||
public InputStream expandEntity(
|
||||
final String entitySetName,
|
||||
final String entityId,
|
||||
final InputStream entity,
|
||||
final String linkName)
|
||||
throws Exception {
|
||||
// --------------------------------
|
||||
// 2. Retrieve expanded object (entry or feed)
|
||||
// --------------------------------
|
||||
return replaceLink(entity, linkName, expanded);
|
||||
return replaceLink(entity, linkName, expandEntity(entitySetName, entityId, linkName));
|
||||
// --------------------------------
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,9 @@ import org.apache.commons.io.IOUtils;
|
|||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.vfs2.FileObject;
|
||||
import org.apache.commons.vfs2.FileSystemException;
|
||||
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
|
||||
import org.apache.olingo.fit.metadata.Metadata;
|
||||
import org.apache.olingo.fit.metadata.NavigationProperty;
|
||||
|
||||
public abstract class AbstractXMLUtilities extends AbstractUtilities {
|
||||
|
||||
|
@ -59,12 +62,10 @@ public abstract class AbstractXMLUtilities extends AbstractUtilities {
|
|||
|
||||
protected static XMLOutputFactory ofactory = null;
|
||||
|
||||
public AbstractXMLUtilities(final ODataVersion version) throws Exception {
|
||||
public AbstractXMLUtilities(final ODataServiceVersion version) throws Exception {
|
||||
super(version);
|
||||
}
|
||||
|
||||
public abstract void retrieveLinkInfoFromMetadata() throws Exception;
|
||||
|
||||
@Override
|
||||
protected Accept getDefaultFormat() {
|
||||
return Accept.ATOM;
|
||||
|
@ -146,6 +147,9 @@ public abstract class AbstractXMLUtilities extends AbstractUtilities {
|
|||
|
||||
writer.add(entry.getValue().getStart());
|
||||
|
||||
final Metadata metadata = Commons.getMetadata(version);
|
||||
final Map<String, NavigationProperty> navigationProperties = metadata.getNavigationProperties(entitySetName);
|
||||
|
||||
// add for links
|
||||
for (String link : links) {
|
||||
final Set<Attribute> attributes = new HashSet<Attribute>();
|
||||
|
@ -155,7 +159,7 @@ public abstract class AbstractXMLUtilities extends AbstractUtilities {
|
|||
attributes.add(eventFactory.createAttribute(new QName("rel"),
|
||||
Constants.get(version, ConstantKey.ATOM_LINK_REL) + link));
|
||||
attributes.add(eventFactory.createAttribute(new QName("type"),
|
||||
Commons.linkInfo.get(version).isFeed(entitySetName, link)
|
||||
navigationProperties.get(link).isFeed()
|
||||
? Constants.get(version, ConstantKey.ATOM_LINK_FEED)
|
||||
: Constants.get(version, ConstantKey.ATOM_LINK_ENTRY)));
|
||||
|
||||
|
@ -192,7 +196,7 @@ public abstract class AbstractXMLUtilities extends AbstractUtilities {
|
|||
while (true) {
|
||||
final Map.Entry<Integer, XmlElement> linkInfo =
|
||||
extractElement(reader, null,
|
||||
Collections.<String>singletonList(Constants.get(version, ConstantKey.LINK)), startDepth, 2, 2);
|
||||
Collections.<String>singletonList(Constants.get(version, ConstantKey.LINK)), startDepth, 2, 2);
|
||||
|
||||
startDepth = linkInfo.getKey();
|
||||
|
||||
|
@ -243,7 +247,7 @@ public abstract class AbstractXMLUtilities extends AbstractUtilities {
|
|||
try {
|
||||
final XmlElement inlineElement =
|
||||
extractElement(link.getContentReader(), null,
|
||||
Collections.<String>singletonList(Constants.get(version, ConstantKey.INLINE)), 0, -1, -1).
|
||||
Collections.<String>singletonList(Constants.get(version, ConstantKey.INLINE)), 0, -1, -1).
|
||||
getValue();
|
||||
final XMLEventReader inlineReader = inlineElement.getContentReader();
|
||||
|
||||
|
@ -447,7 +451,7 @@ public abstract class AbstractXMLUtilities extends AbstractUtilities {
|
|||
// check edit link existence
|
||||
extractElement(reader, writer, Collections.<String>singletonList(Constants.get(version, ConstantKey.LINK)),
|
||||
Collections.<Map.Entry<String, String>>singletonList(
|
||||
new AbstractMap.SimpleEntry<String, String>("rel", "edit")), false, 0, -1, -1);
|
||||
new AbstractMap.SimpleEntry<String, String>("rel", "edit")), false, 0, -1, -1);
|
||||
|
||||
addAtomElement(IOUtils.toInputStream(editLinkElement), writer);
|
||||
writer.add(reader);
|
||||
|
@ -540,7 +544,7 @@ public abstract class AbstractXMLUtilities extends AbstractUtilities {
|
|||
try {
|
||||
final XmlElement entryElement =
|
||||
extractElement(reader, writer, Collections.<String>singletonList(
|
||||
Constants.get(version, ConstantKey.PROPERTIES)), 0, 2, 3).getValue();
|
||||
Constants.get(version, ConstantKey.PROPERTIES)), 0, 2, 3).getValue();
|
||||
|
||||
addAtomElement(
|
||||
IOUtils.toInputStream("<content type=\"application/xml\">"),
|
||||
|
@ -795,7 +799,7 @@ public abstract class AbstractXMLUtilities extends AbstractUtilities {
|
|||
if (event.getEventType() == XMLStreamConstants.START_ELEMENT
|
||||
&& Constants.get(version, ConstantKey.LINK).equals(event.asStartElement().getName().getLocalPart())
|
||||
&& !fieldToBeSaved.contains(
|
||||
event.asStartElement().getAttributeByName(new QName("title")).getValue())
|
||||
event.asStartElement().getAttributeByName(new QName("title")).getValue())
|
||||
&& !"edit".equals(event.asStartElement().getAttributeByName(new QName("rel")).getValue())) {
|
||||
writeCurrent = false;
|
||||
} else if (event.getEventType() == XMLStreamConstants.END_ELEMENT
|
||||
|
@ -803,13 +807,13 @@ public abstract class AbstractXMLUtilities extends AbstractUtilities {
|
|||
writeNext = true;
|
||||
} else if (event.getEventType() == XMLStreamConstants.START_ELEMENT
|
||||
&& (Constants.get(version, ConstantKey.PROPERTIES)).equals(
|
||||
event.asStartElement().getName().getLocalPart())) {
|
||||
event.asStartElement().getName().getLocalPart())) {
|
||||
writeCurrent = true;
|
||||
writeNext = false;
|
||||
inProperties = true;
|
||||
} else if (event.getEventType() == XMLStreamConstants.END_ELEMENT
|
||||
&& (Constants.get(version, ConstantKey.PROPERTIES)).equals(
|
||||
event.asEndElement().getName().getLocalPart())) {
|
||||
event.asEndElement().getName().getLocalPart())) {
|
||||
writeCurrent = true;
|
||||
} else if (inProperties) {
|
||||
if (event.getEventType() == XMLStreamConstants.START_ELEMENT) {
|
||||
|
@ -826,7 +830,7 @@ public abstract class AbstractXMLUtilities extends AbstractUtilities {
|
|||
} else if (event.getEventType() == XMLStreamConstants.END_ELEMENT
|
||||
&& StringUtils.isNotBlank(currentName)
|
||||
&& (Constants.get(version, ConstantKey.ATOM_PROPERTY_PREFIX) + currentName.trim()).equals(
|
||||
event.asEndElement().getName().getLocalPart())) {
|
||||
event.asEndElement().getName().getLocalPart())) {
|
||||
writeNext = false;
|
||||
currentName = null;
|
||||
}
|
||||
|
@ -894,10 +898,10 @@ public abstract class AbstractXMLUtilities extends AbstractUtilities {
|
|||
|
||||
final XmlElement entry =
|
||||
extractElement(
|
||||
getEventReader(readEntity(uri.getKey(), uri.getValue(), Accept.ATOM).getValue()),
|
||||
null,
|
||||
Collections.<String>singletonList("entry"),
|
||||
0, 1, 1).getValue();
|
||||
getEventReader(readEntity(uri.getKey(), uri.getValue(), Accept.ATOM).getValue()),
|
||||
null,
|
||||
Collections.<String>singletonList("entry"),
|
||||
0, 1, 1).getValue();
|
||||
|
||||
IOUtils.copy(entry.toStream(), writer, encoding);
|
||||
} catch (Exception e) {
|
||||
|
@ -934,7 +938,7 @@ public abstract class AbstractXMLUtilities extends AbstractUtilities {
|
|||
|
||||
final Map.Entry<Integer, XmlElement> propertyElement =
|
||||
extractElement(reader, null,
|
||||
Collections.<String>singletonList(Constants.get(version, ConstantKey.PROPERTIES)), 0, 2, 3);
|
||||
Collections.<String>singletonList(Constants.get(version, ConstantKey.PROPERTIES)), 0, 2, 3);
|
||||
reader.close();
|
||||
|
||||
reader = propertyElement.getValue().getContentReader();
|
||||
|
@ -958,7 +962,7 @@ public abstract class AbstractXMLUtilities extends AbstractUtilities {
|
|||
while (true) {
|
||||
final Map.Entry<Integer, XmlElement> linkElement =
|
||||
extractElement(reader, null,
|
||||
Collections.<String>singletonList(Constants.get(version, ConstantKey.LINK)), pos, 2, 2);
|
||||
Collections.<String>singletonList(Constants.get(version, ConstantKey.LINK)), pos, 2, 2);
|
||||
|
||||
res.put("[Constants.get(version, ConstantKey.LINK)]"
|
||||
+ linkElement.getValue().getStart().getAttributeByName(new QName("title")).getValue(),
|
||||
|
@ -988,7 +992,7 @@ public abstract class AbstractXMLUtilities extends AbstractUtilities {
|
|||
// ---------------------------------
|
||||
Map.Entry<Integer, XmlElement> propertyElement =
|
||||
extractElement(reader, writer,
|
||||
Collections.<String>singletonList(Constants.get(version, ConstantKey.PROPERTIES)), 0, 2, 3);
|
||||
Collections.<String>singletonList(Constants.get(version, ConstantKey.PROPERTIES)), 0, 2, 3);
|
||||
|
||||
writer.flush();
|
||||
|
||||
|
@ -1121,9 +1125,9 @@ public abstract class AbstractXMLUtilities extends AbstractUtilities {
|
|||
try {
|
||||
final XmlElement linkElement =
|
||||
extractElement(reader, writer,
|
||||
Collections.<String>singletonList(Constants.get(version, ConstantKey.LINK)),
|
||||
Collections.<Map.Entry<String, String>>singletonList(
|
||||
new SimpleEntry<String, String>("title", linkName)), false, 0, -1, -1).getValue();
|
||||
Collections.<String>singletonList(Constants.get(version, ConstantKey.LINK)),
|
||||
Collections.<Map.Entry<String, String>>singletonList(
|
||||
new SimpleEntry<String, String>("title", linkName)), false, 0, -1, -1).getValue();
|
||||
writer.add(linkElement.getStart());
|
||||
|
||||
// ------------------------------------------
|
||||
|
@ -1234,7 +1238,7 @@ public abstract class AbstractXMLUtilities extends AbstractUtilities {
|
|||
|
||||
final InputStream src =
|
||||
fsManager.readFile(Commons.getEntityBasePath(entitySetName, entityId)
|
||||
+ Constants.get(version, ConstantKey.ENTITY), Accept.XML);
|
||||
+ Constants.get(version, ConstantKey.ENTITY), Accept.XML);
|
||||
|
||||
final XMLEventReader reader = getEventReader(src);
|
||||
final XmlElement property = extractElement(reader, null, pathElements, 0, 3, 4).getValue();
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.apache.olingo.fit.utils;
|
|||
import java.util.regex.Pattern;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
|
||||
import org.apache.olingo.fit.UnsupportedMediaTypeException;
|
||||
|
||||
public enum Accept {
|
||||
|
@ -55,17 +56,17 @@ public enum Accept {
|
|||
this.fileExtension = fileExtension;
|
||||
}
|
||||
|
||||
public String toString(final ODataVersion version) {
|
||||
return ODataVersion.v3 == version ? contentTypeV3 : contentTypeV4;
|
||||
public String toString(final ODataServiceVersion version) {
|
||||
return version.compareTo(ODataServiceVersion.V40) >= 0 ? contentTypeV4 : contentTypeV3;
|
||||
}
|
||||
|
||||
public String getExtension() {
|
||||
return fileExtension;
|
||||
}
|
||||
|
||||
public static Accept parse(final String contentType, final ODataVersion version) {
|
||||
public static Accept parse(final String contentType, final ODataServiceVersion version) {
|
||||
final Accept def;
|
||||
if (ODataVersion.v3 == version) {
|
||||
if (version.compareTo(ODataServiceVersion.V30) <= 0) {
|
||||
def = ATOM;
|
||||
} else {
|
||||
def = JSON_NOMETA;
|
||||
|
@ -74,7 +75,7 @@ public enum Accept {
|
|||
return parse(contentType, version, def);
|
||||
}
|
||||
|
||||
public static Accept parse(final String contentType, final ODataVersion version, final Accept def) {
|
||||
public static Accept parse(final String contentType, final ODataServiceVersion version, final Accept def) {
|
||||
if (StringUtils.isBlank(contentType) || allTypesPattern.matcher(contentType).matches()) {
|
||||
return def;
|
||||
} else if (JSON_NOMETA.toString(version).equals(contentType)) {
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
package org.apache.olingo.fit.utils;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.databind.InjectableValues;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
|
@ -39,6 +41,11 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
|
||||
import org.apache.olingo.commons.core.data.AtomDeserializer;
|
||||
import org.apache.olingo.commons.core.data.AtomSerializer;
|
||||
import org.apache.olingo.commons.core.op.InjectableSerializerProvider;
|
||||
import org.apache.olingo.fit.metadata.Metadata;
|
||||
import org.codehaus.plexus.util.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -50,15 +57,24 @@ public abstract class Commons {
|
|||
*/
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(Commons.class);
|
||||
|
||||
private static Map<ODataServiceVersion, AtomDeserializer> atomDeserializer =
|
||||
new EnumMap<ODataServiceVersion, AtomDeserializer>(ODataServiceVersion.class);
|
||||
|
||||
private static Map<ODataServiceVersion, AtomSerializer> atomSerializer =
|
||||
new EnumMap<ODataServiceVersion, AtomSerializer>(ODataServiceVersion.class);
|
||||
|
||||
private static Map<ODataServiceVersion, ObjectMapper> jsonmapper =
|
||||
new EnumMap<ODataServiceVersion, ObjectMapper>(ODataServiceVersion.class);
|
||||
|
||||
private static EnumMap<ODataServiceVersion, Metadata> metadata =
|
||||
new EnumMap<ODataServiceVersion, Metadata>(ODataServiceVersion.class);
|
||||
|
||||
protected static Pattern multiKeyPattern = Pattern.compile("(.*=.*,?)+");
|
||||
|
||||
protected final static Map<String, Integer> sequence = new HashMap<String, Integer>();
|
||||
|
||||
protected final static Map<String, String> mediaContent = new HashMap<String, String>();
|
||||
|
||||
protected final static Map<ODataVersion, MetadataLinkInfo> linkInfo =
|
||||
new EnumMap<ODataVersion, MetadataLinkInfo>(ODataVersion.class);
|
||||
|
||||
static {
|
||||
sequence.put("Customer", 1000);
|
||||
sequence.put("CustomerInfo", 1000);
|
||||
|
@ -75,8 +91,56 @@ public abstract class Commons {
|
|||
mediaContent.put("Car/Photo", null);
|
||||
}
|
||||
|
||||
public static Map<ODataVersion, MetadataLinkInfo> getLinkInfo() {
|
||||
return linkInfo;
|
||||
public static AtomDeserializer getAtomDeserializer(final ODataServiceVersion version) {
|
||||
if (!atomDeserializer.containsKey(version)) {
|
||||
atomDeserializer.put(version, new AtomDeserializer(version));
|
||||
}
|
||||
return atomDeserializer.get(version);
|
||||
}
|
||||
|
||||
public static AtomSerializer getAtomSerializer(final ODataServiceVersion version) {
|
||||
if (!atomSerializer.containsKey(version)) {
|
||||
atomSerializer.put(version, new AtomSerializer(version, true));
|
||||
}
|
||||
|
||||
return atomSerializer.get(version);
|
||||
}
|
||||
|
||||
public static ObjectMapper getJsonMapper(final ODataServiceVersion version) {
|
||||
if (!jsonmapper.containsKey(version)) {
|
||||
final ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
||||
|
||||
mapper.setInjectableValues(new InjectableValues.Std()
|
||||
.addValue(Boolean.class, Boolean.TRUE)
|
||||
.addValue(ODataServiceVersion.class, version));
|
||||
|
||||
mapper.setSerializerProvider(new InjectableSerializerProvider(mapper.getSerializerProvider(),
|
||||
mapper.getSerializationConfig()
|
||||
.withAttribute(ODataServiceVersion.class, version)
|
||||
.withAttribute(Boolean.class, Boolean.TRUE),
|
||||
mapper.getSerializerFactory()));
|
||||
|
||||
jsonmapper.put(version, mapper);
|
||||
}
|
||||
|
||||
return jsonmapper.get(version);
|
||||
}
|
||||
|
||||
public static Metadata getMetadata(final ODataServiceVersion version) {
|
||||
if (!metadata.containsKey(version)) {
|
||||
final InputStream is = Commons.class.getResourceAsStream(
|
||||
File.separatorChar
|
||||
+ version.name()
|
||||
+ File.separatorChar + "metadata.xml");
|
||||
|
||||
metadata.put(version, new Metadata(is));
|
||||
}
|
||||
|
||||
return metadata.get(version);
|
||||
}
|
||||
|
||||
public static Map<String, String> getMediaContent() {
|
||||
return mediaContent;
|
||||
}
|
||||
|
||||
public static String getEntityURI(final String entitySetName, final String entityKey) {
|
||||
|
@ -91,7 +155,7 @@ public abstract class Commons {
|
|||
}
|
||||
|
||||
public static String getLinksURI(
|
||||
final ODataVersion version,
|
||||
final ODataServiceVersion version,
|
||||
final String entitySetName,
|
||||
final String entityId,
|
||||
final String linkName) throws IOException {
|
||||
|
@ -99,22 +163,22 @@ public abstract class Commons {
|
|||
}
|
||||
|
||||
public static String getLinksPath(
|
||||
final ODataVersion version,
|
||||
final ODataServiceVersion version,
|
||||
final String entitySetName,
|
||||
final String entityId,
|
||||
final String linkName,
|
||||
final Accept accept) throws IOException {
|
||||
return getLinksPath(ODataVersion.v3, getEntityBasePath(entitySetName, entityId), linkName, accept);
|
||||
return getLinksPath(ODataServiceVersion.V30, getEntityBasePath(entitySetName, entityId), linkName, accept);
|
||||
|
||||
}
|
||||
|
||||
public static String getLinksPath(
|
||||
final ODataVersion version, final String basePath, final String linkName, final Accept accept)
|
||||
final ODataServiceVersion version, final String basePath, final String linkName, final Accept accept)
|
||||
throws IOException {
|
||||
try {
|
||||
return FSManager.instance(version)
|
||||
.getAbsolutePath(basePath + Constants.get(version, ConstantKey.LINKS_FILE_PATH)
|
||||
+ File.separatorChar + linkName, accept);
|
||||
+ File.separatorChar + linkName, accept);
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
@ -255,7 +319,7 @@ public abstract class Commons {
|
|||
return node;
|
||||
}
|
||||
|
||||
public static String getETag(final String basePath, final ODataVersion version) throws Exception {
|
||||
public static String getETag(final String basePath, final ODataServiceVersion version) throws Exception {
|
||||
try {
|
||||
final InputStream is = FSManager.instance(version).readFile(basePath + "etag", Accept.TEXT);
|
||||
if (is.available() <= 0) {
|
||||
|
|
|
@ -18,8 +18,10 @@
|
|||
*/
|
||||
package org.apache.olingo.fit.utils;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
|
||||
|
||||
public class Constants {
|
||||
|
||||
|
@ -27,6 +29,8 @@ public class Constants {
|
|||
|
||||
private final static Map<ConstantKey, String> constants = new EnumMap<ConstantKey, String>(ConstantKey.class);
|
||||
|
||||
public static Charset encoding = Charset.forName("UTF-8");
|
||||
|
||||
static {
|
||||
|
||||
// -----------------------------
|
||||
|
@ -93,8 +97,8 @@ public class Constants {
|
|||
return get(null, key);
|
||||
}
|
||||
|
||||
public static String get(final ODataVersion version, final ConstantKey key) {
|
||||
return (version == null || version == ODataVersion.v3 || !v4constants.containsKey(key)
|
||||
public static String get(final ODataServiceVersion version, final ConstantKey key) {
|
||||
return (version == null || version.compareTo(ODataServiceVersion.V30) <= 0 || !v4constants.containsKey(key)
|
||||
? constants : v4constants).get(key);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 org.apache.olingo.fit.utils;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.olingo.commons.api.data.Entry;
|
||||
import org.apache.olingo.commons.api.data.Feed;
|
||||
import org.apache.olingo.commons.api.data.Link;
|
||||
import org.apache.olingo.commons.api.data.Property;
|
||||
import org.apache.olingo.commons.api.data.Value;
|
||||
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
|
||||
import org.apache.olingo.commons.core.data.AtomEntryImpl;
|
||||
import org.apache.olingo.commons.core.data.AtomFeedImpl;
|
||||
import org.apache.olingo.commons.core.data.AtomPropertyImpl;
|
||||
import org.apache.olingo.commons.core.data.CollectionValueImpl;
|
||||
import org.apache.olingo.commons.core.data.ComplexValueImpl;
|
||||
import org.apache.olingo.commons.core.data.JSONEntryImpl;
|
||||
import org.apache.olingo.commons.core.data.JSONFeedImpl;
|
||||
import org.apache.olingo.commons.core.data.JSONPropertyImpl;
|
||||
import org.apache.olingo.commons.core.data.LinkImpl;
|
||||
import org.apache.olingo.fit.metadata.Metadata;
|
||||
import org.apache.olingo.fit.metadata.NavigationProperty;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
public class DataBinder {
|
||||
|
||||
private final ODataServiceVersion version;
|
||||
|
||||
public DataBinder(final ODataServiceVersion version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public JSONFeedImpl getJsonFeed(final AtomFeedImpl atomfeed) {
|
||||
final JSONFeedImpl jsonfeed = new JSONFeedImpl();
|
||||
|
||||
BeanUtils.copyProperties(atomfeed, jsonfeed, "baseURI", "metadataContextURL");
|
||||
jsonfeed.setMetadataContextURL(atomfeed.getBaseURI() == null
|
||||
? null
|
||||
: URI.create(atomfeed.getBaseURI().toASCIIString() + "/$metadata").normalize());
|
||||
|
||||
final Collection<Entry> entries = jsonfeed.getEntries();
|
||||
for (Entry entry : atomfeed.getEntries()) {
|
||||
entries.add(getJsonEntry((AtomEntryImpl) entry));
|
||||
}
|
||||
|
||||
return jsonfeed;
|
||||
}
|
||||
|
||||
public AtomFeedImpl getAtomFeed(final JSONFeedImpl jsonfeed) {
|
||||
final AtomFeedImpl atomfeed = new AtomFeedImpl();
|
||||
|
||||
BeanUtils.copyProperties(jsonfeed, atomfeed, "baseURI", "metadataContextURL");
|
||||
atomfeed.setBaseURI(jsonfeed.getBaseURI() == null
|
||||
? null
|
||||
: jsonfeed.getBaseURI().toASCIIString() + "/$metadata");
|
||||
|
||||
final Collection<Entry> entries = atomfeed.getEntries();
|
||||
for (Entry entry : jsonfeed.getEntries()) {
|
||||
entries.add(getAtomEntry((JSONEntryImpl) entry));
|
||||
}
|
||||
|
||||
return atomfeed;
|
||||
}
|
||||
|
||||
public JSONEntryImpl getJsonEntry(final AtomEntryImpl atomentry) {
|
||||
final JSONEntryImpl jsonentry = new JSONEntryImpl();
|
||||
|
||||
BeanUtils.copyProperties(atomentry, jsonentry, "baseURI", "properties", "links");
|
||||
jsonentry.setBaseURI(atomentry.getBaseURI() == null ? null : atomentry.getBaseURI().toASCIIString());
|
||||
|
||||
for (Link link : atomentry.getNavigationLinks()) {
|
||||
|
||||
final Link jlink = new LinkImpl();
|
||||
jlink.setHref(link.getHref());
|
||||
jlink.setTitle(link.getTitle());
|
||||
jlink.setType(link.getType());
|
||||
jlink.setRel(link.getRel());
|
||||
|
||||
if (link.getInlineEntry() instanceof AtomEntryImpl) {
|
||||
Entry inlineEntry = link.getInlineEntry();
|
||||
if (inlineEntry instanceof AtomEntryImpl) {
|
||||
jlink.setInlineEntry(getJsonEntry((AtomEntryImpl) link.getInlineEntry()));
|
||||
}
|
||||
} else if (link.getInlineFeed() instanceof AtomFeedImpl) {
|
||||
|
||||
Feed inlineFeed = link.getInlineFeed();
|
||||
if (inlineFeed instanceof AtomFeedImpl) {
|
||||
jlink.setInlineFeed(getJsonFeed((AtomFeedImpl) link.getInlineFeed()));
|
||||
}
|
||||
}
|
||||
|
||||
jsonentry.getNavigationLinks().add(jlink);
|
||||
}
|
||||
|
||||
final Collection<Property> properties = jsonentry.getProperties();
|
||||
for (Property property : atomentry.getProperties()) {
|
||||
properties.add(getJsonProperty((AtomPropertyImpl) property));
|
||||
}
|
||||
|
||||
return jsonentry;
|
||||
}
|
||||
|
||||
public AtomEntryImpl getAtomEntry(final JSONEntryImpl jsonentry) {
|
||||
final AtomEntryImpl atomentry = new AtomEntryImpl();
|
||||
|
||||
final Metadata metadata = Commons.getMetadata(version);
|
||||
|
||||
BeanUtils.copyProperties(jsonentry, atomentry, "baseURI", "properties", "links");
|
||||
atomentry.setBaseURI(jsonentry.getBaseURI() == null ? null : jsonentry.getBaseURI().toASCIIString());
|
||||
|
||||
for (Link link : jsonentry.getNavigationLinks()) {
|
||||
final Link alink = new LinkImpl();
|
||||
alink.setHref(link.getHref());
|
||||
alink.setTitle(link.getTitle());
|
||||
alink.setType(metadata.getEntityType(jsonentry.getType()).getNavigationProperty(link.getTitle()).isFeed()
|
||||
? Constants.get(ConstantKey.ATOM_LINK_FEED) : Constants.get(ConstantKey.ATOM_LINK_ENTRY));
|
||||
alink.setRel(link.getRel());
|
||||
|
||||
if (link.getInlineEntry() instanceof JSONEntryImpl) {
|
||||
Entry inlineEntry = link.getInlineEntry();
|
||||
if (inlineEntry instanceof JSONEntryImpl) {
|
||||
alink.setInlineEntry(getAtomEntry((JSONEntryImpl) link.getInlineEntry()));
|
||||
}
|
||||
} else if (link.getInlineFeed() instanceof JSONFeedImpl) {
|
||||
Feed inlineFeed = link.getInlineFeed();
|
||||
if (inlineFeed instanceof JSONFeedImpl) {
|
||||
alink.setInlineFeed(getAtomFeed((JSONFeedImpl) link.getInlineFeed()));
|
||||
}
|
||||
}
|
||||
|
||||
atomentry.getNavigationLinks().add(alink);
|
||||
}
|
||||
|
||||
final Map<String, NavigationProperty> navProperties =
|
||||
metadata.getEntityType(jsonentry.getType()).getNavigationPropertyMap();
|
||||
|
||||
final List<Property> properties = atomentry.getProperties();
|
||||
|
||||
for (Property property : jsonentry.getProperties()) {
|
||||
if (navProperties.containsKey(property.getName())) {
|
||||
final Link alink = new LinkImpl();
|
||||
alink.setTitle(property.getName());
|
||||
|
||||
alink.setType(navProperties.get(property.getName()).isFeed()
|
||||
? Constants.get(ConstantKey.ATOM_LINK_FEED)
|
||||
: Constants.get(ConstantKey.ATOM_LINK_ENTRY));
|
||||
|
||||
alink.setRel(Constants.get(ConstantKey.ATOM_LINK_REL) + property.getName());
|
||||
|
||||
if (property.getValue().isComplex()) {
|
||||
final Entry inline = new AtomEntryImpl();
|
||||
inline.setType(navProperties.get(property.getName()).getType());
|
||||
for (Property prop : property.getValue().asComplex().get()) {
|
||||
inline.getProperties().add(prop);
|
||||
}
|
||||
alink.setInlineEntry(inline);
|
||||
|
||||
} else if (property.getValue().isCollection()) {
|
||||
final Feed inline = new AtomFeedImpl();
|
||||
for (Value entry : property.getValue().asCollection().get()) {
|
||||
final Entry inlineEntry = new AtomEntryImpl();
|
||||
inlineEntry.setType(navProperties.get(property.getName()).getType());
|
||||
for (Property prop : entry.asComplex().get()) {
|
||||
inlineEntry.getProperties().add(prop);
|
||||
}
|
||||
inline.getEntries().add(inlineEntry);
|
||||
}
|
||||
alink.setInlineFeed(inline);
|
||||
} else {
|
||||
throw new IllegalStateException("Invalid navigation property " + property);
|
||||
}
|
||||
atomentry.getNavigationLinks().add(alink);
|
||||
} else {
|
||||
properties.add(getAtomProperty((JSONPropertyImpl) property, atomentry.getType()));
|
||||
}
|
||||
}
|
||||
|
||||
return atomentry;
|
||||
}
|
||||
|
||||
public JSONPropertyImpl getJsonProperty(final AtomPropertyImpl atomproperty) {
|
||||
final JSONPropertyImpl jsonproperty = new JSONPropertyImpl();
|
||||
BeanUtils.copyProperties(atomproperty, jsonproperty, "value");
|
||||
|
||||
if (atomproperty.getValue() instanceof ComplexValueImpl) {
|
||||
final ComplexValueImpl complex = new ComplexValueImpl();
|
||||
jsonproperty.setValue(complex);
|
||||
|
||||
for (Property field : atomproperty.getValue().asComplex().get()) {
|
||||
complex.get().add(getJsonProperty((AtomPropertyImpl) field));
|
||||
}
|
||||
} else if (atomproperty.getValue() instanceof CollectionValueImpl) {
|
||||
final CollectionValueImpl collection = new CollectionValueImpl();
|
||||
jsonproperty.setValue(collection);
|
||||
|
||||
for (Value element : atomproperty.getValue().asCollection().get()) {
|
||||
if (element instanceof ComplexValueImpl) {
|
||||
final ComplexValueImpl complex = new ComplexValueImpl();
|
||||
collection.get().add(complex);
|
||||
|
||||
for (Property field : element.asComplex().get()) {
|
||||
complex.get().add(getJsonProperty((AtomPropertyImpl) field));
|
||||
}
|
||||
} else {
|
||||
collection.get().add(element);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
jsonproperty.setValue(atomproperty.getValue());
|
||||
}
|
||||
|
||||
return jsonproperty;
|
||||
}
|
||||
|
||||
public AtomPropertyImpl getAtomProperty(final JSONPropertyImpl jsonproperty, final String entryType) {
|
||||
final AtomPropertyImpl atomproperty = new AtomPropertyImpl();
|
||||
atomproperty.setName(jsonproperty.getName());
|
||||
|
||||
if (StringUtils.isNotBlank(jsonproperty.getType())) {
|
||||
atomproperty.setType(jsonproperty.getType());
|
||||
} else {
|
||||
atomproperty.setType(
|
||||
Commons.getMetadata(version).getEntityType(entryType).getProperty(jsonproperty.getName()).getType());
|
||||
}
|
||||
|
||||
if (jsonproperty.getValue() instanceof ComplexValueImpl) {
|
||||
final ComplexValueImpl complex = new ComplexValueImpl();
|
||||
atomproperty.setValue(complex);
|
||||
|
||||
for (Property field : jsonproperty.getValue().asComplex().get()) {
|
||||
complex.get().add(getAtomProperty((JSONPropertyImpl) field, atomproperty.getType()));
|
||||
}
|
||||
} else if (jsonproperty.getValue() instanceof CollectionValueImpl) {
|
||||
final CollectionValueImpl collection = new CollectionValueImpl();
|
||||
atomproperty.setValue(collection);
|
||||
|
||||
for (Value element : jsonproperty.getValue().asCollection().get()) {
|
||||
if (element instanceof ComplexValueImpl) {
|
||||
final ComplexValueImpl complex = new ComplexValueImpl();
|
||||
collection.get().add(complex);
|
||||
|
||||
for (Property field : element.asComplex().get()) {
|
||||
complex.get().add(getAtomProperty((JSONPropertyImpl) field,
|
||||
atomproperty.getType().replaceAll("^Collection\\(", "").replaceAll("\\)$", "")));
|
||||
}
|
||||
} else {
|
||||
collection.get().add(element);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
atomproperty.setValue(jsonproperty.getValue());
|
||||
}
|
||||
|
||||
return atomproperty;
|
||||
}
|
||||
}
|
|
@ -18,10 +18,14 @@
|
|||
*/
|
||||
package org.apache.olingo.fit.utils;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import javax.ws.rs.NotFoundException;
|
||||
|
@ -32,6 +36,12 @@ import org.apache.commons.vfs2.FileSelector;
|
|||
import org.apache.commons.vfs2.FileSystemException;
|
||||
import org.apache.commons.vfs2.FileSystemManager;
|
||||
import org.apache.commons.vfs2.VFS;
|
||||
import org.apache.olingo.commons.api.data.Container;
|
||||
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
|
||||
import org.apache.olingo.commons.core.data.AtomEntryImpl;
|
||||
import org.apache.olingo.commons.core.data.AtomSerializer;
|
||||
import org.apache.olingo.commons.core.data.JSONEntryImpl;
|
||||
import org.apache.olingo.fit.serializer.JsonEntryContainer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -48,18 +58,19 @@ public class FSManager {
|
|||
|
||||
private final FileSystemManager fsManager;
|
||||
|
||||
private static Map<ODataVersion, FSManager> instance = new EnumMap<ODataVersion, FSManager>(ODataVersion.class);
|
||||
private static Map<ODataServiceVersion, FSManager> instance =
|
||||
new EnumMap<ODataServiceVersion, FSManager>(ODataServiceVersion.class);
|
||||
|
||||
private final ODataVersion version;
|
||||
private final ODataServiceVersion version;
|
||||
|
||||
public static FSManager instance(final ODataVersion version) throws Exception {
|
||||
public static FSManager instance(final ODataServiceVersion version) throws Exception {
|
||||
if (!instance.containsKey(version)) {
|
||||
instance.put(version, new FSManager(version));
|
||||
}
|
||||
return instance.get(version);
|
||||
}
|
||||
|
||||
private FSManager(final ODataVersion version) throws Exception {
|
||||
private FSManager(final ODataServiceVersion version) throws Exception {
|
||||
this.version = version;
|
||||
fsManager = VFS.getManager();
|
||||
}
|
||||
|
@ -88,6 +99,37 @@ public class FSManager {
|
|||
return memObject;
|
||||
}
|
||||
|
||||
public void putInMemory(final Container<AtomEntryImpl> container, final String relativePath)
|
||||
throws IOException {
|
||||
try {
|
||||
final ODataServiceVersion serviceVersion =
|
||||
version == ODataServiceVersion.V30 ? ODataServiceVersion.V30 : ODataServiceVersion.V40;
|
||||
|
||||
final AtomSerializer atomSerializer = Commons.getAtomSerializer(serviceVersion);
|
||||
|
||||
final ByteArrayOutputStream content = new ByteArrayOutputStream();
|
||||
final OutputStreamWriter writer = new OutputStreamWriter(content, Constants.encoding);
|
||||
|
||||
atomSerializer.write(writer, container);
|
||||
writer.flush();
|
||||
|
||||
putInMemory(new ByteArrayInputStream(content.toByteArray()), getAbsolutePath(relativePath, Accept.ATOM));
|
||||
content.reset();
|
||||
|
||||
final ObjectMapper mapper = Commons.getJsonMapper(serviceVersion);
|
||||
mapper.writeValue(
|
||||
writer, new JsonEntryContainer<JSONEntryImpl>(
|
||||
container.getContextURL(),
|
||||
container.getMetadataETag(),
|
||||
(new DataBinder(version == ODataServiceVersion.V30 ? ODataServiceVersion.V30 : ODataServiceVersion.V40)).
|
||||
getJsonEntry(container.getObject())));
|
||||
|
||||
putInMemory(new ByteArrayInputStream(content.toByteArray()), getAbsolutePath(relativePath, Accept.JSON_FULLMETA));
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public InputStream readFile(final String relativePath) {
|
||||
return readFile(relativePath, null);
|
||||
}
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
*/
|
||||
package org.apache.olingo.fit.utils.v3;
|
||||
|
||||
import org.apache.olingo.fit.utils.ODataVersion;
|
||||
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
|
||||
|
||||
public class JSONUtilities extends org.apache.olingo.fit.utils.AbstractJSONUtilities {
|
||||
|
||||
public JSONUtilities() throws Exception {
|
||||
super(ODataVersion.v3);
|
||||
super(ODataServiceVersion.V30);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,175 +18,11 @@
|
|||
*/
|
||||
package org.apache.olingo.fit.utils.v3;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.olingo.fit.utils.Accept;
|
||||
import org.apache.olingo.fit.utils.Commons;
|
||||
import org.apache.olingo.fit.utils.ConstantKey;
|
||||
import org.apache.olingo.fit.utils.Constants;
|
||||
import org.apache.olingo.fit.utils.MetadataLinkInfo;
|
||||
import org.apache.olingo.fit.utils.ODataVersion;
|
||||
import org.apache.olingo.fit.utils.XmlElement;
|
||||
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
|
||||
|
||||
public class XMLUtilities extends org.apache.olingo.fit.utils.AbstractXMLUtilities {
|
||||
|
||||
public XMLUtilities() throws Exception {
|
||||
super(ODataVersion.v3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void retrieveLinkInfoFromMetadata() throws Exception {
|
||||
|
||||
final MetadataLinkInfo metadataLinkInfo = new MetadataLinkInfo();
|
||||
Commons.getLinkInfo().put(version, metadataLinkInfo);
|
||||
|
||||
final InputStream metadata = fsManager.readFile(Constants.get(version, ConstantKey.METADATA), Accept.XML);
|
||||
final XMLEventReader reader = getEventReader(metadata);
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
final Map.Entry<Integer, XmlElement> entitySetElement =
|
||||
extractElement(reader, null, Collections.<String>singletonList("EntitySet"),
|
||||
null, false, 0, -1, -1);
|
||||
|
||||
retrieveLinks(entitySetElement.getValue(), metadataLinkInfo);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void retrieveLinks(final XmlElement entitySetElement, final MetadataLinkInfo metadataLinkInfo)
|
||||
throws Exception {
|
||||
|
||||
final InputStream metadata = fsManager.readFile(Constants.get(version, ConstantKey.METADATA), Accept.XML);
|
||||
|
||||
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
IOUtils.copy(metadata, bos);
|
||||
IOUtils.closeQuietly(metadata);
|
||||
|
||||
final String entitySetName = entitySetElement.getStart().getAttributeByName(new QName("Name")).getValue().trim();
|
||||
final String entityType = entitySetElement.getStart().getAttributeByName(new QName("EntityType")).getValue().trim();
|
||||
|
||||
final Collection<Map.Entry<String, String>> filter = new HashSet<Map.Entry<String, String>>();
|
||||
filter.add(new SimpleEntry<String, String>(
|
||||
"Name", entityType.substring(entityType.lastIndexOf(".") + 1, entityType.length())));
|
||||
filter.add(new SimpleEntry<String, String>("BaseType", entityType));
|
||||
|
||||
final XMLEventReader reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
|
||||
|
||||
final Map.Entry<Integer, XmlElement> entityTypeElement = extractElement(
|
||||
reader, null, Collections.<String>singletonList("EntityType"), filter, true, 0, -1, -1);
|
||||
|
||||
final XMLEventReader entityReader = entityTypeElement.getValue().getContentReader();
|
||||
int size = 0;
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
final XmlElement navProperty =
|
||||
extractElement(entityReader, null, Collections.<String>singletonList("NavigationProperty"),
|
||||
null, false, 0, -1, -1).getValue();
|
||||
|
||||
final String linkName = navProperty.getStart().getAttributeByName(new QName("Name")).getValue();
|
||||
final Map.Entry<String, Boolean> target = getTargetInfo(navProperty.getStart(), linkName);
|
||||
|
||||
metadataLinkInfo.addLink(
|
||||
entitySetName,
|
||||
linkName,
|
||||
target.getKey(),
|
||||
target.getValue());
|
||||
|
||||
size++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
entityReader.close();
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
metadataLinkInfo.addEntitySet(entitySetName);
|
||||
}
|
||||
}
|
||||
|
||||
private Map.Entry<String, Boolean> getTargetInfo(final StartElement element, final String linkName)
|
||||
throws Exception {
|
||||
final InputStream metadata = fsManager.readFile(Constants.get(version, ConstantKey.METADATA), Accept.XML);
|
||||
|
||||
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
IOUtils.copy(metadata, bos);
|
||||
IOUtils.closeQuietly(metadata);
|
||||
|
||||
// ------------------------------------
|
||||
// Retrieve association
|
||||
// ------------------------------------
|
||||
XMLEventReader reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
|
||||
|
||||
final String associationName = element.getAttributeByName(new QName("Relationship")).getValue();
|
||||
|
||||
final Map.Entry<Integer, XmlElement> association = extractElement(
|
||||
reader, null, Collections.<String>singletonList("Association"),
|
||||
Collections.<Map.Entry<String, String>>singleton(new SimpleEntry<String, String>(
|
||||
"Name", associationName.substring(associationName.lastIndexOf(".") + 1))), false,
|
||||
0, 4, 4);
|
||||
|
||||
reader.close();
|
||||
// ------------------------------------
|
||||
|
||||
// ------------------------------------
|
||||
// check for feed or not from Association role
|
||||
// ------------------------------------
|
||||
InputStream associationContent = association.getValue().toStream();
|
||||
reader = getEventReader(associationContent);
|
||||
|
||||
Map.Entry<Integer, XmlElement> associationEnd = extractElement(
|
||||
reader, null, Collections.<String>singletonList("End"),
|
||||
Collections.<Map.Entry<String, String>>singleton(new SimpleEntry<String, String>("Role", linkName)),
|
||||
false, 0, -1, -1);
|
||||
|
||||
reader.close();
|
||||
IOUtils.closeQuietly(associationContent);
|
||||
|
||||
final boolean feed = associationEnd.getValue().getStart().getAttributeByName(
|
||||
new QName("Multiplicity")).getValue().equals("*");
|
||||
// ------------------------------------
|
||||
|
||||
// ------------------------------------
|
||||
// Retrieve target association set name
|
||||
// ------------------------------------
|
||||
reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
|
||||
|
||||
final Map.Entry<Integer, XmlElement> associationSet = extractElement(
|
||||
reader, null, Collections.<String>singletonList("AssociationSet"),
|
||||
Collections.<Map.Entry<String, String>>singleton(new SimpleEntry<String, String>(
|
||||
"Association", associationName)), false, 0, -1, -1);
|
||||
|
||||
reader.close();
|
||||
|
||||
associationContent = associationSet.getValue().toStream();
|
||||
reader = getEventReader(associationContent);
|
||||
|
||||
associationEnd = extractElement(
|
||||
reader, null, Collections.<String>singletonList("End"),
|
||||
Collections.<Map.Entry<String, String>>singleton(new SimpleEntry<String, String>("Role", linkName)),
|
||||
false, 0, -1, -1);
|
||||
|
||||
reader.close();
|
||||
IOUtils.closeQuietly(associationContent);
|
||||
|
||||
final String target = associationEnd.getValue().getStart().getAttributeByName(new QName("EntitySet")).getValue();
|
||||
// ------------------------------------
|
||||
|
||||
return new SimpleEntry<String, Boolean>(target, feed);
|
||||
super(ODataServiceVersion.V30);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
*/
|
||||
package org.apache.olingo.fit.utils.v4;
|
||||
|
||||
import org.apache.olingo.fit.utils.ODataVersion;
|
||||
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
|
||||
|
||||
public class JSONUtilities extends org.apache.olingo.fit.utils.AbstractJSONUtilities {
|
||||
|
||||
public JSONUtilities() throws Exception {
|
||||
super(ODataVersion.v4);
|
||||
super(ODataServiceVersion.V40);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,130 +18,11 @@
|
|||
*/
|
||||
package org.apache.olingo.fit.utils.v4;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.olingo.fit.utils.Accept;
|
||||
import org.apache.olingo.fit.utils.Commons;
|
||||
import org.apache.olingo.fit.utils.ConstantKey;
|
||||
import org.apache.olingo.fit.utils.Constants;
|
||||
import org.apache.olingo.fit.utils.MetadataLinkInfo;
|
||||
import org.apache.olingo.fit.utils.ODataVersion;
|
||||
import org.apache.olingo.fit.utils.XmlElement;
|
||||
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
|
||||
|
||||
public class XMLUtilities extends org.apache.olingo.fit.utils.AbstractXMLUtilities {
|
||||
|
||||
public XMLUtilities() throws Exception {
|
||||
super(ODataVersion.v4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void retrieveLinkInfoFromMetadata() throws Exception {
|
||||
|
||||
final MetadataLinkInfo metadataLinkInfo = new MetadataLinkInfo();
|
||||
Commons.getLinkInfo().put(version, metadataLinkInfo);
|
||||
|
||||
final InputStream metadata = fsManager.readFile(Constants.get(version, ConstantKey.METADATA), Accept.XML);
|
||||
|
||||
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
IOUtils.copy(metadata, bos);
|
||||
IOUtils.closeQuietly(metadata);
|
||||
|
||||
XMLEventReader reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
|
||||
|
||||
final Set<String> singletons = new HashSet<String>();
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
final Map.Entry<Integer, XmlElement> entitySetElement =
|
||||
extractElement(reader, null, Collections.<String>singletonList("Singleton"),
|
||||
null, false, 0, -1, -1);
|
||||
|
||||
final String entitySetName =
|
||||
entitySetElement.getValue().getStart().getAttributeByName(new QName("Name")).getValue().trim();
|
||||
singletons.add(entitySetName);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
reader.close();
|
||||
}
|
||||
|
||||
reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
final Map.Entry<Integer, XmlElement> entitySetElement =
|
||||
extractElement(reader, null, Collections.<String>singletonList("EntitySet"),
|
||||
null, false, 0, -1, -1);
|
||||
|
||||
retrieveLinks(entitySetElement.getValue(), metadataLinkInfo, singletons);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
reader.close();
|
||||
}
|
||||
|
||||
reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
final Map.Entry<Integer, XmlElement> entitySetElement =
|
||||
extractElement(reader, null, Collections.<String>singletonList("Singleton"),
|
||||
null, false, 0, -1, -1);
|
||||
|
||||
retrieveLinks(entitySetElement.getValue(), metadataLinkInfo, singletons);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void retrieveLinks(
|
||||
final XmlElement entitySetElement, final MetadataLinkInfo metadataLinkInfo, final Set<String> singletons)
|
||||
throws Exception {
|
||||
|
||||
final String entitySetName = entitySetElement.getStart().getAttributeByName(new QName("Name")).getValue().trim();
|
||||
|
||||
final XMLEventReader entityReader = entitySetElement.getContentReader();
|
||||
int size = 0;
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
final XmlElement navProperty =
|
||||
extractElement(entityReader, null, Collections.<String>singletonList("NavigationPropertyBinding"),
|
||||
null, false, 0, -1, -1).getValue();
|
||||
|
||||
final String linkName = navProperty.getStart().getAttributeByName(new QName("Path")).getValue();
|
||||
final String target = navProperty.getStart().getAttributeByName(new QName("Target")).getValue();
|
||||
final boolean feed = !singletons.contains(target);
|
||||
|
||||
metadataLinkInfo.addLink(
|
||||
entitySetName,
|
||||
linkName,
|
||||
target,
|
||||
feed);
|
||||
|
||||
size++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
entityReader.close();
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
metadataLinkInfo.addEntitySet(entitySetName);
|
||||
}
|
||||
|
||||
if (singletons.contains(entitySetName)) {
|
||||
metadataLinkInfo.setSingleton(entitySetName);
|
||||
}
|
||||
super(ODataServiceVersion.V40);
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue