Excerpt.java 10.2 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  javax.jcr.ItemVisitor
 *  javax.jcr.Node
 *  javax.jcr.Property
 *  javax.jcr.RepositoryException
 *  javax.jcr.Value
 *  javax.jcr.query.Row
 *  javax.jcr.util.TraversingItemVisitor
 *  javax.jcr.util.TraversingItemVisitor$Default
 *  org.apache.sling.api.resource.Resource
 */
package com.day.cq.search.impl.misc;

import com.day.cq.search.impl.result.HitImpl;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.jcr.ItemVisitor;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.query.Row;
import javax.jcr.util.TraversingItemVisitor;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.parser.DTD;
import javax.swing.text.html.parser.DocumentParser;
import javax.swing.text.html.parser.Entity;
import javax.swing.text.html.parser.ParserDelegator;
import org.apache.sling.api.resource.Resource;

public class Excerpt {
    private static final HTML.Tag HIGHLIGHT_TAG = HTML.Tag.STRONG;
    private static final int HIGHLIGHT_OFFSET = HIGHLIGHT_TAG.toString().length() * 2 + 5;
    private final String text;
    private final boolean hasHighlights;

    private Excerpt(String text, boolean hasHighlights) {
        this.text = text;
        this.hasHighlights = hasHighlights;
    }

    private Excerpt(String text) {
        this(text, false);
    }

    public static Excerpt create(final HitImpl hit, final Set excerptPropNames, final int maxLength) throws RepositoryException {
        ArrayList excerpt;
        block5 : {
            Node content;
            Node node = (Node)hit.getResource().adaptTo(Node.class);
            if (node == null) {
                return new Excerpt(hit.getExcerpts().get("."));
            }
            Node node2 = content = node.hasNode("jcr:content") ? node.getNode("jcr:content") : node;
            if (content.isNodeType("nt:resource") || node.isNodeType("dam:Asset")) {
                return new Excerpt(hit.getExcerpts().get("."));
            }
            excerpt = new ArrayList();
            final int prefixLength = node.getPath().length() + 1;
            try {
                content.accept((ItemVisitor)new TraversingItemVisitor.Default(true){

                    protected void entering(Property property, int level) throws RepositoryException {
                        if (!excerptPropNames.contains(property.getName())) {
                            return;
                        }
                        String relPath = property.getPath().substring(prefixLength);
                        Excerpt e = Excerpt.createExcerpt(property, relPath, hit.getRow(), maxLength);
                        if (e == null) {
                            return;
                        }
                        if (e.hasHighlights) {
                            excerpt.clear();
                            excerpt.add(e);
                            throw new RepositoryException();
                        }
                        if (excerpt.size() == 0) {
                            excerpt.add(e);
                        }
                    }
                });
            }
            catch (RepositoryException e) {
                if (excerpt.size() != 0) break block5;
                throw e;
            }
        }
        if (excerpt.size() == 0) {
            return new Excerpt("");
        }
        return (Excerpt)excerpt.get(0);
    }

    public String getText() {
        return this.text;
    }

    public static String getFirstSpan(String excerpt) {
        int end;
        int start = excerpt.indexOf("<span>");
        if (start != -1 && (end = excerpt.indexOf("</span>", start)) != -1) {
            return excerpt.substring(start + "<span>".length(), end);
        }
        return excerpt;
    }

    private static Excerpt createExcerpt(Property property, String relPath, Row row, final int maxLength) throws RepositoryException {
        if (property.isMultiple() || property.getLength() == 0) {
            return null;
        }
        Value v = row.getValue("rep:excerpt(" + relPath + ")");
        if (v == null) {
            return null;
        }
        final int[] numHighlights = new int[]{0};
        final StringBuffer text = new StringBuffer();
        HTMLEditorKit.Parser parser = HTMLParser.getInstance();
        try {
            parser.parse(new StringReader(Excerpt.getFirstSpan(v.getString())), new HTMLEditorKit.ParserCallback(){
                private boolean tagOpened;
                private int tagOpenedPos;
                private boolean highlighted;
                private boolean complete;

                /*
                 * Enabled force condition propagation
                 * Lifted jumps to return sites
                 */
                @Override
                public void handleText(char[] data, int pos) {
                    if (this.complete) {
                        return;
                    }
                    this.stripTagsAndAppend(new String(data));
                    if (this.highlighted || text.length() <= this.getMaxLength()) return;
                    if (numHighlights[0] > 0) {
                        if (this.tagOpened) {
                            text.setLength(this.tagOpenedPos);
                            this.tagOpened = false;
                        }
                        if (text.length() <= this.getMaxLength()) return;
                        for (int i = this.getMaxLength(); i >= 0; --i) {
                            if (!Character.isWhitespace(text.charAt(i))) continue;
                            text.setLength(i + 1);
                            text.append("...");
                            break;
                        }
                        this.complete = true;
                        return;
                    } else {
                        if (this.tagOpened) {
                            text.setLength(this.tagOpenedPos + 1);
                        }
                        for (int i = text.length() - this.getMaxLength() / 3; i >= 0; --i) {
                            if (!Character.isWhitespace(text.charAt(i))) continue;
                            text.delete(0, i + 1);
                            if (this.tagOpenedPos > i + 1) {
                                this.tagOpenedPos -= i + 1;
                                return;
                            }
                            this.tagOpenedPos = 0;
                            return;
                        }
                    }
                }

                @Override
                public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
                    if (this.complete) {
                        return;
                    }
                    if (t == HIGHLIGHT_TAG) {
                        text.append("<");
                        text.append(t.toString());
                        text.append(">");
                        this.highlighted = true;
                        int[] arrn = numHighlights;
                        arrn[0] = arrn[0] + 1;
                    }
                }

                @Override
                public void handleEndTag(HTML.Tag t, int pos) {
                    if (this.complete) {
                        return;
                    }
                    if (t == HIGHLIGHT_TAG) {
                        text.append("</");
                        text.append(t.toString());
                        text.append(">");
                        this.highlighted = false;
                    }
                }

                private int getMaxLength() {
                    return maxLength + numHighlights[0] * HIGHLIGHT_OFFSET;
                }

                private void stripTagsAndAppend(String s) {
                    block4 : for (int i = 0; i < s.length(); ++i) {
                        char c = s.charAt(i);
                        switch (c) {
                            case '<': {
                                if (!this.tagOpened) {
                                    this.tagOpenedPos = text.length();
                                }
                                this.tagOpened = true;
                                text.append(c);
                                continue block4;
                            }
                            case '>': {
                                text.setLength(this.tagOpenedPos);
                                this.tagOpened = false;
                                continue block4;
                            }
                            default: {
                                text.append(c);
                            }
                        }
                    }
                }
            }, true);
        }
        catch (IOException e) {
            throw new RepositoryException((Throwable)e);
        }
        return new Excerpt(text.toString(), numHighlights[0] > 0);
    }

    private static final class DTDEx
    extends DTD {
        static final DTD INSTANCE = ParserDelegatorEx.createDTD();

        private DTDEx() {
            super("html32");
        }

        private static final class ParserDelegatorEx
        extends ParserDelegator {
            private static final long serialVersionUID = -7151679094537195031L;

            private ParserDelegatorEx() {
            }

            static DTD createDTD() {
                DTD dtd = new DTDEx();
                dtd = ParserDelegator.createDTD(dtd, "html32");
                dtd.defEntity("apos", 65536, 39);
                return dtd;
            }
        }

    }

    private static final class HTMLParser
    extends HTMLEditorKit {
        private static final long serialVersionUID = 383121295616881915L;

        private HTMLParser() {
        }

        public static HTMLEditorKit.Parser getInstance() {
            return new HTMLEditorKit.Parser(){

                @Override
                public void parse(Reader r, HTMLEditorKit.ParserCallback cb, boolean ignoreCharSet) throws IOException {
                    new DocumentParser(DTDEx.INSTANCE).parse(r, cb, ignoreCharSet);
                }
            };
        }

    }

}