OSDN Git Service

93f031c5bc5e011921e33c4510d137de1cc7acbf
[dvibrowser/dvi2epub.git] / src / jp / sourceforge / dvibrowser / dvicore / special / HtmlSpecialParser.java
1 /*
2  * Copyright (c) 2009, Takeyuki Nagao
3  * All rights reserved.
4  * 
5  * Redistribution and use in source and binary forms, with or
6  * without modification, are permitted provided that the
7  * following conditions are met:
8  * 
9  *  * Redistributions of source code must retain the above
10  *    copyright notice, this list of conditions and the
11  *    following disclaimer.
12  *  * Redistributions in binary form must reproduce the above
13  *    copyright notice, this list of conditions and the
14  *    following disclaimer in the documentation and/or other
15  *    materials provided with the distribution.
16  *    
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
18  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
29  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
30  * OF SUCH DAMAGE.
31  */
32
33 package jp.sourceforge.dvibrowser.dvicore.special;
34
35 import java.util.Stack;
36 import java.util.regex.Matcher;
37 import java.util.regex.Pattern;
38
39 import jp.sourceforge.dvibrowser.dvicore.DviException;
40 import jp.sourceforge.dvibrowser.dvicore.DviObject;
41 import jp.sourceforge.dvibrowser.dvicore.api.DviContextSupport;
42 import jp.sourceforge.dvibrowser.dvicore.api.DviDocument;
43
44
45 // TODO: support Logging
46 public class HtmlSpecialParser
47 extends DviObject
48 {
49   private final AnchorSet anchorSet = new AnchorSet();
50   private final PrivateExecuter exe;
51
52   public HtmlSpecialParser(DviContextSupport dcs)
53   {
54     super(dcs);
55     exe = new PrivateExecuter(dcs, anchorSet);
56   }
57
58   private static final Pattern hrefPat
59     = Pattern.compile(
60       "\\s*html:\\s*<a\\s*href\\s*=\\s*\"(.*)\"\\s*>",
61       Pattern.CASE_INSENSITIVE
62     );
63   private static final Pattern namePat
64     = Pattern.compile(
65       "\\s*html:\\s*<a\\s*name\\s*=\\s*\"(.*)\"\\s*>",
66       Pattern.CASE_INSENSITIVE
67     );
68   private static final Pattern endPat
69     = Pattern.compile(
70       "\\s*html:\\s*</a>",
71       Pattern.CASE_INSENSITIVE
72     );
73   
74   public void execute(DviDocument doc)
75   throws DviException
76   {
77     for (int p=0; p<doc.getTotalPages(); p++) {
78       exe.execute(doc.getPage(p));
79     }
80   }
81
82   public AnchorSet getAnchorSet()
83   {
84     return anchorSet;
85   }
86
87   private static class PrivateExecuter
88   extends AbstractDviSpecialExecutor
89   {
90     private final AnchorSet anchorSet;
91     public PrivateExecuter(DviContextSupport dcs, AnchorSet anchorSet) {
92       super(dcs);
93       this.anchorSet = anchorSet;
94     }
95
96     private static class StackItem
97     {
98       private final long start;
99       private final String tag;
100       private final String data;
101       public StackItem(long start, String tag, String data) {
102         this.start = start;
103         this.tag = tag;
104         this.data = data;
105       }
106     }
107
108     private final Stack<StackItem> stack
109       = new Stack<StackItem>();
110
111     public void doSpecial(byte [] _xxx)
112     throws DviException
113     {
114       String xxx = new String(_xxx);
115       Matcher mat;
116       DviExecutorContextImpl ctx = getExecutorContext();
117       if ((mat = hrefPat.matcher(xxx)).matches()) {
118         stack.push(
119           new StackItem(
120             ctx.getCommandRange().begin(),
121             "href",
122             mat.group(1)
123           )
124         );
125       } else if ((mat = namePat.matcher(xxx)).matches()) {
126         stack.push(
127           new StackItem(
128             ctx.getCommandRange().begin(),
129             "name",
130             mat.group(1)
131           )
132         );
133       } else if ((mat = endPat.matcher(xxx)).matches()) {
134         Anchor el = null;
135         if (!stack.empty()) {
136           StackItem it = stack.pop();
137           if ("href".equals(it.tag)) {
138             el = new Anchor.Href(
139               it.start,
140               ctx.getCommandRange().end(),
141               it.data
142             );
143           } else if ("name".equals(it.tag)) {
144             el = new Anchor.Name(
145               it.start,
146               ctx.getCommandRange().end(),
147               it.data
148             );
149           }
150         } else {
151           // TODO: logging
152 //          System.out.println("html tag stack underflow.");
153           // This is an error.  We ignore it.
154         }
155         if (el != null) {
156           anchorSet.add(el);
157         }
158       }
159     }
160   }
161 }