You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by fm...@apache.org on 2014/03/18 20:05:53 UTC
[4/4] git commit: [OLINGO-175] Provides (V3) CRUD property +
refactoring
[OLINGO-175] Provides (V3) CRUD property + refactoring
Project: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/commit/8f3541c2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/tree/8f3541c2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/diff/8f3541c2
Branch: refs/heads/olingo200
Commit: 8f3541c2dab262c0f72cb70bf3876d300eb2ede3
Parents: a835edd
Author: fmartelli <fa...@gmail.com>
Authored: Tue Mar 18 20:05:28 2014 +0100
Committer: fmartelli <fa...@gmail.com>
Committed: Tue Mar 18 20:05:28 2014 +0100
----------------------------------------------------------------------
.../org/apache/olingo/fit/AbstractServices.java | 354 +++++++--
.../olingo/fit/utils/AbstractUtilities.java | 214 ++----
.../org/apache/olingo/fit/utils/Constants.java | 2 +
.../apache/olingo/fit/utils/JSONUtilities.java | 93 ++-
.../olingo/fit/utils/XMLEventReaderWrapper.java | 24 +-
.../apache/olingo/fit/utils/XMLUtilities.java | 709 +++++++++++-------
.../resources/v3/Customer/-7/entity.full.json | 487 ++++++++++++
.../resources/v3/Customer/-9/entity.full.json | 750 +++++++++++++++++++
.../main/resources/v3/Customer/-9/entity.xml | 565 ++++++++++++++
.../main/resources/v3/Order/-8/entity.full.json | 17 +
fit/src/main/resources/v3/Order/-8/entity.xml | 43 ++
.../client/core/it/v3/PropertyTestITCase.java | 17 -
12 files changed, 2790 insertions(+), 485 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/8f3541c2/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java b/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java
index 27cd0ad..43f47bb 100644
--- a/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java
+++ b/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java
@@ -34,9 +34,12 @@ import org.apache.olingo.fit.utils.LinkInfo;
import java.io.File;
import java.io.InputStream;
import java.util.AbstractMap;
+import java.util.Arrays;
import java.util.Collections;
+import java.util.EnumSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
@@ -64,6 +67,8 @@ public abstract class AbstractServices {
*/
protected static final Logger LOG = LoggerFactory.getLogger(AbstractServices.class);
+ private static Set<ODataVersion> initialized = EnumSet.noneOf(ODataVersion.class);
+
protected abstract ODataVersion getVersion();
protected final XMLUtilities xml;
@@ -72,6 +77,11 @@ public abstract class AbstractServices {
public AbstractServices() throws Exception {
this.xml = new XMLUtilities(getVersion());
this.json = new JSONUtilities(getVersion());
+
+ if (!initialized.contains(getVersion())) {
+ xml.retrieveLinkInfoFromMetadata();
+ initialized.add(getVersion());
+ }
}
/**
@@ -279,6 +289,9 @@ public abstract class AbstractServices {
@PathParam("entitySetName") String entitySetName,
final String entity) {
+ // default
+ AbstractUtilities utils = xml;
+
try {
final Accept acceptType = Accept.parse(accept, getVersion());
@@ -286,19 +299,15 @@ public abstract class AbstractServices {
throw new UnsupportedMediaTypeException("Unsupported media type");
}
- final InputStream res;
- if (acceptType == Accept.ATOM) {
- res = xml.addOrReplaceEntity(entitySetName, IOUtils.toInputStream(entity));
- } else {
- res = json.addOrReplaceEntity(entitySetName, IOUtils.toInputStream(entity));
- }
+ utils = getUtilities(acceptType);
+ final InputStream res = utils.addOrReplaceEntity(entitySetName, IOUtils.toInputStream(entity));
final Response response;
if ("return-no-content".equalsIgnoreCase(prefer)) {
res.close();
- response = xml.createResponse(null, null, acceptType, Response.Status.NO_CONTENT);
+ response = utils.createResponse(null, null, acceptType, Response.Status.NO_CONTENT);
} else {
- response = xml.createResponse(res, null, acceptType, Response.Status.CREATED);
+ response = utils.createResponse(res, null, acceptType, Response.Status.CREATED);
}
if (StringUtils.isNotBlank(prefer)) {
@@ -307,7 +316,7 @@ public abstract class AbstractServices {
return response;
} catch (Exception e) {
- return xml.createFaultResponse(accept, e);
+ return utils.createFaultResponse(accept, e);
}
}
@@ -514,6 +523,259 @@ public abstract class AbstractServices {
}
}
+ private Response replaceProperty(
+ final String accept,
+ final String prefer,
+ final String entitySetName,
+ final String entityId,
+ final String path,
+ final String format,
+ final String changes,
+ final boolean justValue) {
+ try {
+ Accept acceptType = null;
+ if (StringUtils.isNotBlank(format)) {
+ acceptType = Accept.valueOf(format.toUpperCase());
+ } else if (StringUtils.isNotBlank(accept)) {
+ acceptType = Accept.parse(accept, getVersion(), null);
+ }
+
+ // if the given path is not about any link then search for property
+ LOG.info("Retrieve property {}", path);
+
+ final AbstractUtilities utils = getUtilities(acceptType);
+
+ final InputStream changed = utils.replaceProperty(
+ entitySetName,
+ entityId,
+ IOUtils.toInputStream(changes),
+ Arrays.asList(path.split("/")),
+ acceptType,
+ justValue);
+
+ final Response response;
+ if ("return-content".equalsIgnoreCase(prefer)) {
+ response = xml.createResponse(changed, null, acceptType, Response.Status.OK);
+ } else {
+ changed.close();
+ response = xml.createResponse(null, null, acceptType, Response.Status.NO_CONTENT);
+ }
+
+ if (StringUtils.isNotBlank(prefer)) {
+ response.getHeaders().put("Preference-Applied", Collections.<Object>singletonList(prefer));
+ }
+
+ return response;
+
+ } catch (Exception e) {
+ return xml.createFaultResponse(accept, e);
+ }
+ }
+
+ private Response deletePropertyValue(
+ final String accept,
+ final String prefer,
+ final String entitySetName,
+ final String entityId,
+ final String path,
+ final String format) {
+ try {
+ Accept acceptType = null;
+ if (StringUtils.isNotBlank(format)) {
+ acceptType = Accept.valueOf(format.toUpperCase());
+ } else if (StringUtils.isNotBlank(accept)) {
+ acceptType = Accept.parse(accept, getVersion(), null);
+ }
+
+ // if the given path is not about any link then search for property
+ LOG.info("Retrieve property {}", path);
+
+ final AbstractUtilities utils = getUtilities(acceptType);
+
+ final InputStream changed = utils.deleteProperty(
+ entitySetName,
+ entityId,
+ Arrays.asList(path.split("/")),
+ acceptType);
+
+ final Response response;
+ if ("return-content".equalsIgnoreCase(prefer)) {
+ response = xml.createResponse(changed, null, acceptType, Response.Status.OK);
+ } else {
+ changed.close();
+ response = xml.createResponse(null, null, acceptType, Response.Status.NO_CONTENT);
+ }
+
+ if (StringUtils.isNotBlank(prefer)) {
+ response.getHeaders().put("Preference-Applied", Collections.<Object>singletonList(prefer));
+ }
+
+ return response;
+
+ } catch (Exception e) {
+ return xml.createFaultResponse(accept, e);
+ }
+ }
+
+ /**
+ * Replace property value.
+ *
+ * @param accept
+ * @param entitySetName
+ * @param entityId
+ * @param path
+ * @param format
+ * @param changes
+ * @return
+ */
+ @PUT
+ @Path("/{entitySetName}({entityId})/{path:.*}/$value")
+ public Response replacePropertyValue(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) String prefer,
+ @PathParam("entitySetName") String entitySetName,
+ @PathParam("entityId") String entityId,
+ @PathParam("path") String path,
+ @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format,
+ final String changes) {
+ return replaceProperty(accept, prefer, entitySetName, entityId, path, format, changes, true);
+ }
+
+ /**
+ * Replace property.
+ *
+ * @param accept
+ * @param entitySetName
+ * @param entityId
+ * @param path
+ * @param format
+ * @param changes
+ * @return
+ */
+ @MERGE
+ @Path("/{entitySetName}({entityId})/{path:.*}")
+ public Response mergeProperty(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) String prefer,
+ @PathParam("entitySetName") String entitySetName,
+ @PathParam("entityId") String entityId,
+ @PathParam("path") String path,
+ @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format,
+ final String changes) {
+ return replaceProperty(accept, prefer, entitySetName, entityId, path, format, changes, false);
+ }
+
+ /**
+ * Replace property.
+ *
+ * @param accept
+ * @param entitySetName
+ * @param entityId
+ * @param path
+ * @param format
+ * @param changes
+ * @return
+ */
+ @PATCH
+ @Path("/{entitySetName}({entityId})/{path:.*}")
+ public Response patchProperty(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) String prefer,
+ @PathParam("entitySetName") String entitySetName,
+ @PathParam("entityId") String entityId,
+ @PathParam("path") String path,
+ @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format,
+ final String changes) {
+ return replaceProperty(accept, prefer, entitySetName, entityId, path, format, changes, false);
+ }
+
+ /**
+ * Replace property.
+ *
+ * @param accept
+ * @param entitySetName
+ * @param entityId
+ * @param path
+ * @param format
+ * @param changes
+ * @return
+ */
+ @PUT
+ @Path("/{entitySetName}({entityId})/{path:.*}")
+ public Response replaceProperty(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) String prefer,
+ @PathParam("entitySetName") String entitySetName,
+ @PathParam("entityId") String entityId,
+ @PathParam("path") String path,
+ @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format,
+ final String changes) {
+ return replaceProperty(accept, prefer, entitySetName, entityId, path, format, changes, false);
+ }
+
+ /**
+ * Nullify property value.
+ *
+ * @param accept
+ * @param entitySetName
+ * @param entityId
+ * @param path
+ * @param format
+ * @param changes
+ * @return
+ */
+ @DELETE
+ @Path("/{entitySetName}({entityId})/{path:.*}/$value")
+ public Response deleteProperty(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) String prefer,
+ @PathParam("entitySetName") String entitySetName,
+ @PathParam("entityId") String entityId,
+ @PathParam("path") String path,
+ @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format) {
+ return deletePropertyValue(accept, prefer, entitySetName, entityId, path, format);
+ }
+
+ /**
+ * Retrieve property sample.
+ *
+ * @param accept Accept header.
+ * @param entitySetName Entity set name.
+ * @param entityId entity id.
+ * @param path path.
+ * @param format format query option.
+ * @return property.
+ */
+ @GET
+ @Path("/{entitySetName}({entityId})/{path:.*}/$value")
+ public Response getPathValue(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @PathParam("entitySetName") String entitySetName,
+ @PathParam("entityId") String entityId,
+ @PathParam("path") String path,
+ @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format) {
+
+ final String basePath = Commons.getEntityBasePath(entitySetName, entityId);
+ AbstractUtilities utils = null;
+ try {
+ Accept acceptType = null;
+ if (StringUtils.isNotBlank(format)) {
+ acceptType = Accept.valueOf(format.toUpperCase());
+ } else if (StringUtils.isNotBlank(accept)) {
+ acceptType = Accept.parse(accept, getVersion(), null);
+ }
+ utils = getUtilities(acceptType);
+
+ return utils.createResponse(
+ getPath(acceptType, entitySetName, entityId, path, true),
+ Commons.getETag(basePath, getVersion()),
+ acceptType);
+
+ } catch (Exception e) {
+ return (utils == null ? xml : utils).createFaultResponse(accept, e);
+ }
+ }
+
/**
* Retrieve property sample.
*
@@ -534,7 +796,6 @@ public abstract class AbstractServices {
@QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format) {
try {
- boolean searchForValue = path.endsWith("$value");
Accept acceptType = null;
if (StringUtils.isNotBlank(format)) {
acceptType = Accept.valueOf(format.toUpperCase());
@@ -542,14 +803,13 @@ public abstract class AbstractServices {
acceptType = Accept.parse(accept, getVersion(), null);
}
- final String basePath =
- entitySetName + File.separatorChar + Commons.getEntityKey(entityId) + File.separatorChar;
+ final String basePath = Commons.getEntityBasePath(entitySetName, entityId);
InputStream stream;
try {
final LinkInfo linkInfo = xml.readLinks(entitySetName, entityId, path, Accept.XML);
- final Map.Entry<String, List<String>> links = XMLUtilities.extractLinkURIs(linkInfo.getLinks());
+ final Map.Entry<String, List<String>> links = xml.extractLinkURIs(linkInfo.getLinks());
switch (acceptType) {
case JSON:
@@ -564,30 +824,7 @@ public abstract class AbstractServices {
} catch (NotFoundException e) {
// if the given path is not about any link then search for property
LOG.info("Retrieve property {}", path);
-
- stream = FSManager.instance(getVersion()).readFile(
- basePath + ENTITY, acceptType == null || acceptType == Accept.TEXT
- ? Accept.XML : acceptType);
-
- if (searchForValue) {
- stream = xml.getAtomPropertyValue(stream, path.split("/"));
- } else {
- if (acceptType == null || acceptType == Accept.XML || acceptType == Accept.ATOM) {
- // retrieve xml
- stream = xml.getAtomProperty(stream, path.split("/"));
- } else {
- // retrieve Edm type from xml
- final String edmType = xml.getEdmTypeFromXML(
- FSManager.instance(getVersion()).readFile(basePath + ENTITY, Accept.XML),
- path.split("/"));
- // retrieve json property
- stream = json.getJsonProperty(stream, path.split("/"), edmType);
- }
- }
-
- if ((searchForValue && acceptType != null && acceptType != Accept.TEXT) || acceptType == Accept.ATOM) {
- throw new UnsupportedMediaTypeException("Unsupported media type " + acceptType);
- }
+ stream = getPath(acceptType, entitySetName, entityId, path, false);
}
return xml.createResponse(stream, Commons.getETag(basePath, getVersion()), acceptType);
@@ -596,6 +833,37 @@ public abstract class AbstractServices {
}
}
+ private InputStream getPath(
+ final Accept acceptType,
+ final String entitySetName,
+ final String entityId,
+ final String path,
+ final boolean searchForValue) throws Exception {
+
+ if ((searchForValue && acceptType != null && acceptType != Accept.TEXT) || acceptType == Accept.ATOM) {
+ throw new UnsupportedMediaTypeException("Unsupported media type " + acceptType);
+ }
+
+ final String basePath = Commons.getEntityBasePath(entitySetName, entityId);
+
+ InputStream stream = FSManager.instance(getVersion()).readFile(
+ basePath + ENTITY, acceptType == null || acceptType == Accept.TEXT
+ ? Accept.XML : acceptType);
+
+ final AbstractUtilities utils = getUtilities(acceptType);
+
+ final List<String> pathElements = Arrays.asList(path.split("\\/"));
+
+ if (searchForValue) {
+ stream = utils.getPropertyValue(stream, pathElements);
+ } else {
+ String edmType = xml.getEdmTypeFromAtom(entitySetName, entityId, pathElements);
+ stream = utils.getProperty(entitySetName, entityId, pathElements, edmType);
+ }
+
+ return stream;
+ }
+
/**
* Retrieve links sample.
*
@@ -670,9 +938,9 @@ public abstract class AbstractServices {
final List<String> links;
if (content == Accept.XML || content == Accept.TEXT || content == Accept.ATOM) {
- links = XMLUtilities.extractLinkURIs(IOUtils.toInputStream(link)).getValue();
+ links = xml.extractLinkURIs(IOUtils.toInputStream(link)).getValue();
} else {
- links = JSONUtilities.extractLinkURIs(IOUtils.toInputStream(link)).getValue();
+ links = json.extractLinkURIs(IOUtils.toInputStream(link)).getValue();
}
utils.putLinksInMemory(
@@ -747,9 +1015,9 @@ public abstract class AbstractServices {
final List<String> links;
if (content == Accept.XML || content == Accept.TEXT || content == Accept.ATOM) {
- links = XMLUtilities.extractLinkURIs(IOUtils.toInputStream(link)).getValue();
+ links = xml.extractLinkURIs(IOUtils.toInputStream(link)).getValue();
} else {
- links = JSONUtilities.extractLinkURIs(IOUtils.toInputStream(link)).getValue();
+ links = json.extractLinkURIs(IOUtils.toInputStream(link)).getValue();
}
utils.putLinksInMemory(
@@ -788,10 +1056,10 @@ public abstract class AbstractServices {
final AbstractUtilities utils = getUtilities(acceptType);
- final Map.Entry<String, List<String>> currents = JSONUtilities.extractLinkURIs(utils.readLinks(
+ final Map.Entry<String, List<String>> currents = json.extractLinkURIs(utils.readLinks(
entitySetName, entityId, linkName, Accept.JSON_FULLMETA).getLinks());
- final Map.Entry<String, List<String>> toBeRemoved = JSONUtilities.extractLinkURIs(utils.readLinks(
+ final Map.Entry<String, List<String>> toBeRemoved = json.extractLinkURIs(utils.readLinks(
entitySetName, entityId, linkName + "(" + linkId + ")", Accept.JSON_FULLMETA).getLinks());
final List<String> remains = currents.getValue();
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/8f3541c2/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java
index 9733ce4..b7c5acd 100644
--- a/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java
@@ -30,7 +30,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.ConcurrentModificationException;
-import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
@@ -39,9 +38,6 @@ import java.util.Set;
import java.util.regex.Pattern;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.core.Response;
-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.commons.lang3.StringUtils;
import org.apache.commons.vfs2.FileObject;
@@ -56,8 +52,6 @@ public abstract class AbstractUtilities {
*/
protected static final Logger LOG = LoggerFactory.getLogger(AbstractUtilities.class);
- private static Set<ODataVersion> initialized = EnumSet.noneOf(ODataVersion.class);
-
protected final ODataVersion version;
protected final FSManager fsManager;
@@ -67,97 +61,6 @@ public abstract class AbstractUtilities {
public AbstractUtilities(final ODataVersion version) throws Exception {
this.version = version;
this.fsManager = FSManager.instance(version);
- initialize();
- }
-
- private void initialize() throws Exception {
-
- if (!initialized.contains(version)) {
- final MetadataLinkInfo metadataLinkInfo = new MetadataLinkInfo();
- Commons.linkInfo.put(version, metadataLinkInfo);
-
- final InputStream metadata = fsManager.readFile(Constants.METADATA, Accept.XML);
- final XMLEventReader reader = XMLUtilities.getEventReader(metadata);
-
- int initialDepth = 0;
- try {
- while (true) {
- Map.Entry<Integer, XmlElement> entityType =
- XMLUtilities.getAtomElement(reader, null, "EntityType", null, initialDepth, 4, 4, false);
- initialDepth = entityType.getKey();
-
- final String entitySetName =
- entityType.getValue().getStart().getAttributeByName(new QName("Name")).getValue();
-
- final XMLEventReader entityReader = XMLUtilities.getEventReader(entityType.getValue().toStream());
- int size = 0;
-
- try {
- while (true) {
- final XmlElement navProperty =
- XMLUtilities.getAtomElement(entityReader, null, "NavigationProperty");
-
- 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);
- }
- }
- } catch (Exception e) {
- } finally {
- reader.close();
- initialized.add(version);
- }
- }
- }
-
- private Map.Entry<String, Boolean> getTargetInfo(final StartElement element, final String linkName)
- throws Exception {
- final InputStream metadata = fsManager.readFile(Constants.METADATA, Accept.XML);
- XMLEventReader reader = XMLUtilities.getEventReader(metadata);
-
- final String associationName = element.getAttributeByName(new QName("Relationship")).getValue();
-
- final Map.Entry<Integer, XmlElement> association = XMLUtilities.getAtomElement(
- reader, null, "Association",
- Collections.<Map.Entry<String, String>>singleton(new SimpleEntry<String, String>(
- "Name", associationName.substring(associationName.lastIndexOf(".") + 1))),
- 0, 4, 4, false);
-
- final InputStream associationContent = association.getValue().toStream();
- final ByteArrayOutputStream bos = new ByteArrayOutputStream();
- IOUtils.copy(associationContent, bos);
- IOUtils.closeQuietly(associationContent);
-
- reader.close();
- reader = XMLUtilities.getEventReader(new ByteArrayInputStream(bos.toByteArray()));
-
- final Map.Entry<Integer, XmlElement> associationEnd = XMLUtilities.getAtomElement(
- reader, null, "End",
- Collections.<Map.Entry<String, String>>singleton(new SimpleEntry<String, String>("Role", linkName)),
- 0, -1, -1, false);
-
- final String target = associationEnd.getValue().getStart().getAttributeByName(new QName("Type")).getValue();
- final boolean feed = associationEnd.getValue().getStart().getAttributeByName(
- new QName("Multiplicity")).getValue().equals("*");
-
- return new SimpleEntry<String, Boolean>(target, feed);
}
public boolean isMediaContent(final String entityName) {
@@ -275,8 +178,7 @@ public abstract class AbstractUtilities {
for (String availableLink : new HashSet<String>(linksToBeMantained)) {
try {
- fsManager.resolve(
- Commons.getLinksPath(version, entitySetName, key, availableLink, Accept.JSON_FULLMETA));
+ fsManager.resolve(Commons.getLinksPath(version, entitySetName, key, availableLink, Accept.JSON_FULLMETA));
} catch (Exception e) {
linksToBeMantained.remove(availableLink);
}
@@ -376,8 +278,7 @@ public abstract class AbstractUtilities {
if (Commons.linkInfo.get(version).isFeed(entitySetName, linkName)) {
try {
- final Map.Entry<String, List<String>> currents = JSONUtilities.extractLinkURIs(
- readLinks(entitySetName, entityKey, linkName, Accept.JSON_FULLMETA).getLinks());
+ final Map.Entry<String, List<String>> currents = extractLinkURIs(entitySetName, entityKey, linkName);
uris.addAll(currents.getValue());
} catch (Exception ignore) {
}
@@ -436,7 +337,6 @@ public abstract class AbstractUtilities {
}
public Response createFaultResponse(final String accept, final Exception e) {
- e.printStackTrace();
LOG.debug("Create fault response about .... ", e);
final Response.ResponseBuilder builder = Response.serverError();
@@ -490,8 +390,7 @@ public abstract class AbstractUtilities {
propertyNames.add("FromUsername");
final StringBuilder keyBuilder = new StringBuilder();
- for (Map.Entry<String, InputStream> value
- : getPropertyValues(entity, propertyNames, accept).entrySet()) {
+ for (Map.Entry<String, InputStream> value : getPropertyValues(entity, propertyNames).entrySet()) {
if (keyBuilder.length() > 0) {
keyBuilder.append(",");
@@ -513,7 +412,7 @@ public abstract class AbstractUtilities {
} else if ("Order".equals(entitySetName)) {
try {
final Map<String, InputStream> value =
- getPropertyValues(entity, Collections.<String>singletonList("OrderId"), accept);
+ getPropertyValues(entity, Collections.<String>singletonList("OrderId"));
res = value.isEmpty() ? null : IOUtils.toString(value.values().iterator().next());
} catch (Exception e) {
if (sequence.containsKey(entitySetName)) {
@@ -526,7 +425,7 @@ public abstract class AbstractUtilities {
} else if ("Customer".equals(entitySetName)) {
try {
final Map<String, InputStream> value =
- getPropertyValues(entity, Collections.<String>singletonList("CustomerId"), accept);
+ getPropertyValues(entity, Collections.<String>singletonList("CustomerId"));
res = value.isEmpty() ? null : IOUtils.toString(value.values().iterator().next());
} catch (Exception e) {
if (sequence.containsKey(entitySetName)) {
@@ -539,7 +438,7 @@ public abstract class AbstractUtilities {
} else if ("ComputerDetail".equals(entitySetName)) {
try {
final Map<String, InputStream> value =
- getPropertyValues(entity, Collections.<String>singletonList("ComputerDetailId"), accept);
+ getPropertyValues(entity, Collections.<String>singletonList("ComputerDetailId"));
res = value.isEmpty() ? null : IOUtils.toString(value.values().iterator().next());
} catch (Exception e) {
if (sequence.containsKey(entitySetName)) {
@@ -552,7 +451,7 @@ public abstract class AbstractUtilities {
} else if ("AllGeoTypesSet".equals(entitySetName)) {
try {
final Map<String, InputStream> value =
- getPropertyValues(entity, Collections.<String>singletonList("Id"), accept);
+ getPropertyValues(entity, Collections.<String>singletonList("Id"));
res = value.isEmpty() ? null : IOUtils.toString(value.values().iterator().next());
} catch (Exception e) {
if (sequence.containsKey(entitySetName)) {
@@ -565,7 +464,7 @@ public abstract class AbstractUtilities {
} else if ("CustomerInfo".equals(entitySetName)) {
try {
final Map<String, InputStream> value =
- getPropertyValues(entity, Collections.<String>singletonList("CustomerInfoId"), accept);
+ getPropertyValues(entity, Collections.<String>singletonList("CustomerInfoId"));
res = value.isEmpty() ? null : IOUtils.toString(value.values().iterator().next());
} catch (Exception e) {
if (sequence.containsKey(entitySetName)) {
@@ -587,35 +486,15 @@ public abstract class AbstractUtilities {
}
}
- private static Map<String, InputStream> getPropertyValues(
- final InputStream is, final List<String> propertyNames, final Accept accept)
+ private Map<String, InputStream> getPropertyValues(final InputStream is, final List<String> propertyNames)
throws Exception {
final Map<String, InputStream> res = new LinkedHashMap<String, InputStream>();
- final ByteArrayOutputStream bos = new ByteArrayOutputStream();
- IOUtils.copy(is, bos);
- IOUtils.closeQuietly(is);
-
for (String propertyName : propertyNames) {
- final InputStream value;
-
- switch (accept) {
- case JSON:
- case JSON_FULLMETA:
- case JSON_NOMETA:
- value = JSONUtilities.getJsonPropertyValue(
- new ByteArrayInputStream(bos.toByteArray()),
- propertyName);
- break;
- default:
- value = XMLUtilities.getAtomPropertyValue(
- new ByteArrayInputStream(bos.toByteArray()),
- new String[] {propertyName, "$value"});
- }
- res.put(propertyName, value);
+ res.put(propertyName, getPropertyValue(is, Collections.<String>singletonList(propertyName)));
}
- IOUtils.closeQuietly(bos);
+ IOUtils.closeQuietly(is);
return res;
}
@@ -650,8 +529,7 @@ public abstract class AbstractUtilities {
throw new UnsupportedMediaTypeException("Unsupported media type");
}
- final String basePath =
- entitySetName + File.separatorChar + Commons.getEntityKey(entityId) + File.separatorChar;
+ final String basePath = Commons.getEntityBasePath(entitySetName, entityId);
return new SimpleEntry<String, InputStream>(basePath, fsManager.readFile(basePath + ENTITY, accept));
}
@@ -666,7 +544,7 @@ public abstract class AbstractUtilities {
// 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 = XMLUtilities.extractLinkURIs(linkInfo.getLinks());
+ final Map.Entry<String, List<String>> links = extractLinkURIs(entitySetName, entityId, linkName);
// --------------------------------
// --------------------------------
@@ -704,6 +582,52 @@ public abstract class AbstractUtilities {
return addOrReplaceEntity(entityId, entitySetName, setChanges(entityInfo.getValue(), replacement));
}
+ public InputStream replaceProperty(
+ final String entitySetName,
+ final String entityId,
+ final InputStream changes,
+ final List<String> path,
+ final Accept accept,
+ final boolean justValue) throws Exception {
+ final String basePath = Commons.getEntityBasePath(entitySetName, entityId);
+
+ final Accept acceptType = accept == null || Accept.TEXT == accept
+ ? Accept.XML : accept.getExtension().equals(Accept.JSON.getExtension()) ? Accept.JSON_FULLMETA : accept;
+
+ // read atom
+ InputStream stream = fsManager.readFile(basePath + ENTITY, acceptType);
+
+ // change atom
+ stream = replaceProperty(stream, changes, path, justValue);
+
+ // save atom
+ fsManager.putInMemory(stream, fsManager.getAbsolutePath(basePath + ENTITY, acceptType));
+
+ return fsManager.readFile(basePath + ENTITY, acceptType);
+ }
+
+ public InputStream deleteProperty(
+ final String entitySetName,
+ final String entityId,
+ final List<String> path,
+ final Accept accept) throws Exception {
+ final String basePath = Commons.getEntityBasePath(entitySetName, entityId);
+
+ final Accept acceptType = accept == null || Accept.TEXT == accept
+ ? Accept.XML : accept.getExtension().equals(Accept.JSON.getExtension()) ? Accept.JSON_FULLMETA : accept;
+
+ // read atom
+ InputStream stream = fsManager.readFile(basePath + ENTITY, acceptType);
+
+ // change atom
+ stream = deleteProperty(stream, path);
+
+ // save atom
+ fsManager.putInMemory(stream, fsManager.getAbsolutePath(basePath + ENTITY, acceptType));
+
+ return fsManager.readFile(basePath + ENTITY, acceptType);
+ }
+
public abstract InputStream readEntities(
final List<String> links, final String linkName, final String next, final boolean forceFeed)
throws Exception;
@@ -722,4 +646,22 @@ public abstract class AbstractUtilities {
public abstract InputStream addEditLink(
final InputStream content, final String title, final String href) throws Exception;
-}
+
+ protected abstract InputStream replaceProperty(
+ final InputStream src, final InputStream replacement, final List<String> path, final boolean justValue)
+ throws Exception;
+
+ protected abstract InputStream deleteProperty(final InputStream src, final List<String> path) throws Exception;
+
+ public abstract InputStream getProperty(
+ final String entitySetName, final String entityId, final List<String> path, final String edmType)
+ throws Exception;
+
+ public abstract InputStream getPropertyValue(final InputStream is, final List<String> path)
+ throws Exception;
+
+ public abstract Map.Entry<String, List<String>> extractLinkURIs(final InputStream is) throws Exception;
+
+ public abstract Map.Entry<String, List<String>> extractLinkURIs(
+ final String entitySetName, final String entityId, final String linkName) throws Exception;
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/8f3541c2/fit/src/main/java/org/apache/olingo/fit/utils/Constants.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/Constants.java b/fit/src/main/java/org/apache/olingo/fit/utils/Constants.java
index 4dba9da..59fdc35 100644
--- a/fit/src/main/java/org/apache/olingo/fit/utils/Constants.java
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/Constants.java
@@ -28,6 +28,8 @@ public class Constants {
public final static String ODATA_METADATA_PREFIX = DEFAULT_SERVICE_URL + "$metadata#";
+ public final static String ATOM_DEF_TYPE = "Edm.String";
+
public final static String ATOM_PROPERTY_PREFIX = "d:";
public final static String ATOM_METADATA_PREFIX = "m:";
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/8f3541c2/fit/src/main/java/org/apache/olingo/fit/utils/JSONUtilities.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/JSONUtilities.java b/fit/src/main/java/org/apache/olingo/fit/utils/JSONUtilities.java
index f979db7..a58f3d2 100644
--- a/fit/src/main/java/org/apache/olingo/fit/utils/JSONUtilities.java
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/JSONUtilities.java
@@ -176,35 +176,41 @@ public class JSONUtilities extends AbstractUtilities {
return IOUtils.toInputStream(srcNode.toString());
}
- protected static InputStream getJsonPropertyValue(final InputStream src, final String name)
+ @Override
+ public InputStream getPropertyValue(final InputStream src, final List<String> path)
throws Exception {
- ObjectMapper mapper = new ObjectMapper();
+ final ObjectMapper mapper = new ObjectMapper();
final JsonNode srcNode = mapper.readTree(src);
- JsonNode node = getJsonProperty(srcNode, new String[] {name}, 0);
+ JsonNode node = getProperty(srcNode, path, 0);
return IOUtils.toInputStream(node.asText());
}
- public static InputStream getJsonProperty(final InputStream src, final String[] path, final String edmType)
+ @Override
+ public InputStream getProperty(
+ final String entitySetName, final String entityId, final List<String> path, final String edmType)
throws Exception {
+ final InputStream src =
+ fsManager.readFile(Commons.getEntityBasePath(entitySetName, entityId) + ENTITY, Accept.JSON_FULLMETA);
+
final ObjectMapper mapper = new ObjectMapper();
final JsonNode srcNode = mapper.readTree(src);
- final ObjectNode property = new ObjectNode(JsonNodeFactory.instance);
+ final ObjectNode propertyNode = new ObjectNode(JsonNodeFactory.instance);
if (StringUtils.isNotBlank(edmType)) {
- property.put(JSON_ODATAMETADATA_NAME, ODATA_METADATA_PREFIX + edmType);
+ propertyNode.put(JSON_ODATAMETADATA_NAME, ODATA_METADATA_PREFIX + edmType);
}
- JsonNode jsonNode = getJsonProperty(srcNode, path, 0);
+ JsonNode jsonNode = getProperty(srcNode, path, 0);
if (jsonNode.isObject()) {
- property.putAll((ObjectNode) jsonNode);
+ propertyNode.putAll((ObjectNode) jsonNode);
} else {
- property.put("value", jsonNode.asText());
+ propertyNode.put("value", jsonNode.asText());
}
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
- mapper.writeValue(bos, property);
+ mapper.writeValue(bos, propertyNode);
final InputStream res = new ByteArrayInputStream(bos.toByteArray());
IOUtils.closeQuietly(bos);
@@ -212,16 +218,16 @@ public class JSONUtilities extends AbstractUtilities {
return res;
}
- private static JsonNode getJsonProperty(final JsonNode node, final String[] path, final int index)
+ private JsonNode getProperty(final JsonNode node, final List<String> path, final int index)
throws NotFoundException {
final Iterator<Map.Entry<String, JsonNode>> iter = node.fields();
while (iter.hasNext()) {
final Map.Entry<String, JsonNode> entry = iter.next();
- if (path[index].equals(entry.getKey())) {
- if (path.length - 1 == index) {
+ if (path.get(index).equals(entry.getKey())) {
+ if (path.size() - 1 == index) {
return entry.getValue();
} else {
- return getJsonProperty(entry.getValue(), path, index + 1);
+ return getProperty(entry.getValue(), path, index + 1);
}
}
}
@@ -400,7 +406,16 @@ public class JSONUtilities extends AbstractUtilities {
return IOUtils.toInputStream(toBeChangedObject.toString());
}
- public static Map.Entry<String, List<String>> extractLinkURIs(final InputStream is)
+ @Override
+ public Map.Entry<String, List<String>> extractLinkURIs(
+ final String entitySetName, final String entityId, final String linkName)
+ throws Exception {
+ final LinkInfo links = readLinks(entitySetName, entityId, linkName, Accept.JSON_FULLMETA);
+ return extractLinkURIs(links.getLinks());
+ }
+
+ @Override
+ public Map.Entry<String, List<String>> extractLinkURIs(final InputStream is)
throws Exception {
final ObjectMapper mapper = new ObjectMapper();
final ObjectNode srcNode = (ObjectNode) mapper.readTree(is);
@@ -436,4 +451,52 @@ public class JSONUtilities extends AbstractUtilities {
srcNode.set(JSON_EDITLINK_NAME, new TextNode(href));
return IOUtils.toInputStream(srcNode.toString());
}
+
+ @Override
+ public InputStream replaceProperty(
+ final InputStream src, final InputStream replacement, final List<String> path, final boolean justValue)
+ throws Exception {
+ final ObjectMapper mapper = new ObjectMapper();
+ final ObjectNode srcNode = (ObjectNode) mapper.readTree(src);
+ IOUtils.closeQuietly(src);
+
+ final JsonNode replacementNode;
+ if (justValue) {
+ replacementNode = new TextNode(IOUtils.toString(replacement));
+ } else {
+ replacementNode = (ObjectNode) mapper.readTree(replacement);
+ }
+ IOUtils.closeQuietly(replacement);
+
+ JsonNode node = srcNode;
+ for (int i = 0; i < path.size() - 1; i++) {
+ node = node.get(path.get(i));
+ if (node == null) {
+ throw new NotFoundException();
+ }
+ }
+
+ ((ObjectNode) node).set(path.get(path.size() - 1), replacementNode);
+
+ return IOUtils.toInputStream(srcNode.toString());
+ }
+
+ @Override
+ public InputStream deleteProperty(final InputStream src, final List<String> path) throws Exception {
+ final ObjectMapper mapper = new ObjectMapper();
+ final ObjectNode srcNode = (ObjectNode) mapper.readTree(src);
+ IOUtils.closeQuietly(src);
+
+ JsonNode node = srcNode;
+ for (int i = 0; i < path.size() - 1; i++) {
+ node = node.get(path.get(i));
+ if (node == null) {
+ throw new NotFoundException();
+ }
+ }
+
+ ((ObjectNode) node).set(path.get(path.size() - 1), null);
+
+ return IOUtils.toInputStream(srcNode.toString());
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/8f3541c2/fit/src/main/java/org/apache/olingo/fit/utils/XMLEventReaderWrapper.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/XMLEventReaderWrapper.java b/fit/src/main/java/org/apache/olingo/fit/utils/XMLEventReaderWrapper.java
index eaf3e8c..6ba0ee9 100644
--- a/fit/src/main/java/org/apache/olingo/fit/utils/XMLEventReaderWrapper.java
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/XMLEventReaderWrapper.java
@@ -47,30 +47,22 @@ public class XMLEventReaderWrapper implements XMLEventReader {
this.wrapped = factory.createXMLEventReader(
new ByteArrayInputStream(
(XMLEventReaderWrapper.CONTENT_STAG
- + IOUtils.toString(stream)
+ + IOUtils.toString(stream).replaceAll("^<\\?xml.*\\?>", "")
+ XMLEventReaderWrapper.CONTENT_ETAG).getBytes()));
- init(wrapped);
+ init();
}
- public XMLEventReaderWrapper(final XMLEventReader wrapped) {
- this.wrapped = wrapped;
- init(wrapped);
- }
-
- private void init(final XMLEventReader wrapped) {
+ private void init() {
try {
- this.nextGivenEvent = this.wrapped.nextEvent();
+ do {
- if (this.nextGivenEvent.isStartDocument()) {
- this.nextGivenEvent = this.wrapped.nextEvent(); // discard start document
- }
+ this.nextGivenEvent = this.wrapped.nextEvent();
- if (this.nextGivenEvent.isStartElement()
- && CONTENT.equals(this.nextGivenEvent.asStartElement().getName().getLocalPart())) {
- this.nextGivenEvent = this.wrapped.nextEvent(); // discard content start tag
- }
+ } while (this.nextGivenEvent.isStartDocument()
+ || (this.nextGivenEvent.isStartElement()
+ && CONTENT.equals(this.nextGivenEvent.asStartElement().getName().getLocalPart())));
} catch (Exception ignore) {
// ignore
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/8f3541c2/fit/src/main/java/org/apache/olingo/fit/utils/XMLUtilities.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/XMLUtilities.java b/fit/src/main/java/org/apache/olingo/fit/utils/XMLUtilities.java
index bfe5890..564f1f4 100644
--- a/fit/src/main/java/org/apache/olingo/fit/utils/XMLUtilities.java
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/XMLUtilities.java
@@ -24,6 +24,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
+import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.util.AbstractMap;
@@ -50,30 +51,165 @@ 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.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
public class XMLUtilities extends AbstractUtilities {
- protected static XMLInputFactory factory = null;
+ protected static XMLInputFactory ifactory = null;
+
+ protected static XMLOutputFactory ofactory = null;
public XMLUtilities(final ODataVersion version) throws Exception {
super(version);
}
+ public void retrieveLinkInfoFromMetadata() throws Exception {
+
+ final MetadataLinkInfo metadataLinkInfo = new MetadataLinkInfo();
+ Commons.linkInfo.put(version, metadataLinkInfo);
+
+ final InputStream metadata = fsManager.readFile(Constants.METADATA, Accept.XML);
+ final XMLEventReader reader = getEventReader(metadata);
+
+ int initialDepth = 0;
+ try {
+ while (true) {
+ Map.Entry<Integer, XmlElement> entityType =
+ extractElement(reader, null, Collections.<String>singletonList("EntityType"),
+ null, false, initialDepth, 4, 4);
+ initialDepth = entityType.getKey();
+
+ final String entitySetName =
+ entityType.getValue().getStart().getAttributeByName(new QName("Name")).getValue();
+
+ final XMLEventReader entityReader = getEventReader(entityType.getValue().toStream());
+ 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);
+ }
+ }
+ } catch (Exception e) {
+ } finally {
+ reader.close();
+ }
+ }
+
+ private Map.Entry<String, Boolean> getTargetInfo(final StartElement element, final String linkName)
+ throws Exception {
+ final InputStream metadata = fsManager.readFile(Constants.METADATA, Accept.XML);
+ XMLEventReader reader = getEventReader(metadata);
+
+ 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();
+ IOUtils.closeQuietly(metadata);
+
+ final InputStream associationContent = association.getValue().toStream();
+ reader = getEventReader(associationContent);
+
+ final 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 String target = associationEnd.getValue().getStart().getAttributeByName(new QName("Type")).getValue();
+ final boolean feed = associationEnd.getValue().getStart().getAttributeByName(
+ new QName("Multiplicity")).getValue().equals("*");
+
+ return new SimpleEntry<String, Boolean>(target, feed);
+ }
+
@Override
protected Accept getDefaultFormat() {
return Accept.ATOM;
}
- protected static XMLEventReader getEventReader(final InputStream is) throws XMLStreamException {
- if (factory == null) {
- factory = XMLInputFactory.newInstance();
+ protected XMLEventReader getEventReader(final InputStream is) throws XMLStreamException {
+ if (ifactory == null) {
+ ifactory = XMLInputFactory.newInstance();
+ }
+ ifactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, false);
+ return ifactory.createXMLEventReader(is);
+ }
+
+ protected static XMLEventWriter getEventWriter(final OutputStream os) throws XMLStreamException {
+ if (ofactory == null) {
+ ofactory = XMLOutputFactory.newInstance();
+ }
+
+ return ofactory.createXMLEventWriter(os);
+ }
+
+ private void writeEvent(final XMLEvent event, final XMLEventWriter writer) {
+ if (writer != null) {
+ try {
+ writer.add(event);
+ } catch (XMLStreamException e) {
+ LOG.error("Error writing event {}", event, e);
+ }
+ }
+ }
+
+ private void skipElement(
+ final StartElement start,
+ final XMLEventReader reader,
+ final XMLEventWriter writer,
+ final boolean excludeStart)
+ throws Exception {
+
+ if (!excludeStart) {
+ writeEvent(start, writer);
+ }
+
+ int depth = 1;
+ boolean found = false;
+
+ while (reader.hasNext() && !found) {
+ final XMLEvent event = reader.nextEvent();
+
+ writeEvent(event, writer);
+
+ if (event.getEventType() == XMLStreamConstants.START_ELEMENT) {
+ depth++;
+ } else if (event.getEventType() == XMLStreamConstants.END_ELEMENT) {
+ depth--;
+ found = depth == 0 && start.getName().equals(event.asEndElement().getName());
+ }
}
- factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, false);
- return factory.createXMLEventReader(is);
}
/**
@@ -91,12 +227,12 @@ public class XMLUtilities extends AbstractUtilities {
final XMLEventFactory eventFactory = XMLEventFactory.newInstance();
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
- final XMLOutputFactory xof = XMLOutputFactory.newInstance();
- final XMLEventWriter writer = xof.createXMLEventWriter(bos);
+ final XMLEventWriter writer = getEventWriter(bos);
// -----------------------------------------
+ final Map.Entry<Integer, XmlElement> entry =
+ extractElement(reader, writer, Collections.singletonList("entry"), 0, 1, 1);
- final XmlElement entry = getAtomElement(reader, writer, "entry");
- writer.add(entry.getStart());
+ writer.add(entry.getValue().getStart());
// add for links
for (String link : links) {
@@ -113,8 +249,8 @@ public class XMLUtilities extends AbstractUtilities {
writer.add(eventFactory.createEndElement(new QName(LINK), null));
}
- writer.add(entry.getContentReader());
- writer.add(entry.getEnd());
+ writer.add(entry.getValue().getContentReader());
+ writer.add(entry.getValue().getEnd());
writer.add(reader);
IOUtils.closeQuietly(is);
@@ -140,7 +276,7 @@ public class XMLUtilities extends AbstractUtilities {
while (true) {
final Map.Entry<Integer, XmlElement> linkInfo =
- getAtomElement(reader, null, LINK, null, startDepth, 2, 2, true);
+ extractElement(reader, null, Collections.<String>singletonList(LINK), startDepth, 2, 2);
startDepth = linkInfo.getKey();
@@ -177,8 +313,8 @@ public class XMLUtilities extends AbstractUtilities {
while (true) {
// a. search for link with type attribute equals to "application/atom+xml;type=entry/feed"
- final Map.Entry<Integer, XmlElement> linkInfo = getAtomElement(
- reader, null, LINK, filter, startDepth, 2, 2, true);
+ final Map.Entry<Integer, XmlElement> linkInfo = extractElement(
+ reader, null, Collections.<String>singletonList(LINK), filter, true, startDepth, 2, 2);
final XmlElement link = linkInfo.getValue();
startDepth = linkInfo.getKey();
@@ -186,12 +322,16 @@ public class XMLUtilities extends AbstractUtilities {
final String href = link.getStart().getAttributeByName(new QName("href")).getValue();
try {
- final XmlElement inlineElement = getAtomElement(link.getContentReader(), null, INLINE);
+ final XmlElement inlineElement =
+ extractElement(link.getContentReader(), null, Collections.<String>singletonList(INLINE), 0, -1, -1).
+ getValue();
final XMLEventReader inlineReader = inlineElement.getContentReader();
try {
while (true) {
- final XmlElement entry = getAtomElement(inlineReader, null, "entry");
+ final XmlElement entry =
+ extractElement(inlineReader, null, Collections.<String>singletonList("entry"), 0, -1, -1).
+ getValue();
links.addInlines(title, entry.toStream());
}
} catch (Exception e) {
@@ -231,8 +371,7 @@ public class XMLUtilities extends AbstractUtilities {
is.close();
final ByteArrayOutputStream tmpBos = new ByteArrayOutputStream();
- final XMLOutputFactory xof = XMLOutputFactory.newInstance();
- final XMLEventWriter writer = xof.createXMLEventWriter(tmpBos);
+ final XMLEventWriter writer = getEventWriter(tmpBos);
final XMLEventReader reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
// -----------------------------------------
@@ -251,8 +390,9 @@ public class XMLUtilities extends AbstractUtilities {
while (true) {
// a. search for link with type attribute equals to "application/atom+xml;type=entry/feed"
- linkInfo = getAtomElement(
- reader, writer, LINK, filter, linkInfo == null ? 0 : linkInfo.getKey(), 2, 2, true);
+ linkInfo = extractElement(
+ reader, writer, Collections.<String>singletonList(LINK), filter, true,
+ linkInfo == null ? 0 : linkInfo.getKey(), 2, 2);
final XmlElement link = linkInfo.getValue();
final String title = link.getStart().getAttributeByName(new QName("title")).getValue();
@@ -300,104 +440,7 @@ public class XMLUtilities extends AbstractUtilities {
}
- public XmlElement getAtomElement(
- final InputStream is,
- final String name)
- throws Exception {
- return getAtomElement(is, name, -1, -1);
- }
-
- public static XmlElement getAtomElement(
- final InputStream is,
- final String name,
- final int minDepth,
- final int maxDepth)
- throws Exception {
- final XMLEventReader reader = getEventReader(is);
- final XmlElement res = getAtomElement(reader, null, name, null, 0, minDepth, maxDepth, false).getValue();
- reader.close();
-
- return res;
- }
-
- public static XmlElement getAtomElement(
- final XMLEventReader reader,
- final XMLEventWriter discarded,
- final String name)
- throws Exception {
- return getAtomElement(reader, discarded, name, null, 0, -1, -1, false).getValue();
- }
-
- public XmlElement getAtomElement(
- final XMLEventReader reader,
- final XMLEventWriter discarded,
- final String name,
- final Collection<Map.Entry<String, String>> filterAttrs)
- throws Exception {
- return getAtomElement(reader, discarded, name, filterAttrs, 0, -1, -1, false).getValue();
- }
-
- public static Map.Entry<Integer, XmlElement> getAtomElement(
- final XMLEventReader reader,
- final XMLEventWriter discarded,
- final String name,
- final Collection<Map.Entry<String, String>> filterAttrs,
- final int initialDepth,
- final int minDepth,
- final int maxDepth,
- final boolean filterInOr)
- throws Exception {
-
- int depth = initialDepth;
- StartElement start = null;
-
- while (reader.hasNext() && start == null) {
- final XMLEvent event = reader.nextEvent();
-
- if (event.getEventType() == XMLStreamConstants.START_ELEMENT) {
- depth++;
-
- if ((StringUtils.isBlank(name) || name.trim().equals(event.asStartElement().getName().getLocalPart()))
- && (minDepth < 0 || minDepth <= depth) && (maxDepth < 0 || maxDepth >= depth)) {
-
- boolean match = filterAttrs == null || filterAttrs.isEmpty() || !filterInOr;
-
- for (Map.Entry<String, String> filterAttr : filterAttrs == null
- ? Collections.<Map.Entry<String, String>>emptySet() : filterAttrs) {
- final Attribute attr =
- event.asStartElement().getAttributeByName(new QName(filterAttr.getKey().trim()));
-
- if (attr == null || !filterAttr.getValue().trim().equals(attr.getValue())) {
- match = filterInOr ? match : false;
- } else {
- match = filterInOr ? true : match;
- }
- }
-
- if (match) {
- start = event.asStartElement();
- }
- }
-
- } else if (event.getEventType() == XMLStreamConstants.END_ELEMENT) {
- depth--;
- }
-
- if (start == null) {
- if (discarded != null) {
- discarded.add(event);
- }
- }
- }
-
- if (start == null) {
- throw new Exception(String.format("Could not find an element named '%s'", name));
- }
-
- return new SimpleEntry<Integer, XmlElement>(Integer.valueOf(depth - 1), getAtomElement(start, reader));
- }
-
- public static XmlElement getAtomElement(
+ public XmlElement getXmlElement(
final StartElement start,
final XMLEventReader reader)
throws Exception {
@@ -412,11 +455,9 @@ public class XMLUtilities extends AbstractUtilities {
while (reader.hasNext() && depth > 0) {
final XMLEvent event = reader.nextEvent();
- if (event.getEventType() == XMLStreamConstants.START_ELEMENT
- && start.getName().getLocalPart().equals(event.asStartElement().getName().getLocalPart())) {
+ if (event.getEventType() == XMLStreamConstants.START_ELEMENT) {
depth++;
- } else if (event.getEventType() == XMLStreamConstants.END_ELEMENT
- && start.getName().getLocalPart().equals(event.asEndElement().getName().getLocalPart())) {
+ } else if (event.getEventType() == XMLStreamConstants.END_ELEMENT) {
depth--;
}
@@ -467,7 +508,6 @@ public class XMLUtilities extends AbstractUtilities {
public InputStream addEditLink(
final InputStream content, final String title, final String href)
throws Exception {
- final XMLOutputFactory xof = XMLOutputFactory.newInstance();
final ByteArrayOutputStream copy = new ByteArrayOutputStream();
IOUtils.copy(content, copy);
@@ -477,15 +517,15 @@ public class XMLUtilities extends AbstractUtilities {
XMLEventReader reader = getEventReader(new ByteArrayInputStream(copy.toByteArray()));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
- XMLEventWriter writer = xof.createXMLEventWriter(bos);
+ XMLEventWriter writer = getEventWriter(bos);
final String editLinkElement = String.format("<link rel=\"edit\" title=\"%s\" href=\"%s\" />", title, href);
try {
// check edit link existence
- getAtomElement(reader, writer, LINK,
+ extractElement(reader, writer, Collections.<String>singletonList(LINK),
Collections.<Map.Entry<String, String>>singletonList(
- new AbstractMap.SimpleEntry<String, String>("rel", "edit")));
+ new AbstractMap.SimpleEntry<String, String>("rel", "edit")), false, 0, -1, -1);
addAtomElement(IOUtils.toInputStream(editLinkElement), writer);
writer.add(reader);
@@ -495,9 +535,10 @@ public class XMLUtilities extends AbstractUtilities {
reader = getEventReader(new ByteArrayInputStream(copy.toByteArray()));
bos = new ByteArrayOutputStream();
- writer = xof.createXMLEventWriter(bos);
+ writer = getEventWriter(bos);
- final XmlElement entryElement = getAtomElement(reader, writer, "entry");
+ final XmlElement entryElement =
+ extractElement(reader, writer, Collections.<String>singletonList("entry"), 0, 1, 1).getValue();
writer.add(entryElement.getStart());
@@ -520,7 +561,6 @@ public class XMLUtilities extends AbstractUtilities {
public InputStream addAtomContent(
final InputStream content, final String title, final String href)
throws Exception {
- final XMLOutputFactory xof = XMLOutputFactory.newInstance();
final ByteArrayOutputStream copy = new ByteArrayOutputStream();
IOUtils.copy(content, copy);
@@ -530,11 +570,12 @@ public class XMLUtilities extends AbstractUtilities {
XMLEventReader reader = getEventReader(new ByteArrayInputStream(copy.toByteArray()));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
- XMLEventWriter writer = xof.createXMLEventWriter(bos);
+ XMLEventWriter writer = getEventWriter(bos);
try {
// check edit link existence
- XmlElement contentElement = getAtomElement(reader, writer, "content");
+ XmlElement contentElement =
+ extractElement(reader, writer, Collections.<String>singletonList("content"), 0, 2, 2).getValue();
writer.add(contentElement.getStart());
writer.add(contentElement.getContentReader());
writer.add(contentElement.getEnd());
@@ -544,10 +585,11 @@ public class XMLUtilities extends AbstractUtilities {
reader = getEventReader(new ByteArrayInputStream(copy.toByteArray()));
bos = new ByteArrayOutputStream();
- writer = xof.createXMLEventWriter(bos);
+ writer = getEventWriter(bos);
if (isMediaContent(title)) {
- final XmlElement entryElement = getAtomElement(reader, writer, "entry");
+ final XmlElement entryElement =
+ extractElement(reader, writer, Collections.<String>singletonList("entry"), 0, 1, 1).getValue();
writer.add(entryElement.getStart());
writer.add(entryElement.getContentReader());
@@ -559,7 +601,8 @@ public class XMLUtilities extends AbstractUtilities {
writer.add(entryElement.getEnd());
} else {
try {
- final XmlElement entryElement = getAtomElement(reader, writer, PROPERTIES);
+ final XmlElement entryElement =
+ extractElement(reader, writer, Collections.<String>singletonList(PROPERTIES), 0, 2, 3).getValue();
addAtomElement(
IOUtils.toInputStream("<content type=\"application/xml\">"),
@@ -577,9 +620,10 @@ public class XMLUtilities extends AbstractUtilities {
reader = getEventReader(new ByteArrayInputStream(copy.toByteArray()));
bos = new ByteArrayOutputStream();
- writer = xof.createXMLEventWriter(bos);
+ writer = getEventWriter(bos);
- final XmlElement entryElement = getAtomElement(reader, writer, "entry");
+ final XmlElement entryElement =
+ extractElement(reader, writer, Collections.<String>singletonList("entry"), 0, 1, 1).getValue();
writer.add(entryElement.getStart());
writer.add(entryElement.getContentReader());
@@ -643,103 +687,101 @@ public class XMLUtilities extends AbstractUtilities {
return count;
}
- public static StartElement getPropertyStartTag(final XMLEventReader propReader, final String[] path)
+ public Map.Entry<Integer, XmlElement> extractElement(
+ final XMLEventReader reader, final XMLEventWriter writer, final List<String> path,
+ final int startPathPos, final int minPathPos, final int maxPathPos)
throws Exception {
- int pos = 0;
-
- StartElement property = null;
-
- while (propReader.hasNext() && pos < path.length) {
- final XMLEvent event = propReader.nextEvent();
-
- if (event.getEventType() == XMLStreamConstants.START_ELEMENT
- && (ATOM_PROPERTY_PREFIX + path[pos].trim()).equals(
- event.asStartElement().getName().getLocalPart())) {
- pos++;
- if (path.length == pos) {
- property = event.asStartElement();
- }
- }
- }
-
- if (property == null) {
- throw new NotFoundException();
- }
-
- return property;
+ return extractElement(reader, writer, path, null, false, startPathPos, minPathPos, maxPathPos);
}
- public String getEdmTypeFromXML(final InputStream is, final String[] path)
+ public Map.Entry<Integer, XmlElement> extractElement(
+ final XMLEventReader reader, final XMLEventWriter writer, final List<String> path,
+ final Collection<Map.Entry<String, String>> filter,
+ final boolean filterInOr,
+ final int startPathPos, final int minPathPos, final int maxPathPos)
throws Exception {
- final XMLEventReader reader = getEventReader(is);
- final Attribute type = getPropertyStartTag(reader, path).getAttributeByName(new QName(TYPE));
-
- reader.close();
-
- if (type == null) {
- throw new NotFoundException();
- }
+ StartElement start = null;
+ int searchFor = 0;
+ int depth = startPathPos;
- return type.getValue();
- }
+ // Current inspected element
+ String current = null;
- public InputStream getAtomProperty(final InputStream is, final String[] path)
- throws Exception {
- final XMLEventReader reader = getEventReader(is);
-
- final XmlElement props = getAtomElement(reader, null, PROPERTIES);
- final XMLEventReader propsReader = props.getContentReader();
+ // set defaults
+ final List<String> pathElementNames = path == null ? Collections.<String>emptyList() : path;
+ final Collection<Map.Entry<String, String>> filterAttrs =
+ filter == null ? Collections.<Map.Entry<String, String>>emptySet() : filter;
- reader.close();
+ while (reader.hasNext() && start == null) {
+ final XMLEvent event = reader.nextEvent();
- final InputStream propertyStream = writeFromStartToEndElement(
- getPropertyStartTag(propsReader, path),
- propsReader,
- true);
+ if (event.getEventType() == XMLStreamConstants.START_ELEMENT) {
+ depth++;
- if (propertyStream == null) {
- throw new NotFoundException();
- }
+ if (current != null || ((minPathPos < 0 || minPathPos <= depth) && (maxPathPos < 0 || depth <= maxPathPos))) {
+ if (pathElementNames.isEmpty()
+ || pathElementNames.get(searchFor).trim().equals(event.asStartElement().getName().getLocalPart())) {
- return propertyStream;
- }
+ if (searchFor < pathElementNames.size() - 1) {
+ // path exploring not completed
+ writeEvent(event, writer);
+ current = pathElementNames.get(searchFor).trim();
+ searchFor++;
+ } else {
- private InputStream writeFromStartToEndElement(
- final StartElement element, final XMLEventReader reader, final boolean document)
- throws XMLStreamException {
- final ByteArrayOutputStream bos = new ByteArrayOutputStream();
- final XMLOutputFactory xof = XMLOutputFactory.newInstance();
- final XMLEventWriter writer = xof.createXMLEventWriter(bos);
+ // path exploring completed ... evaluate filter about path element name attribute
+ boolean match = filterAttrs.isEmpty() || !filterInOr;
+
+ for (Map.Entry<String, String> filterAttr : filterAttrs) {
+ final Attribute attr = event.asStartElement().getAttributeByName(new QName(filterAttr.getKey().trim()));
+
+ if (attr == null || !filterAttr.getValue().trim().equals(attr.getValue())) {
+ match = filterInOr ? match : false;
+ } else {
+ match = filterInOr ? true : match;
+ }
+ }
+
+ if (match) {
+ // found searched element
+ start = event.asStartElement();
+ } else {
+ skipElement(event.asStartElement(), reader, writer, false);
+ depth--;
+ }
+ }
+ } else if (current == null) {
+ writeEvent(event, writer);
+ } else {
+ // skip element
+ skipElement(event.asStartElement(), reader, writer, false);
+ depth--;
+ }
+ } else {
+ writeEvent(event, writer);
+ }
- final QName name = element.getName();
+ } else if (event.getEventType() == XMLStreamConstants.END_ELEMENT) {
+ depth--;
- if (document) {
- final XMLEventFactory eventFactory = XMLEventFactory.newInstance();
- writer.add(eventFactory.createStartDocument("UTF-8", "1.0"));
- writer.add(element);
+ writeEvent(event, writer);
- if (element.getAttributeByName(new QName(ATOM_DATASERVICE_NS)) == null) {
- writer.add(eventFactory.createNamespace(ATOM_PROPERTY_PREFIX.substring(0, 1), DATASERVICES_NS));
- }
- if (element.getAttributeByName(new QName(ATOM_METADATA_NS)) == null) {
- writer.add(eventFactory.createNamespace(ATOM_METADATA_PREFIX.substring(0, 1), METADATA_NS));
+ if (event.asEndElement().getName().getLocalPart().equals(current)) {
+ // back step ....
+ searchFor--;
+ current = searchFor > 0 ? pathElementNames.get(searchFor - 1).trim() : null;
+ }
+ } else {
+ writeEvent(event, writer);
}
- } else {
- writer.add(element);
}
- XMLEvent event = element;
-
- while (reader.hasNext() && !(event.isEndElement() && name.equals(event.asEndElement().getName()))) {
- event = reader.nextEvent();
- writer.add(event);
+ if (start == null) {
+ throw new NotFoundException();
}
- writer.flush();
- writer.close();
-
- return new ByteArrayInputStream(bos.toByteArray());
+ return new SimpleEntry<Integer, XmlElement>(Integer.valueOf(depth - 1), getXmlElement(start, reader));
}
public InputStream addAtomInlinecount(
@@ -748,12 +790,12 @@ public class XMLUtilities extends AbstractUtilities {
final XMLEventReader reader = getEventReader(feed);
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
- final XMLOutputFactory xof = XMLOutputFactory.newInstance();
- final XMLEventWriter writer = xof.createXMLEventWriter(bos);
+ final XMLEventWriter writer = getEventWriter(bos);
try {
- final XmlElement feedElement = getAtomElement(reader, writer, "feed");
+ final XmlElement feedElement =
+ extractElement(reader, writer, Collections.<String>singletonList("feed"), 0, 1, 1).getValue();
writer.add(feedElement.getStart());
addAtomElement(IOUtils.toInputStream(String.format("<m:count>%d</m:count>", count)), writer);
@@ -774,28 +816,23 @@ public class XMLUtilities extends AbstractUtilities {
return new ByteArrayInputStream(bos.toByteArray());
}
- public static InputStream getAtomPropertyValue(final InputStream is, final String[] path)
+ @Override
+ public InputStream getPropertyValue(final InputStream is, final List<String> path)
throws Exception {
- final XmlElement props = getAtomElement(is, PROPERTIES, 2, 3);
- final XMLEventReader propsReader = props.getContentReader();
- // search for property start element
- getPropertyStartTag(propsReader, ArrayUtils.subarray(path, 0, path.length - 1));
+ final List<String> pathElements = new ArrayList<String>();
- final InputStream res;
+ for (String element : path) {
+ pathElements.add(ATOM_PROPERTY_PREFIX + element);
+ }
- XMLEvent event = propsReader.nextEvent();
+ final XMLEventReader reader = getEventReader(is);
+ final Map.Entry<Integer, XmlElement> property = extractElement(reader, null, pathElements, 0, 3, 4);
- // expected text node
- if (event.isCharacters()) {
- res = new ByteArrayInputStream(event.asCharacters().getData().getBytes());
- } else if (event.isEndElement()) {
- throw new NotFoundException();
- } else {
- throw new Exception("The method or operation is not implemented.");
- }
+ reader.close();
+ IOUtils.closeQuietly(is);
- return res;
+ return property.getValue().getContent();
}
@Override
@@ -803,8 +840,7 @@ public class XMLUtilities extends AbstractUtilities {
final XMLEventReader reader = getEventReader(entity);
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
- final XMLOutputFactory xof = XMLOutputFactory.newInstance();
- final XMLEventWriter writer = xof.createXMLEventWriter(bos);
+ final XMLEventWriter writer = getEventWriter(bos);
final List<String> found = new ArrayList<String>(Arrays.asList(propertyNames));
@@ -912,7 +948,11 @@ public class XMLUtilities extends AbstractUtilities {
final Map.Entry<String, String> uri = Commons.parseEntityURI(link);
final XmlElement entry =
- getAtomElement(readEntity(uri.getKey(), uri.getValue(), Accept.ATOM).getValue(), "entry");
+ extractElement(
+ getEventReader(readEntity(uri.getKey(), uri.getValue(), Accept.ATOM).getValue()),
+ null,
+ Collections.<String>singletonList("entry"),
+ 0, 1, 1).getValue();
IOUtils.copy(entry.toStream(), bos);
} catch (Exception e) {
@@ -945,14 +985,14 @@ public class XMLUtilities extends AbstractUtilities {
XMLEventReader reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
final Map.Entry<Integer, XmlElement> propertyElement =
- getAtomElement(reader, null, PROPERTIES, null, 0, 2, 3, false);
+ extractElement(reader, null, Collections.<String>singletonList(PROPERTIES), 0, 2, 3);
reader.close();
reader = propertyElement.getValue().getContentReader();
try {
while (true) {
- final XmlElement property = getAtomElement(reader, null, null);
+ final XmlElement property = extractElement(reader, null, null, 0, -1, -1).getValue();
res.put(property.getStart().getName().getLocalPart(), property.toStream());
}
} catch (Exception ignore) {
@@ -968,7 +1008,7 @@ public class XMLUtilities extends AbstractUtilities {
int pos = 0;
while (true) {
final Map.Entry<Integer, XmlElement> linkElement =
- getAtomElement(reader, null, LINK, null, pos, 2, 2, false);
+ extractElement(reader, null, Collections.<String>singletonList(LINK), pos, 2, 2);
res.put("[LINK]" + linkElement.getValue().getStart().getAttributeByName(new QName("title")).getValue(),
linkElement.getValue().toStream());
@@ -990,14 +1030,13 @@ public class XMLUtilities extends AbstractUtilities {
XMLEventReader reader = getEventReader(toBeChanged);
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
- final XMLOutputFactory xof = XMLOutputFactory.newInstance();
- XMLEventWriter writer = xof.createXMLEventWriter(bos);
+ XMLEventWriter writer = getEventWriter(bos);
// ---------------------------------
// add property changes
// ---------------------------------
Map.Entry<Integer, XmlElement> propertyElement =
- getAtomElement(reader, writer, PROPERTIES, null, 0, 2, 3, false);
+ extractElement(reader, writer, Collections.<String>singletonList(PROPERTIES), 0, 2, 3);
writer.flush();
@@ -1008,7 +1047,7 @@ public class XMLUtilities extends AbstractUtilities {
try {
while (true) {
- final XmlElement property = getAtomElement(propertyReader, null, null);
+ final XmlElement property = extractElement(propertyReader, null, null, 0, -1, -1).getValue();
final String name = property.getStart().getName().getLocalPart();
if (properties.containsKey(name)) {
@@ -1058,14 +1097,14 @@ public class XMLUtilities extends AbstractUtilities {
reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
bos.reset();
- writer = xof.createXMLEventWriter(bos);
+ writer = getEventWriter(bos);
try {
final String linkName = remains.getKey().substring(remains.getKey().indexOf("]") + 1);
- getAtomElement(reader, writer, LINK,
- Collections.<Map.Entry<String, String>>singleton(new SimpleEntry<String, String>(
- "title", linkName)), 0, 2, 2, false);
+ extractElement(reader, writer, Collections.<String>singletonList(LINK),
+ Collections.<Map.Entry<String, String>>singleton(new SimpleEntry<String, String>("title", linkName)),
+ false, 0, 2, 2);
writer.add(reader);
@@ -1081,9 +1120,9 @@ public class XMLUtilities extends AbstractUtilities {
reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
bos.reset();
- writer = xof.createXMLEventWriter(bos);
+ writer = getEventWriter(bos);
- propertyElement = getAtomElement(reader, writer, CONTENT, null, 0, 2, 2, false);
+ propertyElement = extractElement(reader, writer, Collections.<String>singletonList(CONTENT), 0, 2, 2);
writer.flush();
pbos.reset();
@@ -1122,17 +1161,16 @@ public class XMLUtilities extends AbstractUtilities {
final XMLEventReader reader = getEventReader(toBeChanged);
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
- final XMLOutputFactory xof = XMLOutputFactory.newInstance();
- final XMLEventWriter writer = xof.createXMLEventWriter(bos);
+ final XMLEventWriter writer = getEventWriter(bos);
final XMLEventFactory eventFactory = XMLEventFactory.newInstance();
XMLEvent newLine = eventFactory.createSpace("\n");
try {
final XmlElement linkElement =
- getAtomElement(reader, writer, LINK,
- Collections.<Map.Entry<String, String>>singletonList(
- new SimpleEntry<String, String>("title", linkName)));
+ extractElement(reader, writer, Collections.<String>singletonList(LINK),
+ Collections.<Map.Entry<String, String>>singletonList(new SimpleEntry<String, String>("title", linkName)),
+ false, 0, -1, -1).getValue();
writer.add(linkElement.getStart());
// ------------------------------------------
@@ -1160,7 +1198,42 @@ public class XMLUtilities extends AbstractUtilities {
return new ByteArrayInputStream(bos.toByteArray());
}
- public static Map.Entry<String, List<String>> extractLinkURIs(final InputStream is)
+ public String getEdmTypeFromAtom(final String entitySetName, final String entityId, final List<String> path)
+ throws Exception {
+ InputStream src = fsManager.readFile(Commons.getEntityBasePath(entitySetName, entityId) + ENTITY, Accept.XML);
+
+ final List<String> atomPathElements = new ArrayList<String>();
+
+ for (String element : path) {
+ atomPathElements.add(ATOM_PROPERTY_PREFIX + element);
+ }
+
+ final Map.Entry<Integer, XmlElement> prop = extractElement(getEventReader(src), null, atomPathElements, 0, 3, 4);
+ IOUtils.closeQuietly(src);
+
+ final Attribute type = prop.getValue().getStart().getAttributeByName(new QName(TYPE));
+
+ final String edmType;
+
+ if (type == null) {
+ edmType = Constants.ATOM_DEF_TYPE;
+ } else {
+ edmType = type.getValue();
+ }
+
+ return edmType;
+ }
+
+ @Override
+ public Map.Entry<String, List<String>> extractLinkURIs(
+ final String entitySetName, final String entityId, final String linkName)
+ throws Exception {
+ final LinkInfo links = readLinks(entitySetName, entityId, linkName, Accept.XML);
+ return extractLinkURIs(links.getLinks());
+ }
+
+ @Override
+ public Map.Entry<String, List<String>> extractLinkURIs(final InputStream is)
throws Exception {
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
IOUtils.copy(is, bos);
@@ -1170,7 +1243,8 @@ public class XMLUtilities extends AbstractUtilities {
final List<String> links = new ArrayList<String>();
try {
while (true) {
- links.add(IOUtils.toString(getAtomElement(reader, null, "uri").getContent()));
+ links.add(IOUtils.toString(extractElement(reader, null, Collections.<String>singletonList("uri"), 0, -1, -1).
+ getValue().getContent()));
}
} catch (Exception ignore) {
// End document reached ...
@@ -1181,7 +1255,8 @@ public class XMLUtilities extends AbstractUtilities {
reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
try {
- next = IOUtils.toString(getAtomElement(reader, null, "next").getContent());
+ next = IOUtils.toString(extractElement(reader, null, Collections.<String>singletonList("next"), 0, -1, -1).
+ getValue().getContent());
} catch (Exception ignore) {
// next link is not mandatory
next = null;
@@ -1190,4 +1265,122 @@ public class XMLUtilities extends AbstractUtilities {
return new AbstractMap.SimpleEntry<String, List<String>>(next, links);
}
+
+ @Override
+ public InputStream getProperty(
+ final String entitySetName, final String entityId, final List<String> path, final String edmType)
+ throws Exception {
+ final List<String> pathElements = new ArrayList<String>();
+
+ for (String element : path) {
+ pathElements.add(ATOM_PROPERTY_PREFIX + element);
+ }
+
+ final InputStream src =
+ fsManager.readFile(Commons.getEntityBasePath(entitySetName, entityId) + ENTITY, Accept.XML);
+
+ final XMLEventReader reader = getEventReader(src);
+ final XmlElement property = extractElement(reader, null, pathElements, 0, 3, 4).getValue();
+
+ reader.close();
+ IOUtils.closeQuietly(src);
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ final XMLEventWriter writer = getEventWriter(bos);
+
+ final XMLEventFactory eventFactory = XMLEventFactory.newInstance();
+ writer.add(eventFactory.createStartDocument("UTF-8", "1.0"));
+ writer.add(property.getStart());
+
+ if (property.getStart().getAttributeByName(new QName(ATOM_DATASERVICE_NS)) == null) {
+ writer.add(eventFactory.createNamespace(ATOM_PROPERTY_PREFIX.substring(0, 1), DATASERVICES_NS));
+ }
+ if (property.getStart().getAttributeByName(new QName(ATOM_METADATA_NS)) == null) {
+ writer.add(eventFactory.createNamespace(ATOM_METADATA_PREFIX.substring(0, 1), METADATA_NS));
+ }
+
+ writer.add(property.getContentReader());
+ writer.add(property.getEnd());
+
+ writer.flush();
+ writer.close();
+
+ return new ByteArrayInputStream(bos.toByteArray());
+ }
+
+ @Override
+ public InputStream replaceProperty(
+ final InputStream src, final InputStream replacement, final List<String> path, final boolean justValue)
+ throws Exception {
+
+ final List<String> pathElements = new ArrayList<String>();
+
+ for (String element : path) {
+ pathElements.add(ATOM_PROPERTY_PREFIX + element);
+ }
+
+ final XMLEventReader reader = getEventReader(src);
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ final XMLEventWriter writer = getEventWriter(bos);
+
+ final Map.Entry<Integer, XmlElement> element = extractElement(reader, writer, pathElements, 0, 3, 4);
+
+ if (justValue) {
+ writer.add(element.getValue().getStart());
+ }
+
+ final XMLEventReader changesReader = new XMLEventReaderWrapper(replacement);
+
+ writer.add(changesReader);
+ changesReader.close();
+ IOUtils.closeQuietly(replacement);
+
+ if (justValue) {
+ writer.add(element.getValue().getEnd());
+ }
+
+ writer.add(reader);
+
+ reader.close();
+ IOUtils.closeQuietly(src);
+
+ writer.flush();
+ writer.close();
+
+ return new ByteArrayInputStream(bos.toByteArray());
+ }
+
+ @Override
+ public InputStream deleteProperty(final InputStream src, final List<String> path) throws Exception {
+
+ final List<String> pathElements = new ArrayList<String>();
+
+ for (String element : path) {
+ pathElements.add(ATOM_PROPERTY_PREFIX + element);
+ }
+
+ final XMLEventReader reader = getEventReader(src);
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ final XMLEventWriter writer = getEventWriter(bos);
+
+ final Map.Entry<Integer, XmlElement> element = extractElement(reader, writer, pathElements, 0, 3, 4);
+
+ final XMLEventReader changesReader = new XMLEventReaderWrapper(
+ IOUtils.toInputStream(String.format("<%s m:null=\"true\" />", path.get(path.size() - 1))));
+
+ writer.add(changesReader);
+ changesReader.close();
+
+ writer.add(reader);
+
+ reader.close();
+ IOUtils.closeQuietly(src);
+
+ writer.flush();
+ writer.close();
+
+ return new ByteArrayInputStream(bos.toByteArray());
+ }
}