Uploaded image for project: 'Magnolia'
  1. Magnolia
  2. MAGNOLIA-9108

Support queryResults wrapper from AbstractContentDecorator

    XMLWordPrintable

Details

    • Improvement
    • Resolution: Unresolved
    • Neutral
    • None
    • 6.2.39
    • None
    • None

    Description

      Customer want to replace all 'ß' with 'ss' for certain sites (not for all) and have currently solved this by wrapping the session using a custom ContentDecorator (wrapped javax.jcr.repository providing wrapped sessions using info.magnolia.repositoryProvider.getUnderlyingRepository()).

      While this works for nodes retrieved by path or id it doesn't work for nodes retrieved by queries, since they are not wrapped in the info.magnolia.jcr.decoration.ContentDecoratorWorkspaceWrapper.

      So we can achieved this by wrapping it ourself, but I think it would be best, if you could apply this to core implementation:

      import info.magnolia.jcr.decoration.AbstractContentDecorator;
      import info.magnolia.jcr.decoration.ContentDecorator;
      import info.magnolia.jcr.decoration.ContentDecoratorWorkspaceWrapper;
      import info.magnolia.jcr.iterator.WrappingNodeIterator;
      import lombok.experimental.Delegate;
      import org.apache.jackrabbit.commons.iterator.RowIteratorAdapter;
      
      import javax.jcr.Node;
      import javax.jcr.NodeIterator;
      import javax.jcr.RepositoryException;
      import javax.jcr.Workspace;
      import javax.jcr.query.*;
      
      public abstract class AbstractQueryContentDecorator extends AbstractContentDecorator {
      
      	@Override
      	public Workspace wrapWorkspace(final Workspace workspace) {
      		return new QueryContentDecoratorWorkspaceWrapper(workspace, this);
      	}
      
      	private static class QueryContentDecoratorWorkspaceWrapper extends ContentDecoratorWorkspaceWrapper {
      		private final ContentDecorator contentDecorator;
      
      		private QueryContentDecoratorWorkspaceWrapper(final Workspace wrapped, final ContentDecorator contentDecorator) {
      			super(wrapped, contentDecorator);
      			this.contentDecorator = contentDecorator;
      		}
      
      		@Override
      		public QueryManager getQueryManager() throws RepositoryException {
      			return new QueryManagerWrapper(super.getQueryManager(), contentDecorator);
      		}
      	}
      
      	private static class QueryManagerWrapper implements QueryManager {
      		private interface Create {
      			Query createQuery(String statement, String language);
      			Query getQuery(Node node);
      		}
      
      		@Delegate(excludes = QueryManagerWrapper.Create.class)
      		private final QueryManager wrapped;
      		private final ContentDecorator contentDecorator;
      
      		private QueryManagerWrapper(final QueryManager wrapped, final ContentDecorator contentDecorator) {
      			this.wrapped = wrapped;
      			this.contentDecorator = contentDecorator;
      		}
      
      		@Override
      		public Query createQuery(final String statement, final String language) throws RepositoryException {
      			return new QueryWrapper(wrapped.createQuery(statement, language), contentDecorator);
      		}
      
      		@Override
      		public Query getQuery(final Node node) throws RepositoryException {
      			return new QueryWrapper(wrapped.getQuery(node), contentDecorator);
      		}
      	}
      
      	private static class QueryWrapper implements Query {
      		private interface Execute {
      			QueryResult execute();
      		}
      
      		@Delegate(excludes = QueryWrapper.Execute.class)
      		private final Query wrapped;
      		private final ContentDecorator contentDecorator;
      
      		private QueryWrapper(final Query wrapped, final ContentDecorator contentDecorator) {
      			this.wrapped = wrapped;
      			this.contentDecorator = contentDecorator;
      		}
      
      		@Override
      		public QueryResult execute() throws InvalidQueryException, RepositoryException {
      			return new QueryResultWrapper(wrapped.execute(), contentDecorator);
      		}
      	}
      
      	private static class QueryResultWrapper implements QueryResult {
      		private interface Iterator {
      			RowIterator getRows();
      			NodeIterator getNodes();
      		}
      
      		@Delegate(excludes = Iterator.class)
      		private final QueryResult wrapped;
      		private final ContentDecorator contentDecorator;
      
      		private QueryResultWrapper(final QueryResult wrapped, final ContentDecorator contentDecorator) {
      			this.wrapped = wrapped;
      			this.contentDecorator = contentDecorator;
      		}
      
      		@Override
      		public RowIterator getRows() throws RepositoryException {
      			return new RowIteratorAdapter(wrapped.getRows()) {
      				@Override
      				public Row nextRow() {
      					return new RowWrapper(super.nextRow(), contentDecorator);
      				}
      			};
      		}
      
      		@Override
      		public NodeIterator getNodes() throws RepositoryException {
      			return new WrappingNodeIterator(wrapped.getNodes(), contentDecorator);
      		}
      	}
      
      	private static class RowWrapper implements Row {
      		private interface Iterator {
      			Node getNode();
      			Node getNode(String selectorName);
      		}
      
      		@Delegate(excludes = RowWrapper.Iterator.class)
      		private final Row wrapped;
      		private final ContentDecorator contentDecorator;
      
      		private RowWrapper(final Row wrapped, final ContentDecorator contentDecorator) {
      			this.wrapped = wrapped;
      			this.contentDecorator = contentDecorator;
      		}
      
      		@Override
      		public Node getNode() throws RepositoryException {
      			return contentDecorator.wrapNode(wrapped.getNode());
      		}
      
      		@Override
      		public Node getNode(final String selectorName) throws RepositoryException {
      			return contentDecorator.wrapNode(wrapped.getNode(selectorName));
      		}
      	}
      }
      

      Checklists

        Acceptance criteria

        Attachments

          Activity

            People

              Unassigned Unassigned
              viet.nguyen Viet Nguyen
              Votes:
              1 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:

                Checklists

                  Task DoD