001/*
002 * $Id: Anchor.java 4784 2011-03-15 08:33:00Z blowagie $
003 *
004 * This file is part of the iText (R) project.
005 * Copyright (c) 1998-2011 1T3XT BVBA
006 * Authors: Bruno Lowagie, Paulo Soares, et al.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU Affero General Public License version 3
010 * as published by the Free Software Foundation with the addition of the
011 * following permission added to Section 15 as permitted in Section 7(a):
012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT,
013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
014 *
015 * This program is distributed in the hope that it will be useful, but
016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
017 * or FITNESS FOR A PARTICULAR PURPOSE.
018 * See the GNU Affero General Public License for more details.
019 * You should have received a copy of the GNU Affero General Public License
020 * along with this program; if not, see http://www.gnu.org/licenses or write to
021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
022 * Boston, MA, 02110-1301 USA, or download the license from the following URL:
023 * http://itextpdf.com/terms-of-use/
024 *
025 * The interactive user interfaces in modified source and object code versions
026 * of this program must display Appropriate Legal Notices, as required under
027 * Section 5 of the GNU Affero General Public License.
028 *
029 * In accordance with Section 7(b) of the GNU Affero General Public License,
030 * a covered work must retain the producer line in every PDF that is created
031 * or manipulated using iText.
032 *
033 * You can be released from the requirements of the license by purchasing
034 * a commercial license. Buying such a license is mandatory as soon as you
035 * develop commercial activities involving the iText software without
036 * disclosing the source code of your own applications.
037 * These activities include: offering paid services to customers as an ASP,
038 * serving PDFs on the fly in a web application, shipping iText with a closed
039 * source product.
040 *
041 * For more information, please contact iText Software Corp. at this
042 * address: sales@itextpdf.com
043 */
044package com.itextpdf.text;
045
046import java.net.MalformedURLException;
047import java.net.URL;
048import java.util.ArrayList;
049import java.util.List;
050import java.util.Iterator;
051
052/**
053 * An <CODE>Anchor</CODE> can be a reference or a destination of a reference.
054 * <P>
055 * An <CODE>Anchor</CODE> is a special kind of <CODE>Phrase</CODE>.
056 * It is constructed in the same way.
057 * <P>
058 * Example:
059 * <BLOCKQUOTE><PRE>
060 * <STRONG>Anchor anchor = new Anchor("this is a link");</STRONG>
061 * <STRONG>anchor.setName("LINK");</STRONG>
062 * <STRONG>anchor.setReference("http://www.lowagie.com");</STRONG>
063 * </PRE></BLOCKQUOTE>
064 *
065 * @see         Element
066 * @see         Phrase
067 */
068
069public class Anchor extends Phrase {
070
071        // constant
072        private static final long serialVersionUID = -852278536049236911L;
073
074    // membervariables
075
076        /** This is the name of the <CODE>Anchor</CODE>. */
077    protected String name = null;
078
079    /** This is the reference of the <CODE>Anchor</CODE>. */
080    protected String reference = null;
081
082    // constructors
083
084    /**
085     * Constructs an <CODE>Anchor</CODE> without specifying a leading.
086     */
087    public Anchor() {
088        super(16);
089    }
090
091    /**
092     * Constructs an <CODE>Anchor</CODE> with a certain leading.
093     *
094     * @param   leading         the leading
095     */
096
097    public Anchor(final float leading) {
098        super(leading);
099    }
100
101    /**
102     * Constructs an <CODE>Anchor</CODE> with a certain <CODE>Chunk</CODE>.
103     *
104     * @param   chunk           a <CODE>Chunk</CODE>
105     */
106    public Anchor(final Chunk chunk) {
107        super(chunk);
108    }
109
110    /**
111     * Constructs an <CODE>Anchor</CODE> with a certain <CODE>String</CODE>.
112     *
113     * @param   string          a <CODE>String</CODE>
114     */
115    public Anchor(final String string) {
116        super(string);
117    }
118
119    /**
120     * Constructs an <CODE>Anchor</CODE> with a certain <CODE>String</CODE>
121     * and a certain <CODE>Font</CODE>.
122     *
123     * @param   string          a <CODE>String</CODE>
124     * @param   font            a <CODE>Font</CODE>
125     */
126    public Anchor(final String string, final Font font) {
127        super(string, font);
128    }
129
130    /**
131     * Constructs an <CODE>Anchor</CODE> with a certain <CODE>Chunk</CODE>
132     * and a certain leading.
133     *
134     * @param   leading         the leading
135     * @param   chunk           a <CODE>Chunk</CODE>
136     */
137    public Anchor(final float leading, final Chunk chunk) {
138        super(leading, chunk);
139    }
140
141    /**
142     * Constructs an <CODE>Anchor</CODE> with a certain leading
143     * and a certain <CODE>String</CODE>.
144     *
145     * @param   leading         the leading
146     * @param   string          a <CODE>String</CODE>
147     */
148    public Anchor(final float leading, final String string) {
149        super(leading, string);
150    }
151
152    /**
153     * Constructs an <CODE>Anchor</CODE> with a certain leading,
154     * a certain <CODE>String</CODE> and a certain <CODE>Font</CODE>.
155     *
156     * @param   leading         the leading
157     * @param   string          a <CODE>String</CODE>
158     * @param   font            a <CODE>Font</CODE>
159     */
160    public Anchor(final float leading, final String string, final Font font) {
161        super(leading, string, font);
162    }
163
164    /**
165     * Constructs an <CODE>Anchor</CODE> with a certain <CODE>Phrase</CODE>.
166     *
167     * @param   phrase          a <CODE>Phrase</CODE>
168     */
169    public Anchor(final Phrase phrase) {
170        super(phrase);
171        if (phrase instanceof Anchor) {
172                Anchor a = (Anchor) phrase;
173                setName(a.name);
174                setReference(a.reference);
175        }
176    }
177
178    // implementation of the Element-methods
179
180    /**
181     * Processes the element by adding it (or the different parts) to an
182     * <CODE>ElementListener</CODE>.
183     *
184     * @param   listener        an <CODE>ElementListener</CODE>
185     * @return  <CODE>true</CODE> if the element was processed successfully
186     */
187    @Override
188    public boolean process(final ElementListener listener) {
189        try {
190            Chunk chunk;
191            Iterator<Chunk> i = getChunks().iterator();
192            boolean localDestination = reference != null && reference.startsWith("#");
193            boolean notGotoOK = true;
194            while (i.hasNext()) {
195                chunk = i.next();
196                if (name != null && notGotoOK && !chunk.isEmpty()) {
197                    chunk.setLocalDestination(name);
198                    notGotoOK = false;
199                }
200                if (localDestination) {
201                    chunk.setLocalGoto(reference.substring(1));
202                }
203                listener.add(chunk);
204            }
205            return true;
206        }
207        catch(DocumentException de) {
208            return false;
209        }
210    }
211
212    /**
213     * Gets all the chunks in this element.
214     *
215     * @return  an <CODE>ArrayList</CODE>
216     */
217    @Override
218    public List<Chunk> getChunks() {
219        List<Chunk> tmp = new ArrayList<Chunk>();
220        Chunk chunk;
221        Iterator<Element> i = iterator();
222        boolean localDestination = reference != null && reference.startsWith("#");
223        boolean notGotoOK = true;
224        while (i.hasNext()) {
225            chunk = (Chunk) i.next();
226            if (name != null && notGotoOK && !chunk.isEmpty()) {
227                chunk.setLocalDestination(name);
228                notGotoOK = false;
229            }
230            if (localDestination) {
231                chunk.setLocalGoto(reference.substring(1));
232            }
233            else if (reference != null)
234                chunk.setAnchor(reference);
235            tmp.add(chunk);
236        }
237        return tmp;
238    }
239
240    /**
241     * Gets the type of the text element.
242     *
243     * @return  a type
244     */
245    @Override
246    public int type() {
247        return Element.ANCHOR;
248    }
249
250    // methods
251
252    /**
253     * Sets the name of this <CODE>Anchor</CODE>.
254     *
255     * @param   name            a new name
256     */
257    public void setName(final String name) {
258        this.name = name;
259    }
260
261    /**
262     * Sets the reference of this <CODE>Anchor</CODE>.
263     *
264     * @param   reference               a new reference
265     */
266    public void setReference(final String reference) {
267        this.reference = reference;
268    }
269
270    // methods to retrieve information
271
272        /**
273     * Returns the name of this <CODE>Anchor</CODE>.
274     *
275     * @return  a name
276     */
277    public String getName() {
278        return name;
279    }
280
281        /**
282     * Gets the reference of this <CODE>Anchor</CODE>.
283     *
284     * @return  a reference
285     */
286    public String getReference() {
287        return reference;
288    }
289
290        /**
291     * Gets the reference of this <CODE>Anchor</CODE>.
292     *
293     * @return  an <CODE>URL</CODE>
294     */
295    public URL getUrl() {
296        try {
297            return new URL(reference);
298        }
299        catch(MalformedURLException mue) {
300            return null;
301        }
302    }
303
304}