private static void writeProperties(Iterable<EdmProperty> properties, XMLWriter2 writer) {
    for (EdmProperty prop : properties) {
      writer.startElement(new QName2("Property"));

      writer.writeAttribute("Name", prop.getName());
      writer.writeAttribute("Type", prop.getType().getFullyQualifiedTypeName());
      writer.writeAttribute("Nullable", Boolean.toString(prop.isNullable()));
      if (prop.getMaxLength() != null) {
        writer.writeAttribute("MaxLength", Integer.toString(prop.getMaxLength()));
      }
      if (!prop.getCollectionKind().equals(CollectionKind.NONE)) {
        writer.writeAttribute("CollectionKind", prop.getCollectionKind().toString());
      }
      if (prop.getDefaultValue() != null) {
        writer.writeAttribute("DefaultValue", prop.getDefaultValue());
      }
      if (prop.getPrecision() != null) {
        writer.writeAttribute("Precision", Integer.toString(prop.getPrecision()));
      }
      if (prop.getScale() != null) {
        writer.writeAttribute("Scale", Integer.toString(prop.getPrecision()));
      }
      writeAnnotationAttributes(prop, writer);
      writeAnnotationElements(prop, writer);
      writer.endElement("Property");
    }
  }
示例#2
0
 protected void writeElement(
     XMLWriter2 writer, String elementName, String elementText, String... attributes) {
   writer.startElement(elementName);
   for (int i = 0; i < attributes.length; i += 2) {
     writer.writeAttribute(attributes[i], attributes[i + 1]);
   }
   if (elementText != null) {
     writer.writeText(elementText);
   }
   writer.endElement(elementName);
 }
  protected void writeLinkInline(
      XMLWriter2 writer,
      OLink linkToInline,
      String href,
      String baseUri,
      String updated,
      boolean isResponse) {

    writer.startElement(new QName2(m, "inline", "m"));
    if (linkToInline instanceof ORelatedEntitiesLinkInline) {
      ORelatedEntitiesLinkInline relLink = ((ORelatedEntitiesLinkInline) linkToInline);
      List<OEntity> entities = relLink.getRelatedEntities();

      if (entities != null && !entities.isEmpty()) {
        writer.startElement(new QName2("feed"));
        writeElement(writer, "title", linkToInline.getTitle(), "type", "text");

        writeElement(writer, "id", baseUri + href);
        writeElement(writer, "updated", updated);
        writeElement(
            writer, "link", null, "rel", "self", "title", linkToInline.getTitle(), "href", href);

        for (OEntity entity : ((ORelatedEntitiesLinkInline) linkToInline).getRelatedEntities()) {
          writer.startElement("entry");
          writeEntry(
              writer,
              entity,
              entity.getProperties(),
              entity.getLinks(),
              entity.getEntitySet().name,
              baseUri,
              updated,
              entity.getEntitySet(),
              isResponse);

          writer.endElement("entry");
        }
        writer.endElement("feed");
      }
    } else if (linkToInline instanceof ORelatedEntityLinkInline) {
      OEntity entity = ((ORelatedEntityLinkInline) linkToInline).getRelatedEntity();
      if (entity != null) {
        writer.startElement("entry");
        writeEntry(
            writer,
            entity,
            entity.getProperties(),
            entity.getLinks(),
            entity.getEntitySet().name,
            baseUri,
            updated,
            entity.getEntitySet(),
            isResponse);

        writer.endElement("entry");
      }
    } else throw new RuntimeException("Unknown OLink type " + linkToInline.getClass());
    writer.endElement("inline");
  }
 /** Extensions to CSDL like Annotations appear in an application specific set of namespaces. */
 private static void writeExtensionNamespaces(EdmDataServices services, XMLWriter2 writer) {
   if (null != services.getNamespaces()) {
     for (PrefixedNamespace ns : services.getNamespaces()) {
       writer.writeNamespace(ns.getPrefix(), ns.getUri());
     }
   }
 }
 private static void writeAnnotationAttributes(EdmItem item, XMLWriter2 writer) {
   if (null != item.getAnnotations()) {
     for (NamespacedAnnotation<?> a : item.getAnnotations()) {
       if (a instanceof EdmAnnotationAttribute) {
         writer.writeAttribute(
             new QName2(a.getNamespace().getUri(), a.getName(), a.getNamespace().getPrefix()),
             a.getValue() == null ? "" : a.getValue().toString());
       }
     }
   }
 }
 private static void writeDocumentation(EdmItem item, XMLWriter2 writer) {
   EdmDocumentation doc = item.getDocumentation();
   if (null != doc && (null != doc.getSummary() || null != doc.getLongDescription())) {
     QName2 d = new QName2(edm, "Documentation");
     writer.startElement(d);
     {
       if (null != doc.getSummary()) {
         QName2 s = new QName2(edm, "Summary");
         writer.startElement(s);
         writer.writeText(doc.getSummary());
         writer.endElement(s.getLocalPart());
       }
       if (null != doc.getLongDescription()) {
         QName2 s = new QName2(edm, "LongDescription");
         writer.startElement(s);
         writer.writeText(doc.getLongDescription());
         writer.endElement(s.getLocalPart());
       }
     }
     writer.endElement(d.getLocalPart());
   }
 }
示例#7
0
  @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);
  }
示例#8
0
  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;
  }
  public static void write(EdmDataServices services, Writer w) {

    XMLWriter2 writer = XMLFactoryProvider2.getInstance().newXMLWriterFactory2().createXMLWriter(w);
    writer.startDocument();

    writer.startElement(new QName2(edmx, "Edmx", "edmx"));
    writer.writeAttribute("Version", "1.0");
    writer.writeNamespace("edmx", edmx);
    writer.writeNamespace("d", d);
    writer.writeNamespace("m", m);
    writeExtensionNamespaces(services, writer);

    writer.startElement(new QName2(edmx, "DataServices", "edmx"));
    writer.writeAttribute(new QName2(m, "DataServiceVersion", "m"), "1.0");

    // Schema
    for (EdmSchema schema : services.getSchemas()) {

      writer.startElement(new QName2("Schema"), edm);
      writer.writeAttribute("Namespace", schema.getNamespace());
      writeAnnotationAttributes(schema, writer);
      writeDocumentation(schema, writer);

      // ComplexType
      for (EdmComplexType ect : schema.getComplexTypes()) {
        writer.startElement(new QName2("ComplexType"));

        writer.writeAttribute("Name", ect.getName());
        if (null != ect.getIsAbstract()) {
          writer.writeAttribute("Abstract", ect.getIsAbstract().toString());
        }
        writeAnnotationAttributes(ect, writer);
        writeDocumentation(ect, writer);

        writeProperties(ect.getProperties(), writer);
        writeAnnotationElements(ect, writer);
        writer.endElement("ComplexType");
      }
      // EntityType
      for (EdmEntityType eet : schema.getEntityTypes()) {
        writer.startElement(new QName2("EntityType"));

        writer.writeAttribute("Name", eet.getName());
        if (null != eet.getIsAbstract()) {
          writer.writeAttribute("Abstract", eet.getIsAbstract().toString());
        }

        if (Boolean.TRUE.equals(eet.getHasStream())) {
          writer.writeAttribute(new QName2(m, "HasStream", "m"), "true");
        }

        // keys only on base types
        if (eet.isRootType()) {
          writeAnnotationAttributes(eet, writer);
          writeDocumentation(eet, writer);
          writer.startElement(new QName2("Key"));
          for (String key : eet.getKeys()) {
            writer.startElement(new QName2("PropertyRef"));
            writer.writeAttribute("Name", key);
            writer.endElement("PropertyRef");
          }

          writer.endElement("Key");
        } else {
          writer.writeAttribute("BaseType", eet.getBaseType().getFullyQualifiedTypeName());
          writeAnnotationAttributes(eet, writer);
          writeDocumentation(eet, writer);
        }

        writeProperties(eet.getDeclaredProperties(), writer);

        for (EdmNavigationProperty np : eet.getDeclaredNavigationProperties()) {

          writer.startElement(new QName2("NavigationProperty"));
          writer.writeAttribute("Name", np.getName());
          writer.writeAttribute("Relationship", np.getRelationship().getFQNamespaceName());
          writer.writeAttribute("FromRole", np.getFromRole().getRole());
          writer.writeAttribute("ToRole", np.getToRole().getRole());
          writeAnnotationAttributes(np, writer);
          writeDocumentation(np, writer);
          writeAnnotationElements(np, writer);
          writer.endElement("NavigationProperty");
        }

        writeAnnotationElements(eet, writer);
        writer.endElement("EntityType");
      }

      // Association
      for (EdmAssociation assoc : schema.getAssociations()) {
        writer.startElement(new QName2("Association"));

        writer.writeAttribute("Name", assoc.getName());
        writeAnnotationAttributes(assoc, writer);
        writeDocumentation(assoc, writer);

        writer.startElement(new QName2("End"));
        writer.writeAttribute("Role", assoc.getEnd1().getRole());
        writer.writeAttribute("Type", assoc.getEnd1().getType().getFullyQualifiedTypeName());
        writer.writeAttribute("Multiplicity", assoc.getEnd1().getMultiplicity().getSymbolString());
        writer.endElement("End");

        writer.startElement(new QName2("End"));
        writer.writeAttribute("Role", assoc.getEnd2().getRole());
        writer.writeAttribute("Type", assoc.getEnd2().getType().getFullyQualifiedTypeName());
        writer.writeAttribute("Multiplicity", assoc.getEnd2().getMultiplicity().getSymbolString());
        writer.endElement("End");

        writeAnnotationElements(assoc, writer);
        writer.endElement("Association");
      }

      // EntityContainer
      for (EdmEntityContainer container : schema.getEntityContainers()) {
        writer.startElement(new QName2("EntityContainer"));

        writer.writeAttribute("Name", container.getName());
        writer.writeAttribute(
            new QName2(m, "IsDefaultEntityContainer", "m"),
            Boolean.toString(container.isDefault()));
        writeAnnotationAttributes(container, writer);
        writeDocumentation(container, writer);

        for (EdmEntitySet ees : container.getEntitySets()) {
          writer.startElement(new QName2("EntitySet"));
          writer.writeAttribute("Name", ees.getName());
          writer.writeAttribute("EntityType", ees.getType().getFullyQualifiedTypeName());
          writeAnnotationAttributes(ees, writer);
          writeDocumentation(ees, writer);
          writeAnnotationElements(ees, writer);
          writer.endElement("EntitySet");
        }

        for (EdmFunctionImport fi : container.getFunctionImports()) {
          writer.startElement(new QName2("FunctionImport"));
          writer.writeAttribute("Name", fi.getName());
          if (null != fi.getEntitySet()) {
            writer.writeAttribute("EntitySet", fi.getEntitySet().getName());
          }
          if (fi.getReturnType() != null) {
            // TODO: how to differentiate inline ReturnType vs embedded ReturnType?
            writer.writeAttribute("ReturnType", fi.getReturnType().getFullyQualifiedTypeName());
          }
          writer.writeAttribute(new QName2(m, "HttpMethod", "m"), fi.getHttpMethod());
          writeAnnotationAttributes(fi, writer);
          writeDocumentation(fi, writer);

          for (EdmFunctionParameter param : fi.getParameters()) {
            writer.startElement(new QName2("Parameter"));
            writer.writeAttribute("Name", param.getName());
            writer.writeAttribute("Type", param.getType().getFullyQualifiedTypeName());
            if (param.getMode() != null) writer.writeAttribute("Mode", param.getMode().toString());
            writeAnnotationAttributes(param, writer);
            writeDocumentation(param, writer);
            writeAnnotationElements(param, writer);
            writer.endElement("Parameter");
          }
          writeAnnotationElements(fi, writer);
          writer.endElement("FunctionImport");
        }

        for (EdmAssociationSet eas : container.getAssociationSets()) {
          writer.startElement(new QName2("AssociationSet"));
          writer.writeAttribute("Name", eas.getName());
          writer.writeAttribute("Association", eas.getAssociation().getFQNamespaceName());
          writeAnnotationAttributes(eas, writer);
          writeDocumentation(eas, writer);

          writer.startElement(new QName2("End"));
          writer.writeAttribute("Role", eas.getEnd1().getRole().getRole());
          writer.writeAttribute("EntitySet", eas.getEnd1().getEntitySet().getName());
          writer.endElement("End");

          writer.startElement(new QName2("End"));
          writer.writeAttribute("Role", eas.getEnd2().getRole().getRole());
          writer.writeAttribute("EntitySet", eas.getEnd2().getEntitySet().getName());
          writer.endElement("End");

          writeAnnotationElements(eas, writer);
          writer.endElement("AssociationSet");
        }

        writeAnnotationElements(container, writer);
        writer.endElement("EntityContainer");
      }

      writeAnnotationElements(schema, writer);
      writer.endElement("Schema");
    }

    writer.endDocument();
  }
示例#10
0
  @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);
  }
示例#11
0
  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;
  }