package org.atomhopper.hibernate.adapter; 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.jpa.PersistedCategory; import org.atomhopper.adapter.jpa.PersistedEntry; import org.atomhopper.adapter.jpa.PersistedFeed; import org.atomhopper.adapter.request.adapter.DeleteEntryRequest; import org.atomhopper.adapter.request.adapter.PostEntryRequest; import org.atomhopper.adapter.request.adapter.PutEntryRequest; import org.atomhopper.dbal.FeedRepository; 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 java.io.IOException; import java.io.StringWriter; import java.util.*; import com.yammer.metrics.Metrics; import com.yammer.metrics.core.Counter; import static org.apache.abdera.i18n.text.UrlEncoding.decode; public class HibernateFeedPublisher implements FeedPublisher { private static final Logger LOG = LoggerFactory.getLogger(HibernateFeedPublisher.class); private static final String UUID_URI_SCHEME = "urn:uuid:"; private static final String LINKREL_SELF = "self"; private boolean allowOverrideId = false; private boolean allowOverrideDate = false; private Map<String, Counter> counterMap = Collections.synchronizedMap(new HashMap<String, Counter>()); private FeedRepository feedRepository; public void setFeedRepository(FeedRepository feedRepository) { this.feedRepository = feedRepository; } 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(); // Update our category indicies final Set<PersistedCategory> entryCategories = feedRepository.updateCategories(processCategories(abderaParsedEntry.getCategories())); persistedEntry.setCategories(entryCategories); 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 = feedRepository.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(decode(postEntryRequest.urlFor(new EnumKeyedTemplateParameters<URITemplate>(URITemplate.FEED))) + "entries/" + persistedEntry.getEntryId()).setRel(LINKREL_SELF); } final PersistedFeed feedRef = new PersistedFeed(postEntryRequest.getFeedName(), UUID_URI_SCHEME + UUID.randomUUID().toString()); persistedEntry.setFeed(feedRef); persistedEntry.setEntryBody(entryToString(abderaParsedEntry)); abderaParsedEntry.setUpdated(persistedEntry.getDateLastUpdated()); abderaParsedEntry.setPublished(persistedEntry.getCreationDate()); feedRepository.saveEntry(persistedEntry); incrementCounterForFeed(postEntryRequest.getFeedName()); return ResponseBuilder.created(abderaParsedEntry); } private Set<PersistedCategory> processCategories(List<org.apache.abdera.model.Category> abderaCategories) { final Set<PersistedCategory> entryCategories = new HashSet<PersistedCategory>(); for (org.apache.abdera.model.Category abderaCat : abderaCategories) { entryCategories.add(new PersistedCategory(abderaCat.getTerm().toLowerCase())); } return entryCategories; } 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 void incrementCounterForFeed(String feedName) { if (!counterMap.containsKey(feedName)) { synchronized (counterMap) { if (!counterMap.containsKey(feedName)) { Counter counter = Metrics.newCounter(HibernateFeedPublisher.class, "entries-created-for-" + feedName); counterMap.put(feedName, counter); } } } counterMap.get(feedName).inc(); } }