/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 ******************************************************************************/
package org.apache.olingo.odata2.client.core.ep.serializer;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URISyntaxException;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.Map.Entry;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

import org.apache.olingo.odata2.api.edm.Edm;
import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings;
import org.apache.olingo.odata2.api.edm.EdmEntitySet;
import org.apache.olingo.odata2.api.edm.EdmException;
import org.apache.olingo.odata2.api.edm.EdmFacets;
import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
import org.apache.olingo.odata2.api.edm.EdmMapping;
import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
import org.apache.olingo.odata2.api.edm.EdmSimpleType;
import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
import org.apache.olingo.odata2.api.edm.EdmTargetPath;
import org.apache.olingo.odata2.api.ep.EntityProviderException;
import org.apache.olingo.odata2.client.api.ep.Entity;
import org.apache.olingo.odata2.client.api.ep.EntityCollection;
import org.apache.olingo.odata2.client.api.ep.EntityCollectionSerializerProperties;
import org.apache.olingo.odata2.client.api.ep.EntitySerializerProperties;
import org.apache.olingo.odata2.core.commons.ContentType;
import org.apache.olingo.odata2.core.commons.Encoder;
import org.apache.olingo.odata2.core.edm.EdmDateTimeOffset;
import org.apache.olingo.odata2.core.ep.EntityProviderProducerException;
import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
import org.apache.olingo.odata2.core.ep.util.FormatXml;

/**
 * Serializes an ATOM entry.
 * 
 */
public class AtomEntryEntitySerializer {
  private final EntitySerializerProperties properties;
  private static final String VALUE = "/$value";

  /**
   * 
   * @param properties
   */
  public AtomEntryEntitySerializer(final EntitySerializerProperties properties) {
    this.properties = properties == null ? EntitySerializerProperties.serviceRoot(null).build() : properties;
  }

  /**
   * This serializes the xml payload entry
   * @param writer
   * @param eia
   * @param data
   * @param isRootElement
   * @param isFeedPart
   * @throws EntityProviderException
   */
  public void append(final XMLStreamWriter writer, final EntityInfoAggregator eia, final Entity data,
      final boolean isRootElement, final boolean isFeedPart) throws EntityProviderException {

    try {
      if (properties.getServiceRoot() == null) {
        throw new EntityProviderProducerException(EntityProviderException.MANDATORY_WRITE_PROPERTY);
      }
      writer.writeStartElement(FormatXml.ATOM_ENTRY);

      if (isRootElement) {
        writer.writeDefaultNamespace(Edm.NAMESPACE_ATOM_2005);
        writer.writeNamespace(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08);
        writer.writeNamespace(Edm.PREFIX_D, Edm.NAMESPACE_D_2007_08);
      }
      if (!isFeedPart) {
        writer.writeAttribute(Edm.PREFIX_XML, Edm.NAMESPACE_XML_1998, FormatXml.XML_BASE, properties.getServiceRoot()
            .toASCIIString());
      }

      String selfLink = null;
      if (properties.isIncludeMetadata()) {
        // write all atom infos (mandatory and optional)
        selfLink = createSelfLink(eia, data.getProperties(), null, properties.isKeyAutoGenerated(), false);
        appendAtomMandatoryParts(writer, eia, data.getProperties());
        appendAtomOptionalParts(writer, eia, data.getProperties());
        appendAtomEditLink(writer, eia, selfLink);
        if (eia.getEntityType().hasStream()) {
          appendAtomContentLink(writer, eia, data.getProperties(), selfLink);
        }
      }

      appendNavigationLinks(writer, eia, data);
      appendCustomProperties(writer, eia, data.getProperties());

      if (eia.getEntityType().hasStream()) {
        if (properties.isIncludeMetadata()) {
          appendAtomContentPart(writer, eia, data.getProperties(), selfLink);
        }
        appendProperties(writer, eia, data.getProperties());
      } else {
        writer.writeStartElement(FormatXml.ATOM_CONTENT);
        writer.writeAttribute(FormatXml.ATOM_TYPE, ContentType.APPLICATION_XML.toString());
        appendProperties(writer, eia, data.getProperties());
        writer.writeEndElement();
      }
      writer.writeEndElement();
      writer.flush();

    } catch (XMLStreamException e) {
      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
    } catch (EdmException e) {
      throw new EntityProviderProducerException(e.getMessageReference(), e);
    } catch (URISyntaxException e) {
      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
    }
  }

  @SuppressWarnings("unchecked")
  private void appendNavigationLinks(final XMLStreamWriter writer, //NOSONAR
      final EntityInfoAggregator eia,
      final Entity data) 
      throws EntityProviderException, EdmException, URISyntaxException, XMLStreamException { 

    for (Entry<String, Object> entry : data.getNavigations().entrySet()) {
      final EntityInfoAggregator targetEntityInfo = EntityInfoAggregator.create(
          eia.getEntitySet().getRelatedEntitySet(
              (EdmNavigationProperty) eia.getEntityType().getProperty(entry.getKey())));
      final boolean isFeed =
          (eia.getNavigationPropertyInfo(entry.getKey()).getMultiplicity() == EdmMultiplicity.MANY);
      if (entry.getValue() == null) {
        throw new EntityProviderProducerException(EntityProviderProducerException.NULL_VALUE);
      } else if (entry.getValue() instanceof Map) {
        Map<String, Object> navigationKeyMap = (Map<String, Object>) entry.getValue();
        if (navigationKeyMap != null && !navigationKeyMap.isEmpty()) {
          appendAtomNavigationLink(writer, createSelfLink(targetEntityInfo, navigationKeyMap, null, 
              properties.isKeyAutoGenerated(), false), entry.getKey(), isFeed);
          writer.writeEndElement();
        }
      } else if (entry.getValue() instanceof Entity) {
        Entity navigationEntity = (Entity) entry.getValue();
        Map<String, Object> navigationKeyMap = navigationEntity.getProperties();
        if (navigationKeyMap != null && !navigationKeyMap.isEmpty()) {
          String navigationPropertyName = entry.getKey();
          String selfLink = createSelfLink(eia, data.getProperties(), navigationPropertyName,
              properties.isKeyAutoGenerated(), false);
          appendNavigationLink(writer, selfLink, navigationPropertyName);

          writer.writeAttribute(FormatXml.ATOM_TYPE, ContentType.APPLICATION_ATOM_XML_ENTRY.toString());
          appendInlineEntry(writer, navigationPropertyName, eia, data);
          writer.writeEndElement();

        }
      } else if (entry.getValue() instanceof EntityCollection) {
        String navigationPropertyName = entry.getKey();
        String selfLink = createSelfLink(eia, data.getProperties(), navigationPropertyName, 
            properties.isKeyAutoGenerated(), false);
        if (!((EntityCollection) entry.getValue()).getEntities().isEmpty()) {
          appendNavigationLink(writer, selfLink, navigationPropertyName);

          writer.writeAttribute(FormatXml.ATOM_TYPE, ContentType.APPLICATION_ATOM_XML_FEED.toString());
          appendInlineFeed(writer, navigationPropertyName, eia, data);
          writer.writeEndElement();
        }

      } else{
        throw new EntityProviderProducerException(EntityProviderProducerException.INCORRECT_NAVIGATION_TYPE);
        
      }
    }
  }

  private void appendNavigationLink(XMLStreamWriter writer, String selfLink, String navigationPropertyName)
      throws XMLStreamException {

    writer.writeStartElement(FormatXml.ATOM_LINK);
    writer.writeAttribute(FormatXml.ATOM_HREF, selfLink);
    writer.writeAttribute(FormatXml.ATOM_REL, Edm.NAMESPACE_REL_2007_08 + navigationPropertyName);
    writer.writeAttribute(FormatXml.ATOM_TITLE, navigationPropertyName);
  }

  private void appendCustomProperties(final XMLStreamWriter writer, final EntityInfoAggregator eia,
      final Map<String, Object> data) throws EntityProviderException {
    List<String> noneSyndicationTargetPaths = eia.getNoneSyndicationTargetPathNames();
    for (String tpName : noneSyndicationTargetPaths) {
      EntityPropertyInfo info = eia.getTargetPathInfo(tpName);
      final String name = info.getName();
      XmlPropertyEntitySerializer aps = new XmlPropertyEntitySerializer(properties);
      aps.appendCustomProperty(writer, name, info, data.get(name));
    }
  }

  private void appendAtomNavigationLink(final XMLStreamWriter writer, final String target,
      final String navigationPropertyName, final boolean isFeed) 
          throws EntityProviderException, EdmException, URISyntaxException { //NOSONAR
    try {
      writer.writeStartElement(FormatXml.ATOM_LINK);
      writer.writeAttribute(FormatXml.ATOM_HREF, target);
      writer.writeAttribute(FormatXml.ATOM_REL, Edm.NAMESPACE_REL_2007_08 + navigationPropertyName);
      writer.writeAttribute(FormatXml.ATOM_TITLE, navigationPropertyName);
      if (isFeed) {
        writer.writeAttribute(FormatXml.ATOM_TYPE, ContentType.APPLICATION_ATOM_XML_FEED.toString());
      } else {
        writer.writeAttribute(FormatXml.ATOM_TYPE, ContentType.APPLICATION_ATOM_XML_ENTRY.toString());
      }
    } catch (XMLStreamException e) {
      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
    }
  }

  private void appendInlineFeed(final XMLStreamWriter writer, final String navigationPropertyName,
      final EntityInfoAggregator eia, final Entity data)
      throws EntityProviderException, XMLStreamException, EdmException {

    if (eia.getNavigationPropertyNames().contains(navigationPropertyName) && 
        data != null && data.getNavigations().containsKey(navigationPropertyName)) {

        EdmNavigationProperty navProp = (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName);

        if (navProp == null) {
          throw new EntityProviderProducerException(EntityProviderException.EXPANDNOTSUPPORTED);
        }
        EntityCollection inlineData;
        inlineData = (EntityCollection) data.getNavigation(navigationPropertyName);
        if (inlineData == null) {
          inlineData = new EntityCollection();
        }

        if (inlineData.getEntities().isEmpty()) {
          return;
        }
        writer.writeStartElement(Edm.NAMESPACE_M_2007_08, FormatXml.M_INLINE);

        EntityCollectionSerializerProperties inlineProperties = inlineData.getCollectionProperties() == null
            ? EntityCollectionSerializerProperties.serviceRoot(data.getWriteProperties().getServiceRoot()).build()
            : inlineData.getCollectionProperties();
        EdmEntitySet inlineEntitySet = eia.getEntitySet().getRelatedEntitySet(navProp);
        AtomFeedSerializer inlineFeedProducer = new AtomFeedSerializer(inlineProperties);
        inlineData.setCollectionProperties(inlineProperties);
        EntityInfoAggregator inlineEia =
            EntityInfoAggregator.create(inlineEntitySet, null);
        inlineFeedProducer.append(writer, inlineEia, inlineData, true);

        writer.writeEndElement();

    }
  }

  private void appendInlineEntry(final XMLStreamWriter writer, final String navigationPropertyName,
      final EntityInfoAggregator eia, final Entity data) throws EntityProviderException,
      XMLStreamException, EdmException {

    if (data.getNavigations() != null && data.getNavigations().containsKey(navigationPropertyName)) {

      EdmNavigationProperty navProp = (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName);

      Entity inlineData = (Entity) data.getNavigation(navigationPropertyName);

      if ((inlineData == null) || inlineData.getProperties().size() == 0) {
        return;
      }

      writer.writeStartElement(Edm.NAMESPACE_M_2007_08, FormatXml.M_INLINE);
      if (inlineData != null && !(inlineData.getProperties().isEmpty())) {
        inlineData.setWriteProperties(inlineData.getWriteProperties() == null ? data.getWriteProperties() : inlineData
            .getWriteProperties());
        EdmEntitySet inlineEntitySet = eia.getEntitySet().getRelatedEntitySet(navProp);
        AtomEntryEntitySerializer inlineProducer = new AtomEntryEntitySerializer(inlineData.getWriteProperties());
        EntityInfoAggregator inlineEia =
            EntityInfoAggregator.create(inlineEntitySet, null);
        inlineProducer.append(writer, inlineEia, inlineData, false, false);
      }

      writer.writeEndElement();
    }
  }


  private void appendAtomEditLink(final XMLStreamWriter writer, final EntityInfoAggregator eia,
      final String selfLink) throws EntityProviderException {
    try {
      writer.writeStartElement(FormatXml.ATOM_LINK);
      writer.writeAttribute(FormatXml.ATOM_HREF, selfLink);
      writer.writeAttribute(FormatXml.ATOM_REL, Edm.LINK_REL_EDIT);
      writer.writeAttribute(FormatXml.ATOM_TITLE, eia.getEntityType().getName());
      writer.writeEndElement();
    } catch (XMLStreamException e) {
      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
    } catch (EdmException e) {
      throw new EntityProviderProducerException(e.getMessageReference(), e);
    }
  }

  private void appendAtomContentLink(final XMLStreamWriter writer, final EntityInfoAggregator eia,
      final Map<String, Object> data, final String selfLink) throws EntityProviderException, EdmException {
    try {
      String mediaResourceMimeType = null;
      EdmMapping entityTypeMapping = eia.getEntityType().getMapping();
      if (entityTypeMapping != null) {
        String mediaResourceMimeTypeKey = entityTypeMapping.getMediaResourceMimeTypeKey();
        if (mediaResourceMimeTypeKey != null) {
          mediaResourceMimeType = (String) data.get(mediaResourceMimeTypeKey);
        }
      }
      if (mediaResourceMimeType == null) {
        mediaResourceMimeType = ContentType.APPLICATION_OCTET_STREAM.toString();
      }

      writer.writeStartElement(FormatXml.ATOM_LINK);
      writer.writeAttribute(FormatXml.ATOM_HREF, selfLink + VALUE);
      writer.writeAttribute(FormatXml.ATOM_REL, Edm.LINK_REL_EDIT_MEDIA);
      writer.writeAttribute(FormatXml.ATOM_TYPE, mediaResourceMimeType);
      writer.writeEndElement();
    } catch (XMLStreamException e) {
      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
    }
  }

  private void appendAtomContentPart(final XMLStreamWriter writer, final EntityInfoAggregator eia,
      final Map<String, Object> data, final String selfLink) throws EntityProviderException, EdmException {
    try {

      EdmMapping entityTypeMapping = eia.getEntityType().getMapping();
      String self = null;
      String mediaResourceMimeType = null;

      if (entityTypeMapping != null) {
        String mediaResourceSourceKey = entityTypeMapping.getMediaResourceSourceKey();
        if (mediaResourceSourceKey != null) {
          self = (String) data.get(mediaResourceSourceKey);
        }
        if (self == null) {
          self = selfLink + VALUE;
        }
        String mediaResourceMimeTypeKey = entityTypeMapping.getMediaResourceMimeTypeKey();
        if (mediaResourceMimeTypeKey != null) {
          mediaResourceMimeType = (String) data.get(mediaResourceMimeTypeKey);
        }
        if (mediaResourceMimeType == null) {
          mediaResourceMimeType = ContentType.APPLICATION_OCTET_STREAM.toString();
        }
      } else {
        self = selfLink + VALUE;
        mediaResourceMimeType = ContentType.APPLICATION_OCTET_STREAM.toString();
      }

      writer.writeStartElement(FormatXml.ATOM_CONTENT);
      writer.writeAttribute(FormatXml.ATOM_TYPE, mediaResourceMimeType);
      writer.writeAttribute(FormatXml.ATOM_SRC, self);
      writer.writeEndElement();
    } catch (XMLStreamException e) {
      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
    }
  }

  private void appendAtomMandatoryParts(final XMLStreamWriter writer, final EntityInfoAggregator eia,
      final Map<String, Object> data) throws EntityProviderException {
    try {
      writer.writeStartElement(FormatXml.ATOM_ID);
      String idlocation = properties.getServiceRoot().toASCIIString() + createSelfLink(
          eia, data, null, properties.isKeyAutoGenerated(), true);;
      writer.writeCharacters(idlocation);
      writer.writeEndElement();

      writer.writeStartElement(FormatXml.ATOM_TITLE);
      writer.writeAttribute(FormatXml.ATOM_TYPE, FormatXml.ATOM_TEXT);
      EntityPropertyInfo titleInfo = eia.getTargetPathInfo(EdmTargetPath.SYNDICATION_TITLE);
      if (titleInfo != null) {
        EdmSimpleType st = (EdmSimpleType) titleInfo.getType();
        Object object = data.get(titleInfo.getName());
        String title = null;
        try { //NOSONAR
          title = st.valueToString(object, EdmLiteralKind.DEFAULT, titleInfo.getFacets());
        } catch (EdmSimpleTypeException e) {
          throw new EntityProviderProducerException(EdmSimpleTypeException.getMessageReference(
              e.getMessageReference()).updateContent(e.getMessageReference().getContent(), titleInfo.getName()), e);
        }
        if (title != null) {
          writer.writeCharacters(title);
        }
      } else {
        writer.writeCharacters(eia.getEntitySetName());
      }
      writer.writeEndElement();

      writer.writeStartElement(FormatXml.ATOM_UPDATED);

      writer.writeCharacters(getUpdatedString(eia, data));

      writer.writeEndElement();
    } catch (XMLStreamException e) {
      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
    } catch (EdmSimpleTypeException e) {
      throw new EntityProviderProducerException(e.getMessageReference(), e);
    }
  }

  String getUpdatedString(final EntityInfoAggregator eia, final Map<String, Object> data)
      throws EdmSimpleTypeException, EntityProviderProducerException {
    Object updateDate = null;
    EdmFacets updateFacets = null;
    EntityPropertyInfo updatedInfo = eia.getTargetPathInfo(EdmTargetPath.SYNDICATION_UPDATED);
    if (updatedInfo != null) {
      updateDate = data.get(updatedInfo.getName());
      if (updateDate != null) {
        updateFacets = updatedInfo.getFacets();
      }
    }
    if (updateDate == null) {
      updateDate = new Date();
    }
    try {
      return EdmDateTimeOffset.getInstance().valueToString(updateDate, EdmLiteralKind.DEFAULT, updateFacets);
    } catch (final EdmSimpleTypeException e) {
      throw new EntityProviderProducerException(
          EdmSimpleTypeException.getMessageReference(e.getMessageReference()).
          updateContent(e.getMessageReference().getContent(),
              updatedInfo == null ? null : updatedInfo.getName()), e);
    }
  }

  private String getTargetPathValue(final EntityInfoAggregator eia, final String targetPath,
      final Map<String, Object> data) throws EntityProviderException {
    EntityPropertyInfo info = null;
    try {
      info = eia.getTargetPathInfo(targetPath);
      if (info != null) {
        EdmSimpleType type = (EdmSimpleType) info.getType();
        Object value = data.get(info.getName());
        return type.valueToString(value, EdmLiteralKind.DEFAULT, info.getFacets());
      }
      return null;
    } catch (final EdmSimpleTypeException e) {
      throw new EntityProviderProducerException(
          EdmSimpleTypeException.getMessageReference(e.getMessageReference()).
          updateContent(e.getMessageReference().getContent(), info.getName()), e);
    }
  }

  private void appendAtomOptionalParts(final XMLStreamWriter writer, final EntityInfoAggregator eia,
      final Map<String, Object> data) throws EntityProviderException {
    try {
      String authorEmail = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_AUTHOREMAIL, data);
      String authorName = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_AUTHORNAME, data);
      String authorUri = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_AUTHORURI, data);
      if (authorEmail != null || authorName != null || authorUri != null) {
        writer.writeStartElement(FormatXml.ATOM_AUTHOR);
        appendAtomOptionalPart(writer, FormatXml.ATOM_AUTHOR_NAME, authorName, false);
        appendAtomOptionalPart(writer, FormatXml.ATOM_AUTHOR_EMAIL, authorEmail, false);
        appendAtomOptionalPart(writer, FormatXml.ATOM_AUTHOR_URI, authorUri, false);
        writer.writeEndElement();
      }

      String summary = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_SUMMARY, data);
      appendAtomOptionalPart(writer, FormatXml.ATOM_SUMMARY, summary, true);

      String contributorName = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_CONTRIBUTORNAME, data);
      String contributorEmail = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_CONTRIBUTOREMAIL, data);
      String contributorUri = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_CONTRIBUTORURI, data);
      if (contributorEmail != null || contributorName != null || contributorUri != null) {
        writer.writeStartElement(FormatXml.ATOM_CONTRIBUTOR);
        appendAtomOptionalPart(writer, FormatXml.ATOM_CONTRIBUTOR_NAME, contributorName, false);
        appendAtomOptionalPart(writer, FormatXml.ATOM_CONTRIBUTOR_EMAIL, contributorEmail, false);
        appendAtomOptionalPart(writer, FormatXml.ATOM_CONTRIBUTOR_URI, contributorUri, false);
        writer.writeEndElement();
      }

      String rights = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_RIGHTS, data);
      appendAtomOptionalPart(writer, FormatXml.ATOM_RIGHTS, rights, true);
      String published = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_PUBLISHED, data);
      appendAtomOptionalPart(writer, FormatXml.ATOM_PUBLISHED, published, false);

      String term = eia.getEntityType().getNamespace() + Edm.DELIMITER + eia.getEntityType().getName();
      writer.writeStartElement(FormatXml.ATOM_CATEGORY);
      writer.writeAttribute(FormatXml.ATOM_CATEGORY_TERM, term);
      writer.writeAttribute(FormatXml.ATOM_CATEGORY_SCHEME, Edm.NAMESPACE_SCHEME_2007_08);
      writer.writeEndElement();
    } catch (XMLStreamException e) {
      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
    } catch (EdmException e) {
      throw new EntityProviderProducerException(e.getMessageReference(), e);
    }
  }

  private void appendAtomOptionalPart(final XMLStreamWriter writer, final String name, final String value,
      final boolean writeType) throws EntityProviderException {
    try {
      if (value != null) {
        writer.writeStartElement(name);
        if (writeType) {
          writer.writeAttribute(FormatXml.ATOM_TYPE, FormatXml.ATOM_TEXT);
        }
        writer.writeCharacters(value);
        writer.writeEndElement();
      }
    } catch (XMLStreamException e) {
      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
    }
  }

  static String createSelfLink(final EntityInfoAggregator eia, final Map<String, Object> data, final String extension, 
      boolean isKeyAutoGenerated, boolean isIdTag)
      throws EntityProviderException {
    StringBuilder sb = new StringBuilder();
    if (!eia.isDefaultEntityContainer()) {
      sb.append(Encoder.encode(eia.getEntityContainerName())).append(Edm.DELIMITER);
    }
    sb.append(Encoder.encode(eia.getEntitySetName()));

    String keyValue = createEntryKey(eia, data, isKeyAutoGenerated, isIdTag);
    if (isIdTag && isKeyAutoGenerated && "".equals(keyValue) && keyValue.length() == 0) {
      sb.append(extension == null ? "" : ("/" + extension));
    } else {
      sb.append("(").append(keyValue).append(")").
      append(extension == null ? "" : ("/" + extension));
    }
    return sb.toString();
  }

  private static String createEntryKey(final EntityInfoAggregator entityInfo, final Map<String, Object> data, 
      boolean isKeyAutoGenerated, boolean isIdTag)
      throws EntityProviderException {
    final List<EntityPropertyInfo> keyPropertyInfos = entityInfo.getKeyPropertyInfos();

    StringBuilder keys = new StringBuilder();
    for (final EntityPropertyInfo keyPropertyInfo : keyPropertyInfos) {
      if (keys.length() > 0) {
        keys.append(',');
      }

      final String name = keyPropertyInfo.getName();
      if (keyPropertyInfos.size() > 1) {
        keys.append(Encoder.encode(name)).append('=');
      }

      final EdmSimpleType type = (EdmSimpleType) keyPropertyInfo.getType();
      try {
        String keyValue = null;
        if (isKeyAutoGenerated && data.get(name) == null) {
          if (isIdTag) {
            keyValue = "";
          } else {
            Object value = fetchDefaultValue(type.getDefaultType());
            keyValue = Encoder.encode(type.valueToString(value, EdmLiteralKind.URI,
                keyPropertyInfo.getFacets()));
          }
        } else {
          keyValue = Encoder.encode(type.valueToString(data.get(name), EdmLiteralKind.URI,
              keyPropertyInfo.getFacets()));
        }
        keys.append(keyValue);
      } catch (final EdmSimpleTypeException e) {
        throw new EntityProviderProducerException(
            EdmSimpleTypeException.getMessageReference(e.getMessageReference()).
            updateContent(e.getMessageReference().getContent(), name), e);
      }
    }

    return keys.toString();
  }

  private static Object fetchDefaultValue(Class<?> edmType) throws EntityProviderProducerException {
    if (edmType == boolean.class || edmType == Boolean.class) {
        return false;
      } else if (edmType == String.class) {
        return "A";
      } else if (edmType == byte.class || edmType == Byte.class) {
        return new Byte(Byte.parseByte("0"));
      } else if (edmType == char.class) {
        return new Character('A');
      } else if (edmType == short.class || edmType == Short.class) {
        return new Short(Short.parseShort("0"));
      } else if (edmType == int.class || edmType == Integer.class) {
        return new Integer(0);
      } else if (edmType == long.class || edmType == Long.class) {
        return new Long(0L);
      } else if (edmType == float.class || edmType == Float.class) {
        return new Float(0.0f);
      } else if (edmType == double.class || edmType == Double.class) {
        return new Double(0.0d);
      } else if (edmType == BigDecimal.class) {
        return BigDecimal.valueOf(0.0);
      } else if (edmType == UUID.class) {
        return UUID.fromString("0");
      } else if (edmType == Timestamp.class) {
        return new Timestamp(Calendar.getInstance().getTimeInMillis());
      } else if (edmType == Calendar.class) {
        return Calendar.getInstance();
      } else if (edmType == byte[].class || edmType == Byte[].class) {
        return new byte[0];
      } else if (edmType == Date.class) {
        return new Date();
      } else if (edmType == BigInteger.class) {
        return new BigInteger("0");
      } else if (edmType == Time.class) {
        return new Time(0L);
      } else {
        throw new EntityProviderProducerException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED);
      }
    }
  
  private void appendProperties(final XMLStreamWriter writer, final EntityInfoAggregator eia,
      final Map<String, Object> data) throws EntityProviderException {
    try {
      {
        if (!data.isEmpty() && data.size() > 0) {
          writer.writeStartElement(Edm.NAMESPACE_M_2007_08, FormatXml.M_PROPERTIES);
          for (String propertyName : eia.getPropertyNames()) {
            if (data.containsKey(propertyName)) {
              appendPropertyNameValue(writer, eia, data, propertyName);
            }
          }
          writer.writeEndElement();
        }
      }
    } catch (XMLStreamException e) {
      throw new EntityProviderProducerException(EntityProviderException.COMMON, e);
    }
  }

  /**
   * @param writer
   * @param eia
   * @param data
   * @param propertyName
   * @throws EntityProviderException
   */
  private void appendPropertyNameValue(final XMLStreamWriter writer, final EntityInfoAggregator eia,
      final Map<String, Object> data, String propertyName) throws EntityProviderException {
    EntityPropertyInfo propertyInfo = eia.getPropertyInfo(propertyName);
    if (isNotMappedViaCustomMapping(propertyInfo)) {
      Object value = data.get(propertyName);
      XmlPropertyEntitySerializer aps = new XmlPropertyEntitySerializer(properties);
      aps.append(writer, propertyInfo.getName(), propertyInfo, value);
    }
  }

  private boolean isNotMappedViaCustomMapping(final EntityPropertyInfo propertyInfo) {
    EdmCustomizableFeedMappings customMapping = propertyInfo.getCustomMapping();
    if (customMapping != null && customMapping.isFcKeepInContent() != null) {
      return customMapping.isFcKeepInContent();
    }
    return true;
  }
}
