/* * 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 org.esigate.parser.future; import java.io.IOException; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.http.HttpResponse; import org.esigate.HttpErrorPage; import org.esigate.impl.DriverRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class is based on Parser. * * @see org.esigate.parser.Parser * @author Nicolas Richeton * */ public class FutureParser { private static final Logger LOG = LoggerFactory.getLogger(FutureParser.class); private final Pattern pattern; private final List<FutureElementType> elementTypes; private DriverRequest httpRequest; private HttpResponse httpResponse; private Map<String, Object> data = null; /** * Creates a Parser with a given regular expression pattern and ElementTypes. * * @param pattern * The regular expression Pattern * @param elementTypes * The element types */ public FutureParser(Pattern pattern, FutureElementType... elementTypes) { this.pattern = pattern; this.elementTypes = new ArrayList<>(elementTypes.length + 1); Collections.addAll(this.elementTypes, elementTypes); this.elementTypes.add(UnknownElement.TYPE); } /** * Parses all the CharSequence. * * @param in * The CharSequence to parse * @param out * The Writable to write the result to * @throws IOException * @throws HttpErrorPage */ public void parse(CharSequence in, FutureAppendable out) throws IOException, HttpErrorPage { FutureParserContextImpl ctx = new FutureParserContextImpl(out, this.httpRequest, this.httpResponse, this.data); Matcher matcher = this.pattern.matcher(in); int currentPosition = 0; while (matcher.find()) { String tag = matcher.group(); ctx.characters(new CharSequenceFuture(in.subSequence(currentPosition, matcher.start()))); currentPosition = matcher.end(); if (ctx.isCurrentTagEnd(tag)) { // check if this is the end tag for current element LOG.info("Processing end tag {}", tag); ctx.endElement(tag); } else { // if not, it is an opening tag for a new element LOG.info("Processing start tag {}", tag); FutureElementType type = null; for (FutureElementType t : this.elementTypes) { if (t.isStartTag(tag)) { type = t; break; } } FutureElement element = type.newInstance(); ctx.startElement(type, element, tag); if (type.isSelfClosing(tag)) { ctx.endElement(tag); } } } // we reached the end of input ctx.characters(new CharSequenceFuture(in.subSequence(currentPosition, in.length()))); } public void setHttpRequest(DriverRequest httpRequest) { this.httpRequest = httpRequest; } public void setData(String key, Object o) { if (this.data == null) { this.data = new HashMap<>(); } this.data.put(key, o); } }