package org.atomhopper.mongodb.adapter; import com.yammer.metrics.Metrics; import com.yammer.metrics.core.Counter; import org.apache.abdera.model.Category; import org.apache.abdera.model.Entry; import org.apache.commons.lang.StringUtils; import org.atomhopper.adapter.FeedPublisher; import org.atomhopper.adapter.NotImplemented; import org.atomhopper.adapter.PublicationException; import org.atomhopper.adapter.ResponseBuilder; import org.atomhopper.adapter.request.adapter.DeleteEntryRequest; import org.atomhopper.adapter.request.adapter.PostEntryRequest; import org.atomhopper.adapter.request.adapter.PutEntryRequest; import org.atomhopper.mongodb.domain.PersistedCategory; import org.atomhopper.mongodb.domain.PersistedEntry; import org.atomhopper.response.AdapterResponse; import org.atomhopper.response.EmptyBody; import org.atomhopper.util.uri.template.EnumKeyedTemplateParameters; import org.atomhopper.util.uri.template.URITemplate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import java.io.IOException; import java.io.StringWriter; import java.util.*; import static org.apache.abdera.i18n.text.UrlEncoding.decode; import static org.atomhopper.mongodb.adapter.MongodbUtilities.formatCollectionName; public class MongodbFeedPublisher implements FeedPublisher { private static final Logger LOG = LoggerFactory.getLogger(MongodbFeedPublisher.class); private static final String ID = "_id"; private static final String UUID_URI_SCHEME = "urn:uuid:"; private static final String LINKREL_SELF = "self"; private MongoTemplate mongoTemplate; private boolean allowOverrideId = false; private boolean allowOverrideDate = false; private Map<String, Counter> counterMap = Collections.synchronizedMap(new HashMap<String, Counter>()); public void setMongoTemplate(MongoTemplate mongoTemplate) { this.mongoTemplate = mongoTemplate; } public void setAllowOverrideId(boolean allowOverrideId) { this.allowOverrideId = allowOverrideId; } public void setAllowOverrideDate(boolean allowOverrideDate) { this.allowOverrideDate = allowOverrideDate; } @Override @NotImplemented public void setParameters(Map<String, String> params) { throw new UnsupportedOperationException("Not supported yet."); } @Override public AdapterResponse<Entry> postEntry(PostEntryRequest postEntryRequest) { final Entry abderaParsedEntry = postEntryRequest.getEntry(); final PersistedEntry persistedEntry = new PersistedEntry(); boolean entryIdSent = abderaParsedEntry.getId() != null; // Generate an ID for this entry if (allowOverrideId && entryIdSent && StringUtils.isNotBlank(abderaParsedEntry.getId().toString().trim())) { String entryId = abderaParsedEntry.getId().toString(); // Check to see if entry with this id already exists PersistedEntry exists = getEntry(entryId, postEntryRequest.getFeedName()); if (exists != null) { String errMsg = String.format("Unable to persist entry. Reason: entryId (%s) not unique.", entryId); return ResponseBuilder.conflict(errMsg); } persistedEntry.setEntryId(abderaParsedEntry.getId().toString()); } else { persistedEntry.setEntryId(UUID_URI_SCHEME + UUID.randomUUID().toString()); abderaParsedEntry.setId(persistedEntry.getEntryId()); } if (allowOverrideDate) { Date updated = abderaParsedEntry.getUpdated(); if (updated != null) { persistedEntry.setDateLastUpdated(updated); persistedEntry.setCreationDate(updated); } } if (abderaParsedEntry.getSelfLink() == null) { abderaParsedEntry.addLink(new StringBuilder() .append(decode(postEntryRequest.urlFor(new EnumKeyedTemplateParameters<URITemplate>(URITemplate.FEED)))) .append("entries/") .append(persistedEntry.getEntryId()).toString()).setRel(LINKREL_SELF); } persistedEntry.setFeed(postEntryRequest.getFeedName()); for (Category category : (List<Category>) abderaParsedEntry.getCategories()) { persistedEntry.addCategory(new PersistedCategory(category.getTerm().toLowerCase())); } persistedEntry.setEntryBody(entryToString(abderaParsedEntry)); abderaParsedEntry.setId(persistedEntry.getEntryId()); abderaParsedEntry.setUpdated(persistedEntry.getDateLastUpdated()); abderaParsedEntry.setPublished(persistedEntry.getCreationDate()); mongoTemplate.save(persistedEntry, formatCollectionName(postEntryRequest.getFeedName())); incrementCounterForFeed(postEntryRequest.getFeedName()); return ResponseBuilder.created(abderaParsedEntry); } private String entryToString(Entry entry) { final StringWriter writer = new StringWriter(); try { entry.writeTo(writer); } catch (IOException ioe) { LOG.error("Unable to write entry to string. Unable to persist entry. Reason: " + ioe.getMessage(), ioe); throw new PublicationException(ioe.getMessage(), ioe); } return writer.toString(); } @Override @NotImplemented public AdapterResponse<Entry> putEntry(PutEntryRequest putEntryRequest) { throw new UnsupportedOperationException("Not supported."); } @Override @NotImplemented public AdapterResponse<EmptyBody> deleteEntry(DeleteEntryRequest deleteEntryRequest) { throw new UnsupportedOperationException("Not supported."); } private PersistedEntry getEntry(String entryId, String feedName) { final PersistedEntry entry = mongoTemplate.findOne(new Query( Criteria.where(ID).is(entryId)),PersistedEntry.class, formatCollectionName(feedName)); return entry; } private void incrementCounterForFeed(String feedName) { if (!counterMap.containsKey(feedName)) { synchronized (counterMap) { if (!counterMap.containsKey(feedName)) { Counter counter = Metrics.newCounter(MongodbFeedPublisher.class, "entries-created-for-" + feedName); counterMap.put(feedName, counter); } } } counterMap.get(feedName).inc(); } }