package ecologylab.serialization.serializers.stringformats;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import ecologylab.serialization.ClassDescriptor;
import ecologylab.serialization.FieldDescriptor;
import ecologylab.serialization.FieldTypes;
import ecologylab.serialization.SIMPLTranslationException;
import ecologylab.serialization.TranslationContext;
import ecologylab.serialization.XMLTools;
import ecologylab.serialization.annotations.FieldUsage;
import ecologylab.serialization.formatenums.Format;
/**
*
* @author nabeel
*/
public class BibtexSerializer extends StringSerializer implements FieldTypes
{
public BibtexSerializer()
{
}
@Override
public void serialize(Object object, Appendable appendable, TranslationContext translationContext)
throws SIMPLTranslationException
{
translationContext.resolveGraph(object);
ClassDescriptor<? extends FieldDescriptor> rootObjectClassDescriptor = ClassDescriptor
.getClassDescriptor(object.getClass());
try
{
serialize(object, rootObjectClassDescriptor.pseudoFieldDescriptor(), appendable,
translationContext);
}
catch (IOException e)
{
throw new SIMPLTranslationException("IO Exception occurred", e);
}
}
/**
*
* @param object
* @param rootObjectFieldDescriptor
* @param appendable
* @param translationContext
* @throws SIMPLTranslationException
* @throws IOException
*/
private void serialize(Object object, FieldDescriptor rootObjectFieldDescriptor,
Appendable appendable, TranslationContext translationContext)
throws SIMPLTranslationException, IOException
{
serializationPreHook(object, translationContext);
writeObjectStart(rootObjectFieldDescriptor, appendable);
ArrayList<? extends FieldDescriptor> allFieldDescriptors = getClassDescriptor(object)
.allFieldDescriptors();
serializeFields(object, appendable, translationContext, allFieldDescriptors);
writeClose(appendable);
serializationPostHook(object, translationContext);
}
/**
*
* @param object
* @param appendable
* @param translationContext
* @param allFieldDescriptors
* @throws IOException
* @throws SIMPLTranslationException
*/
private void serializeFields(Object object, Appendable appendable,
TranslationContext translationContext,
ArrayList<? extends FieldDescriptor> allFieldDescriptors) throws IOException,
SIMPLTranslationException
{
int numOfFields = 0;
for (FieldDescriptor childFd : allFieldDescriptors)
{
switch (childFd.getType())
{
case SCALAR:
serializeScalar(object, childFd, appendable, translationContext);
break;
case COMPOSITE_ELEMENT:
serializeComposite(object, appendable, translationContext, childFd);
break;
case COLLECTION_SCALAR:
case MAP_SCALAR:
serializeScalarCollection(object, appendable, translationContext, childFd);
break;
case COLLECTION_ELEMENT:
case MAP_ELEMENT:
if (!childFd.isPolymorphic())
serializeCompositeCollection(object, appendable, translationContext, childFd);
break;
}
if (++numOfFields < allFieldDescriptors.size())
appendable.append(',');
}
}
/**
*
* @param object
* @param fd
* @param appendable
* @param translationContext
* @throws SIMPLTranslationException
* @throws IOException
*/
private void serializeScalar(Object object, FieldDescriptor fd, Appendable appendable,
TranslationContext translationContext) throws SIMPLTranslationException, IOException
{
writeBibtexAttribute(object, fd, appendable, translationContext);
}
private void serializeComposite(Object object, Appendable appendable,
TranslationContext translationContext, FieldDescriptor fd) throws SIMPLTranslationException,
IOException
{
Object compositeObject = fd.getValue(object);
FieldDescriptor compositeAsScalarFD = getClassDescriptor(compositeObject)
.getScalarValueFieldDescripotor();
if (compositeAsScalarFD != null)
{
writeScalarBibtexAttribute(compositeObject, compositeAsScalarFD, appendable, translationContext);
}
}
private void writeScalarBibtexAttribute(Object object, FieldDescriptor fd, Appendable appendable,
TranslationContext translationContext) throws SIMPLTranslationException
{
if (!fd.isDefaultValueFromContext(object))
{
fd.appendValue(appendable, object, translationContext, Format.BIBTEX);
}
}
/**
*
* @param object
* @param fd
* @param appendable
* @param translationContext
* @throws SIMPLTranslationException
* @throws IOException
*/
private void writeBibtexAttribute(Object object, FieldDescriptor fd, Appendable appendable,
TranslationContext translationContext) throws SIMPLTranslationException, IOException
{
if (!fd.isDefaultValueFromContext(object))
{
if (!fd.isBibtexKey())
{
appendable.append(fd.getBibtexTagName());
appendable.append('=');
appendable.append('{');
}
}
fd.appendValue(appendable, object, translationContext, Format.BIBTEX);
if (!fd.isBibtexKey())
appendable.append('}');
}
/**
*
* @param object
* @param appendable
* @param translationContext
* @param fd
* @throws IOException
* @throws SIMPLTranslationException
*/
private void serializeCompositeCollection(Object object, Appendable appendable,
TranslationContext translationContext, FieldDescriptor fd) throws IOException,
SIMPLTranslationException
{
Object scalarCollectionObject = fd.getValue(object);
Collection<?> scalarCollection = XMLTools.getCollection(scalarCollectionObject);
String delim = "author".equals(fd.getBibtexTagName()) ? " and " : translationContext
.getDelimiter();
if (scalarCollection.size() > 0)
{
int numberOfItems = 0;
writeCollectionStart(fd, appendable);
for (Object collectionObject : scalarCollection)
{
FieldDescriptor compositeAsScalarFD = getClassDescriptor(collectionObject)
.getScalarValueFieldDescripotor();
if (compositeAsScalarFD != null)
{
writeScalarBibtexAttribute(collectionObject, compositeAsScalarFD, appendable,
translationContext);
}
if (++numberOfItems < scalarCollection.size())
appendable.append(delim);
}
writeCollectionEnd(appendable);
}
}
/**
*
* @param object
* @param appendable
* @param translationContext
* @param fd
* @throws IOException
* @throws SIMPLTranslationException
*/
private void serializeScalarCollection(Object object, Appendable appendable,
TranslationContext translationContext, FieldDescriptor fd) throws IOException,
SIMPLTranslationException
{
Object scalarCollectionObject = fd.getValue(object);
Collection<?> scalarCollection = XMLTools.getCollection(scalarCollectionObject);
String delim = "author".equals(fd.getBibtexTagName()) ? " and " : translationContext
.getDelimiter();
if (scalarCollection.size() > 0)
{
int numberOfItems = 0;
writeCollectionStart(fd, appendable);
for (Object collectionObject : scalarCollection)
{
writeCollectionScalar(collectionObject, fd, appendable, translationContext);
if (++numberOfItems < scalarCollection.size())
appendable.append(delim);
}
writeCollectionEnd(appendable);
}
}
/**
*
* @param fd
* @param appendable
* @throws IOException
*/
private void writeCollectionStart(FieldDescriptor fd, Appendable appendable) throws IOException
{
appendable.append(fd.getTagName());
appendable.append('=');
appendable.append("{");
}
/**
*
* @param appendable
* @throws IOException
*/
private void writeCollectionEnd(Appendable appendable) throws IOException
{
appendable.append("}");
}
/**
*
* @param collectionObject
* @param fd
* @param appendable
* @param translationContext
* @throws SIMPLTranslationException
*/
private void writeCollectionScalar(Object collectionObject, FieldDescriptor fd,
Appendable appendable, TranslationContext translationContext)
throws SIMPLTranslationException
{
fd.appendCollectionScalarValue(appendable, collectionObject, translationContext, Format.BIBTEX);
}
/**
*
* @param appendable
* @throws IOException
*/
private void writeClose(Appendable appendable) throws IOException
{
appendable.append('}');
}
/**
*
* @param fd
* @param appendable
* @throws IOException
*/
private void writeObjectStart(FieldDescriptor fd, Appendable appendable) throws IOException
{
appendable.append('@');
appendable.append(fd.getBibtexTagName());
appendable.append('{');
}
}