/** * Copyright 2008 - 2009 Pro-Netics S.P.A. * * Licensed 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 it.pronetics.madstore.repository.jcr.impl; import it.pronetics.madstore.common.AtomConstants; import it.pronetics.madstore.repository.EntryRepository; import it.pronetics.madstore.repository.index.SearchResult; import it.pronetics.madstore.repository.support.AtomRepositoryException; import it.pronetics.madstore.repository.util.PagingList; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.Session; import org.joda.time.DateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.extensions.jcr.JcrCallback; import org.w3c.dom.Element; /** * {@link it.pronetics.madstore.repository.EntryRepository} implementation based on Java Content Repository * APIs. * @author Salvatore Incandela * @author Sergio Bossa */ public final class JcrEntryRepository extends AbstractJcrRepository implements EntryRepository { private static final Logger LOG = LoggerFactory.getLogger(JcrEntryRepository.class); @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public String put(final String collectionKey, final Element entryElement) { if (entryElement == null || collectionKey == null || collectionKey.equals("")) { throw new IllegalArgumentException("Parameters cannot be null or empty strings!"); } else if (entryElement.getAttribute(AtomConstants.ATOM_KEY).equals("")) { throw new AtomRepositoryException("The entry element has no key!"); } return (String) jcrTemplate.execute(new JcrCallback() { public Object doInJcr(final Session session) throws IOException, RepositoryException { String entryKey = entryElement.getAttribute(AtomConstants.ATOM_KEY); if (contains(collectionKey, entryKey)) { delete(collectionKey, entryKey); indexManager.delete(collectionKey, entryKey); } importNodeFromDomEntry(collectionKey, entryKey, entryElement, session); indexManager.index(collectionKey, entryKey, entryElement); session.save(); return entryKey; } }); } @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public String putIfAbsent(final String collectionKey, final Element entryElement) { if (entryElement == null || collectionKey == null || collectionKey.equals("")) { throw new IllegalArgumentException("Parameters cannot be null or empty strings!"); } else if (entryElement.getAttribute(AtomConstants.ATOM_KEY).equals("")) { throw new AtomRepositoryException("The entry element has no key!"); } return (String) jcrTemplate.execute(new JcrCallback() { public Object doInJcr(final Session session) throws IOException, RepositoryException { String entryKey = entryElement.getAttribute(AtomConstants.ATOM_KEY); if (!contains(collectionKey, entryKey)) { Node collection = getCollectionNode(collectionKey, session); if (collection != null) { importNodeFromDomEntry(collectionKey, entryKey, entryElement, session); indexManager.index(collectionKey, entryKey, entryElement); session.save(); return entryKey; } } return null; } }); } @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public String updateIfNewer(final String collectionKey, final Element entryElement) { if (entryElement == null || collectionKey == null || collectionKey.equals("")) { throw new IllegalArgumentException("Parameters cannot be null or empty strings!"); } else if (entryElement.getAttribute(AtomConstants.ATOM_KEY).equals("")) { throw new AtomRepositoryException("The entry element has no key!"); } return (String) jcrTemplate.execute(new JcrCallback() { public Object doInJcr(final Session session) throws IOException, RepositoryException { String entryKey = entryElement.getAttribute(AtomConstants.ATOM_KEY); if (contains(collectionKey, entryKey)) { Element repositoryEntry = read(collectionKey, entryKey); String repositoryEntryUpdated = repositoryEntry.getElementsByTagNameNS(AtomConstants.ATOM_NS, AtomConstants.ATOM_ENTRY_UPDATED).item(0).getTextContent(); String newEntryUpdated = entryElement.getElementsByTagNameNS(AtomConstants.ATOM_NS, AtomConstants.ATOM_ENTRY_UPDATED).item(0).getTextContent(); DateTime repositoryEntryDateTime = new DateTime(repositoryEntryUpdated); DateTime newEntryDateTime = new DateTime(newEntryUpdated); if (newEntryDateTime.isAfter(repositoryEntryDateTime)) { if (delete(collectionKey, entryKey) != null) { importNodeFromDomEntry(collectionKey, entryKey, entryElement, session); indexManager.delete(collectionKey, entryKey); indexManager.index(collectionKey, entryKey, entryElement); session.save(); return entryKey; } else { throw new IllegalStateException("Unable to delete: " + entryKey); } } else { return null; } } else { LOG.warn("Entry {} does not exist in collection {}. Nothing to update.", entryKey, collectionKey); return null; } } }); } @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public Boolean delete(final String collectionKey, final String entryKey) { if ((entryKey == null) || (collectionKey == null)) { throw new IllegalArgumentException("Parameters cannot be null or empty strings!"); } return (Boolean) jcrTemplate.execute(new JcrCallback() { public Object doInJcr(final Session session) throws IOException, RepositoryException { Node node = getEntryNode(collectionKey, entryKey, session); if (node != null) { Node container = node.getParent(); container.remove(); indexManager.delete(collectionKey, entryKey); session.save(); return true; } return false; } }); } @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public Element read(final String collectionKey, final String entryKey) { if ((entryKey == null) || (collectionKey == null)) { throw new IllegalArgumentException("Parameters cannot be null or empty strings!"); } return (Element) jcrTemplate.execute(new JcrCallback() { public Object doInJcr(final Session session) throws IOException, RepositoryException { Node node = getEntryNode(collectionKey, entryKey, session); if (node != null) { return exportNodeToDom(node.getPath(), session); } else { return null; } } }); } @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public List<Element> readEntries(final String collectionKey) { return this.readEntries(collectionKey, 0, 0); } @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public PagingList<Element> readEntries(final String collectionKey, final int offset, final int max) { if (collectionKey == null) { throw new IllegalArgumentException("Parameters cannot be null or empty strings!"); } return (PagingList<Element>) jcrTemplate.execute(new JcrCallback() { public Object doInJcr(Session session) throws IOException, RepositoryException { PagingList<Node> nodes = getEntryNodes(collectionKey, offset, max, session); PagingList<Element> elements = new PagingList<Element>( new ArrayList<Element>(nodes.size()), offset, max, nodes.getTotal()); for (Node node : nodes) { Element element = exportNodeToDom(node.getPath(), session); elements.add(element); } return elements; } }); } @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public List<Element> findEntries(String collectionKey, List<String> terms) { return findEntries(collectionKey, terms, 0, 0); } @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public PagingList<Element> findEntries(String collectionKey, List<String> terms, int offset, int max) { PagingList<SearchResult> entryItems = indexManager.searchCollectionByFullText(collectionKey, terms, offset, max); PagingList<Element> elements = new PagingList<Element>( new ArrayList<Element>(), offset, max, entryItems.getTotal()); for (SearchResult entryItem : entryItems) { Element element = read(entryItem.getColletionKey(), entryItem.getEntryKey()); if (element != null) { elements.add(element); } } return elements; } @Transactional(propagation = Propagation.REQUIRED, readOnly = false) public boolean contains(final String collectionKey, final String entryKey) { if ((entryKey == null) || (collectionKey == null)) { throw new IllegalArgumentException("Parameters cannot be null or empty strings!"); } return (Boolean) jcrTemplate.execute(new JcrCallback() { public Object doInJcr(final Session session) throws IOException, RepositoryException { Node contained = getEntryNode(collectionKey, entryKey, session); return contained != null; } }); } }