public void write( UriInfo uriInfo, Writer w, String entityName, Entity entity, Collection<Link> links, Map<Transition, RESTResource> embeddedResources) { String baseUri = AtomXMLProvider.getBaseUri(serviceDocument, uriInfo); String absoluteId = getAbsoluteId(uriInfo, links); DateTime utc = new DateTime().withZone(DateTimeZone.UTC); String updated = InternalUtil.toString(utc); Abdera abdera = new Abdera(); StreamWriter writer = abdera.newStreamWriter(); writer.setOutputStream(new WriterOutputStream(w)); writer.setAutoflush(false); writer.setAutoIndent(true); writer.startDocument(); writer.startEntry(); writer.writeNamespace("d", d); writer.writeNamespace("m", m); writer.writeAttribute("xml:base", baseUri); writeEntry(writer, entityName, entity, links, embeddedResources, baseUri, absoluteId, updated); writer.endEntry(); writer.endDocument(); writer.flush(); }
@Override protected IterationResult<Entry> advance() throws Exception { if (feed == null) { ClientResponse response = client.getEntities(request); ODataVersion version = InternalUtil.getDataServiceVersion( response.getHeaders().getFirst(ODataConstants.Headers.DATA_SERVICE_VERSION)); parser = FormatParserFactory.getParser( Feed.class, client.getFormatType(), new Settings(version, getMetadata(), getLastSegment(), null, fcMapping)); feed = parser.parse(client.getFeedReader(response)); feedEntries = feed.getEntries().iterator(); feedEntryCount = 0; } if (feedEntries.hasNext()) { feedEntryCount++; return IterationResult.next(feedEntries.next()); } // old-style paging: $page and $itemsPerPage if (request.getQueryParams().containsKey("$page") && request.getQueryParams().containsKey("$itemsPerPage")) { if (feedEntryCount == 0) return IterationResult.done(); int page = Integer.parseInt(request.getQueryParams().get("$page")); // int itemsPerPage = Integer.parseInt(request.getQueryParams().get("$itemsPerPage")); request = request.queryParam("$page", Integer.toString(page + 1)); } // new-style paging: $skiptoken else { if (feed.getNext() == null) return IterationResult.done(); int skipTokenIndex = feed.getNext().indexOf("$skiptoken="); if (skipTokenIndex > -1) { String skiptoken = feed.getNext().substring(skipTokenIndex + "$skiptoken=".length()); // decode the skiptoken first since it gets encoded as a query param skiptoken = URLDecoder.decode(skiptoken, "UTF-8"); request = request.queryParam("$skiptoken", skiptoken); } else if (feed.getNext().toLowerCase().startsWith("http")) { request = ODataClientRequest.get(feed.getNext()); } else { throw new UnsupportedOperationException(); } } feed = null; return advance(); // TODO stackoverflow possible here }
/* * Using the supplied EntityResource, add the embedded resources * from the OEntity embedded resources. NB - only an OEntity can * carry OLinks. */ public void addExpandedLinks(EntityResource<OEntity> entityResource) { RequestContext requestContext = RequestContext.getRequestContext(); Collection<Link> links = entityResource.getLinks(); if (links != null) { OEntity oentity = entityResource.getEntity(); List<OLink> olinks = oentity.getLinks(); for (OLink olink : olinks) { if (olink.isInline()) { String relid = InternalUtil.getEntityRelId(oentity); String href = relid + "/" + olink.getTitle(); for (Link link : links) { String linkHref = link.getHref(); if (requestContext != null) { // Extract the transition fragment from the URI path linkHref = link.getRelativeHref(getBaseUri(serviceDocument, uriInfo)); } if (href.equals(linkHref)) { if (entityResource.getEmbedded() == null) { entityResource.setEmbedded(new HashMap<Transition, RESTResource>()); } if (olink.isCollection()) { List<OEntity> oentities = olink.getRelatedEntities(); Collection<EntityResource<OEntity>> entityResources = new ArrayList<EntityResource<OEntity>>(); for (OEntity oe : oentities) { entityResources.add(new EntityResource<OEntity>(oe)); } entityResource .getEmbedded() .put(link.getTransition(), new CollectionResource<OEntity>(entityResources)); } else { // replace the OLink's on the current entity OEntity inlineOentity = olink.getRelatedEntity(); List<OLink> inlineResourceOlinks = formOLinks(new EntityResource<OEntity>(inlineOentity)); OEntity newInlineOentity = OEntities.create( inlineOentity.getEntitySet(), inlineOentity.getEntityKey(), inlineOentity.getProperties(), inlineResourceOlinks); entityResource .getEmbedded() .put(link.getTransition(), new EntityResource<OEntity>(newInlineOentity)); } } } } } } }
@Override public String toString() { return InternalUtil.reflectionToString(this); }
@Override public AtomFeed parse(Reader reader) { return parseFeed(InternalUtil.newXMLEventReader(reader)); }
@SuppressWarnings("unchecked") protected void writeProperty( XMLWriter2 writer, String name, EdmType type, Object value, boolean isDocumentElement, boolean writeType) { writer.startElement(new QName2(d, name, "d")); if (isDocumentElement) { writer.writeNamespace("m", m); writer.writeNamespace("d", d); } String sValue = null; if (!type.isSimple()) { if (writeType) { String typename = type.getFullyQualifiedTypeName(); if (value instanceof OCollection) { EdmCollectionType collectionType = (EdmCollectionType) type; typename = "Bag(" + collectionType.getItemType().getFullyQualifiedTypeName() + ")"; } writer.writeAttribute(new QName2(m, "type", "m"), typename); } // complex or collection if (value instanceof OCollection) { writeCollection(writer, name, (OCollection<? extends OObject>) value); } else if (value instanceof OComplexObject) { writeProperties(writer, ((OComplexObject) value).getProperties()); } else { // deprecated form of a complex object. List<OProperty<?>> complexProperties = (List<OProperty<?>>) value; if (complexProperties != null) { writeProperties(writer, complexProperties); } } } else { // simple // write the type attribute if requested and not a string if (writeType && type != EdmSimpleType.STRING) { writer.writeAttribute(new QName2(m, "type", "m"), type.getFullyQualifiedTypeName()); } // now write the value if (type == EdmSimpleType.INT32) { if (value != null) { sValue = value.toString(); } } else if (type == EdmSimpleType.INT16) { if (value != null) { sValue = value.toString(); } } else if (type == EdmSimpleType.INT64) { if (value != null) { sValue = value.toString(); } } else if (type == EdmSimpleType.BOOLEAN) { if (value != null) { sValue = value.toString(); } } else if (type == EdmSimpleType.BYTE) { if (value != null) { sValue = value.toString(); } } else if (type == EdmSimpleType.SBYTE) { if (value != null) { sValue = value.toString(); } } else if (type == EdmSimpleType.DECIMAL) { if (value != null) { sValue = ((BigDecimal) value).toPlainString(); } } else if (type == EdmSimpleType.SINGLE) { if (value != null) { sValue = value.toString(); } } else if (type == EdmSimpleType.DOUBLE) { if (value != null) { sValue = value.toString(); } } else if (type == EdmSimpleType.STRING) { if (value != null) { sValue = value.toString(); } } else if (type == EdmSimpleType.DATETIME) { if (value != null) sValue = InternalUtil.formatDateTimeForXml((LocalDateTime) value); } else if (type == EdmSimpleType.BINARY) { byte[] bValue = (byte[]) value; if (value != null) { sValue = Base64.encodeBase64String(bValue); } } else if (type == EdmSimpleType.GUID) { if (value != null) { sValue = value.toString(); } } else if (type == EdmSimpleType.TIME) { if (value != null) { sValue = InternalUtil.formatTimeForXml((LocalTime) value); } } else if (type == EdmSimpleType.DATETIMEOFFSET) { // Edm.DateTimeOffset '-'? yyyy '-' mm '-' dd 'T' hh ':' mm // ':' ss ('.' s+)? (zzzzzz)? if (value != null) { sValue = InternalUtil.formatDateTimeOffsetForXml((DateTime) value); } } else { throw new UnsupportedOperationException("Implement " + type); } } if (value == null) { writer.writeAttribute(new QName2(m, "null", "m"), "true"); } else if (sValue != null) { writer.writeText(sValue); } writer.endElement(name); }
protected String writeEntry( XMLWriter2 writer, OEntity oe, List<OProperty<?>> entityProperties, List<OLink> entityLinks, String baseUri, String updated, EdmEntitySet ees, boolean isResponse) { String relid = null; String absid = null; if (isResponse) { relid = InternalUtil.getEntityRelId(oe); absid = baseUri + relid; writeElement(writer, "id", absid); } OAtomEntity oae = getAtomInfo(oe); writeElement(writer, "title", oae.getAtomEntityTitle(), "type", "text"); String summary = oae.getAtomEntitySummary(); if (summary != null) { writeElement(writer, "summary", summary, "type", "text"); } LocalDateTime updatedTime = oae.getAtomEntityUpdated(); if (updatedTime != null) { updated = InternalUtil.toString(updatedTime.toDateTime(DateTimeZone.UTC)); } writeElement(writer, "updated", updated); writer.startElement("author"); writeElement(writer, "name", oae.getAtomEntityAuthor()); writer.endElement("author"); if (isResponse) { writeElement( writer, "link", null, "rel", "edit", "title", ees.getType().getName(), "href", relid); } if (entityLinks != null) { if (isResponse) { // the producer has populated the link collection, we just what he gave us. for (OLink link : entityLinks) { String rel = related + link.getTitle(); String type = (link.isCollection()) ? atom_feed_content_type : atom_entry_content_type; String href = relid + "/" + link.getTitle(); if (link.isInline()) { writer.startElement("link"); writer.writeAttribute("rel", rel); writer.writeAttribute("type", type); writer.writeAttribute("title", link.getTitle()); writer.writeAttribute("href", href); // write the inlined entities inside the link element writeLinkInline(writer, link, href, baseUri, updated, isResponse); writer.endElement("link"); } else { // deferred link. writeElement( writer, "link", null, "rel", rel, "type", type, "title", link.getTitle(), "href", href); } } } else { // for requests we include only the provided links // Note: It seems that OLinks for responses are only built using the // title and OLinks for requests have the additional info in them // alread. I'm leaving that inconsistency in place for now but this // else and its preceding if could probably be unified. for (OLink olink : entityLinks) { String type = olink.isCollection() ? atom_feed_content_type : atom_entry_content_type; writer.startElement("link"); writer.writeAttribute("rel", olink.getRelation()); writer.writeAttribute("type", type); writer.writeAttribute("title", olink.getTitle()); writer.writeAttribute("href", olink.getHref()); if (olink.isInline()) { // write the inlined entities inside the link element writeLinkInline(writer, olink, olink.getHref(), baseUri, updated, isResponse); } writer.endElement("link"); } } } // else entityLinks null writeElement( writer, "category", null, // oe is null for creates "term", oe == null ? ees.getType().getFullyQualifiedTypeName() : oe.getEntityType().getFullyQualifiedTypeName(), "scheme", scheme); boolean hasStream = false; if (oe != null) { OAtomStreamEntity stream = oe.findExtension(OAtomStreamEntity.class); if (stream != null) { hasStream = true; writer.startElement("content"); writer.writeAttribute("type", stream.getAtomEntityType()); writer.writeAttribute("src", baseUri + stream.getAtomEntitySource()); writer.endElement("content"); } } if (!hasStream) { writer.startElement("content"); writer.writeAttribute("type", MediaType.APPLICATION_XML); } writer.startElement(new QName2(m, "properties", "m")); writeProperties(writer, entityProperties); writer.endElement("properties"); if (!hasStream) { writer.endElement("content"); } return absid; }
protected void writeEntry( StreamWriter writer, String entityName, Entity entity, Collection<Link> entityLinks, Map<Transition, RESTResource> embeddedResources, String baseUri, String absoluteId, String updated) { assert (entityName != null); // entity name could be different between entity resource and underlying entity // e.g., for Errors entity, entity resource would have the request entity name String entityMetadataName = entity != null ? entity.getName() : entityName; EntityMetadata entityMetadata = metadata.getEntityMetadata(entityMetadataName); String modelName = metadata.getModelName(); writer.writeId(absoluteId); OAtomEntity oae = getAtomInfo(entity); writer.writeTitle(oae.getAtomEntityTitle()); String summary = oae.getAtomEntitySummary(); if (!summary.isEmpty()) { writer.writeSummary(summary); } LocalDateTime updatedTime = oae.getAtomEntityUpdated(); if (updatedTime != null) { updated = InternalUtil.toString(updatedTime.toDateTime(DateTimeZone.UTC)); } writer.writeUpdated(updated); writer.writeAuthor(oae.getAtomEntityAuthor()); if (entityLinks != null) { for (Link link : entityLinks) { String type = (link.getTransition().getTarget() instanceof CollectionResourceState) ? atom_feed_content_type : atom_entry_content_type; String href = link.getRelativeHref(baseUri); String rel = link.getRel(); writer.startLink(href, rel); if ("self".equals(link.getRel())) { ResourceState target = link.getTransition().getTarget(); writer.writeAttribute("profile", target.getRel()); } if (!"self".equals(link.getRel()) && !"edit".equals(link.getRel())) { writer.writeAttribute("type", type); } writer.writeAttribute("title", link.getTitle()); if (embeddedResources != null && embeddedResources.get(link.getTransition()) != null) { String embeddedAbsoluteId = link.getHref(); writeLinkInline( writer, metadata, link, embeddedResources.get(link.getTransition()), link.getHref(), baseUri, embeddedAbsoluteId, updated); } String linkId = link.getLinkId(); if (linkId != null && linkId.length() > 0) { writer.writeAttribute("id", linkId); } writer.endLink(); } } writer.writeCategory(modelName + Metadata.MODEL_SUFFIX + "." + entityName, scheme); writer.flush(); writer.startContent(MediaType.APPLICATION_XML); writer.startElement(new QName(m, "properties", "m")); if (entity != null) { writeProperties(writer, entityMetadata, entity.getProperties(), modelName); } writer.endElement(); writer.endContent(); }
@SuppressWarnings("unchecked") protected void writeProperty(XMLWriter2 writer, OProperty<?> prop, boolean isDocumentElement) { String name = prop.getName(); EdmType type = prop.getType(); Object value = prop.getValue(); if (isDocumentElement) writer.startElement(new QName2(name), d); else writer.startElement(new QName2(d, name, "d")); String sValue = null; if (!type.isSimple()) { writer.writeAttribute(new QName2(m, "type", "m"), type.toTypeString()); // complex List<OProperty<?>> complexProperties = (List<OProperty<?>>) value; if (complexProperties != null) { writeProperties(writer, complexProperties); } } else { // simple if (type == EdmType.INT32) { writer.writeAttribute(new QName2(m, "type", "m"), type.toTypeString()); if (value != null) { sValue = value.toString(); } } else if (type == EdmType.INT16) { writer.writeAttribute(new QName2(m, "type", "m"), type.toTypeString()); if (value != null) { sValue = value.toString(); } } else if (type == EdmType.INT64) { writer.writeAttribute(new QName2(m, "type", "m"), type.toTypeString()); if (value != null) { sValue = value.toString(); } } else if (type == EdmType.BOOLEAN) { writer.writeAttribute(new QName2(m, "type", "m"), type.toTypeString()); if (value != null) { sValue = value.toString(); } } else if (type == EdmType.BYTE) { writer.writeAttribute(new QName2(m, "type", "m"), type.toTypeString()); if (value != null) { sValue = Hex.encodeHexString(new byte[] {(Byte) value}); } } else if (type == EdmType.DECIMAL) { writer.writeAttribute(new QName2(m, "type", "m"), type.toTypeString()); if (value != null) { sValue = value.toString(); } } else if (type == EdmType.SINGLE) { writer.writeAttribute(new QName2(m, "type", "m"), type.toTypeString()); if (value != null) { sValue = value.toString(); } } else if (type == EdmType.DOUBLE) { writer.writeAttribute(new QName2(m, "type", "m"), type.toTypeString()); if (value != null) { sValue = value.toString(); } } else if (type == EdmType.STRING) { if (value != null) { sValue = value.toString(); } } else if (type == EdmType.DATETIME) { writer.writeAttribute(new QName2(m, "type", "m"), type.toTypeString()); if (value != null) sValue = InternalUtil.formatDateTime((LocalDateTime) value); } else if (type == EdmType.BINARY) { writer.writeAttribute(new QName2(m, "type", "m"), type.toTypeString()); byte[] bValue = (byte[]) value; if (value != null) { sValue = Base64.encodeBase64String(bValue); } } else if (type == EdmType.GUID) { writer.writeAttribute(new QName2(m, "type", "m"), type.toTypeString()); if (value != null) { sValue = value.toString(); } } else if (type == EdmType.TIME) { writer.writeAttribute(new QName2(m, "type", "m"), type.toTypeString()); if (value != null) { sValue = InternalUtil.toString((LocalTime) value); } } else if (type == EdmType.DATETIMEOFFSET) { // Edm.DateTimeOffset '-'? yyyy '-' mm '-' dd 'T' hh ':' mm // ':' ss ('.' s+)? (zzzzzz)? writer.writeAttribute(new QName2(m, "type", "m"), type.toTypeString()); if (value != null) { sValue = InternalUtil.toString((DateTime) value); } } else { throw new UnsupportedOperationException("Implement " + type); } } if (value == null) { writer.writeAttribute(new QName2(m, "null", "m"), "true"); } else { writer.writeText(sValue); } writer.endElement(name); }
protected String writeEntry( XMLWriter2 writer, OEntity oe, List<OProperty<?>> entityProperties, List<OLink> entityLinks, String entitySetName, String baseUri, String updated, EdmEntitySet ees, boolean isResponse) { String relid = null; String absid = null; if (isResponse) { relid = InternalUtil.getEntityRelId(oe); absid = baseUri + relid; writeElement(writer, "id", absid); } writeElement(writer, "title", null, "type", "text"); writeElement(writer, "updated", updated); writer.startElement("author"); writeElement(writer, "name", null); writer.endElement("author"); if (isResponse) { writeElement(writer, "link", null, "rel", "edit", "title", entitySetName, "href", relid); } if (isResponse) { // for responses we need to include all links whether inlined or not for (EdmNavigationProperty np : ees.type.getAllNavigationProperties()) { if (!np.selected) { continue; } String otherEntity = np.name; String rel = related + otherEntity; String type = atom_feed_content_type; if (np.toRole.multiplicity != EdmMultiplicity.MANY) { type = atom_entry_content_type; } final String title = otherEntity; String href = relid + "/" + otherEntity; // check whether we have to write inlined entities OLink linkToInline = entityLinks != null ? Enumerable.create(entityLinks) .firstOrNull( new Predicate1<OLink>() { @Override public boolean apply(OLink input) { return title.equals(input.getTitle()); } }) : null; if (linkToInline == null) { writeElement( writer, "link", null, "rel", rel, "type", type, "title", title, "href", href); } else { writer.startElement("link"); writer.writeAttribute("rel", rel); writer.writeAttribute("type", type); writer.writeAttribute("title", title); writer.writeAttribute("href", href); // write the inlined entities inside the link element writeLinkInline(writer, linkToInline, href, baseUri, updated, isResponse); writer.endElement("link"); } } writeElement( writer, "category", null, "term", ees.type.getFQNamespaceName(), "scheme", scheme); } else { // for requests we include only the provided links if (entityLinks != null) { for (OLink olink : entityLinks) { String type = olink instanceof ORelatedEntitiesLink ? atom_feed_content_type : atom_entry_content_type; writer.startElement("link"); writer.writeAttribute("rel", olink.getRelation()); writer.writeAttribute("type", type); writer.writeAttribute("title", olink.getTitle()); writer.writeAttribute("href", olink.getHref()); if (olink instanceof ORelatedEntitiesLinkInline || olink instanceof ORelatedEntityLinkInline) { // write the inlined entities inside the link element writeLinkInline(writer, olink, olink.getHref(), baseUri, updated, isResponse); } writer.endElement("link"); } } } writer.startElement("content"); writer.writeAttribute("type", MediaType.APPLICATION_XML); writer.startElement(new QName2(m, "properties", "m")); writeProperties(writer, entityProperties); writer.endElement("properties"); writer.endElement("content"); return absid; }