[MAGNOLIA-9108] Support queryResults wrapper from AbstractContentDecorator Created: 25/Sep/23 Updated: 25/Sep/23 |
|
| Status: | Open |
| Project: | Magnolia |
| Component/s: | None |
| Affects Version/s: | 6.2.39 |
| Fix Version/s: | None |
| Type: | Improvement | Priority: | Neutral |
| Reporter: | Viet Nguyen | Assignee: | Unassigned |
| Resolution: | Unresolved | Votes: | 1 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Issue Links: |
|
||||
| Template: |
|
||||
| Acceptance criteria: |
Empty
|
||||
| Task DoD: |
[ ]*
Doc/release notes changes? Comment present?
[ ]*
Downstream builds green?
[ ]*
Solution information and context easily available?
[ ]*
Tests
[ ]*
FixVersion filled and not yet released
[ ] 
Architecture Decision Record (ADR)
|
||||
| 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)); } } } |
| Comments |
| Comment by Viet Nguyen [ 25/Sep/23 ] |
|
This could also be an option instead of applying above big change: public abstract class AbstractQueryContentDecorator extends AbstractContentDecorator { private final boolean wrapQueryResult; public AbstractQueryContentDecorator(final boolean wrapQueryResult) { this.wrapQueryResult = wrapQueryResult; } @Override public Workspace wrapWorkspace(final Workspace workspace) { if(wrapQueryResult) { return new QueryContentDecoratorWorkspaceWrapper(workspace, this); } return super.wrapWorkspace(workspace); } ... } |