001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.extensions.markup.html.basic;
018
019import java.util.HashMap;
020import java.util.Map;
021import java.util.regex.Matcher;
022import java.util.regex.Pattern;
023
024import org.apache.wicket.util.string.Strings;
025
026
027/**
028 * This base implementation iterates over all provided <code>ILinkRenderStrategy</code>
029 * implementations and applies them to the input text.
030 * 
031 * @author Gerolf Seitz
032 */
033public class LinkParser implements ILinkParser
034{
035        private final Map<Pattern, ILinkRenderStrategy> renderStrategies = new HashMap<>();
036
037        /**
038         * Adds a render strategy to the parser.
039         * 
040         * @param pattern
041         *            the pattern to which the provided <code>renderStrategy</code> should be applied.
042         * @param renderStrategy
043         *            the <code>ILinkRenderStrategy</code> which is applied to the text found by the
044         *            provided <code>pattern</code>.
045         * @return this <code>ILinkParser</code>.
046         */
047        public ILinkParser addLinkRenderStrategy(final String pattern,
048                final ILinkRenderStrategy renderStrategy)
049        {
050                final Pattern compiledPattern = Pattern.compile(pattern, Pattern.DOTALL);
051                renderStrategies.put(compiledPattern, renderStrategy);
052                return this;
053        }
054
055        /**
056         * @see ILinkParser#parse(String)
057         */
058        @Override
059        public String parse(final String text)
060        {
061                if (Strings.isEmpty(text))
062                {
063                        return text;
064                }
065
066                String work = text;
067
068                // don't try to parse markup. just plain text. WICKET-4099
069                if (work.indexOf('<') == -1)
070                {
071                        for (Map.Entry<Pattern, ILinkRenderStrategy> entry : renderStrategies.entrySet())
072                        {
073                                Pattern pattern = entry.getKey();
074                                ILinkRenderStrategy strategy = entry.getValue();
075
076                                Matcher matcher = pattern.matcher(work);
077                                StringBuffer buffer = new StringBuffer();
078                                while (matcher.find())
079                                {
080                                        String str = matcher.group();
081                                        matcher.appendReplacement(buffer, strategy.buildLink(str));
082                                }
083                                matcher.appendTail(buffer);
084                                work = buffer.toString();
085                        }
086                }
087                return work;
088        }
089}