OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [javax/] [swing/] [text/] [html/] [css/] [Selector.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* Selector.java -- A CSS selector
2
   Copyright (C) 2006 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package gnu.javax.swing.text.html.css;
40
 
41
import gnu.java.lang.CPStringBuilder;
42
 
43
import java.util.List;
44
import java.util.Map;
45
import java.util.StringTokenizer;
46
 
47
/**
48
 * A CSS selector. This provides methods to interpret a selector and
49
 * query matches with an actual HTML element tree.
50
 */
51
public class Selector
52
{
53
 
54
  /**
55
   * The actual selector. The selector tokens are stored backwards, that
56
   * is the last token first. This makes matching easier.
57
   */
58
  private String[] selector;
59
 
60
  private String[] elements;
61
  private String[] ids;
62
  private String[] classes;
63
 
64
  /**
65
   * The specificity of the selector.
66
   */
67
  private int specificity;
68
 
69
  /**
70
   * An implicit selector has true here. This is the case for CSS rules that
71
   * are attached to HTML elements directly via style="<CSS rule>".
72
   */
73
  private boolean implicit;
74
 
75
  /**
76
   * Creates a new Selector instance for the specified selector string.
77
   *
78
   * @param sel the selector
79
   */
80
  public Selector(String sel)
81
  {
82
    StringTokenizer selectorTokens = new StringTokenizer(sel, " ");
83
    selector = new String[selectorTokens.countTokens()];
84
    for (int i = selector.length - 1; selectorTokens.hasMoreTokens(); i--)
85
      {
86
        selector[i] = selectorTokens.nextToken();
87
      }
88
    calculateSpecificity();
89
  }
90
 
91
  /**
92
   * Determines if this selector matches the element path specified in the
93
   * arguments. The arguments hold the element names as well as class
94
   * and id attibutes of the HTML element to be queried. The first item
95
   * in the array is the deepest element and the last on the highest up (for
96
   * instance, the html tag).
97
   *
98
   * @param tags
99
   *
100
   * @return <code>true</code> when this selector matches the element path,
101
   *         <code>false</code> otherwise
102
   */
103
  public boolean matches(String[] tags, List<Map<String,String>> attributes)
104
  {
105
    // TODO: This implements class, id and descendent matching. These are
106
    // the most commonly used selector matchers in CSS together with HTML.
107
    // However, the CSS spec defines a couple of more sophisticated matches
108
    // which should be implemented.
109
    // http://www.w3.org/TR/CSS21/selector.html
110
 
111
    // All parts of the selector must match at some point.
112
    boolean match = false;
113
    int numTags = tags.length;
114
    int numSel = selector.length;
115
    if (numSel <= numTags)
116
      {
117
        match = true;
118
        int tagIndex = 0;
119
        for (int j = 0; j < numSel && match; j++)
120
          {
121
            boolean tagMatch = false;
122
            for (; tagIndex < numTags && tagMatch == false; tagIndex++)
123
              {
124
                Object pathClass = attributes.get(tagIndex).get("class");
125
                // Try pseudo class too.
126
                Object pseudoClass = attributes.get(tagIndex).get("_pseudo");
127
                Object dynClass = attributes.get(tagIndex).get("_dynamic");
128
                Object pathId = attributes.get(tagIndex).get("id");
129
                String tag = elements[j];
130
                String clazz = classes[j];
131
                String id = ids[j];
132
                tagMatch = tag.equals("") || tag.equals("*")
133
                           || tag.equals(tags[tagIndex]);
134
                tagMatch = tagMatch && (clazz.equals("*")
135
                                        || clazz.equals(dynClass)
136
                                        || clazz.equals(pseudoClass)
137
                                        || clazz.equals(pathClass));
138
                tagMatch = tagMatch && (id.equals("*")
139
                                        || id.equals(pathId));
140
                // For the last element in the selector we must not look
141
                // further.
142
                if (j == 0)
143
                  break;
144
              }
145
            // If we don't come out here with a matching tag, then we're
146
            // not matching at all.
147
            match = tagMatch;
148
          }
149
      }
150
    return match;
151
  }
152
 
153
  /**
154
   * Returns the specificity of the selector. This is calculated according
155
   * to:
156
   * http://www.w3.org/TR/CSS21/cascade.html#specificity
157
   *
158
   * @return the specificity of the selector
159
   */
160
  public int getSpecificity()
161
  {
162
    return specificity;
163
  }
164
 
165
  /**
166
   * Returns a string representation of the selector. This tries to reconstruct
167
   * the original selector as closely as possible.
168
   *
169
   * @return a string representation of the selector
170
   */
171
  public String toString()
172
  {
173
    CPStringBuilder b = new CPStringBuilder();
174
    for (int i = selector.length - 1; i >= 0; i--)
175
      {
176
        b.append(selector[i]);
177
        if (i > 0)
178
          b.append(' ');
179
      }
180
    return b.toString();
181
  }
182
 
183
  /**
184
   * Calculates the specificity of the selector. This is calculated according
185
   * to:
186
   * http://www.w3.org/TR/CSS21/cascade.html#specificity
187
   */
188
  private void calculateSpecificity()
189
  {
190
    int a = implicit ? 1 : 0;
191
    int b = 0;
192
    int c = 0;
193
    int d = 0;
194
    int numSel = selector.length;
195
    elements = new String[numSel];
196
    ids = new String[numSel];
197
    classes = new String[numSel];
198
    for (int i = 0; i < numSel; i++)
199
      {
200
        String sel = selector[i];
201
        int clazzIndex = sel.indexOf('.');
202
        // Try pseudo class too.
203
        if (clazzIndex == -1)
204
          clazzIndex = sel.indexOf(':');
205
        int idIndex = sel.indexOf('#');
206
        String clazz;
207
        if (clazzIndex == -1)
208
          {
209
            clazz = "*";
210
            clazzIndex = sel.length();
211
          }
212
        else
213
          {
214
            c++;
215
            clazz = sel.substring(clazzIndex + 1,
216
                                  idIndex > 0 ? Math.min(idIndex, sel.length())
217
                                                         : sel.length());
218
          }
219
        String id;
220
        if (idIndex == -1)
221
          {
222
            id = "*";
223
            idIndex = sel.length();
224
          }
225
        else
226
          {
227
            b++;
228
            id = sel.substring(idIndex + 1,
229
                               clazzIndex > 0 ? Math.min(clazzIndex, sel.length())
230
                                              : sel.length());
231
          }
232
        String tag = sel.substring(0,
233
                                   Math.min(Math.min(clazzIndex, idIndex),
234
                                            sel.length()));
235
        if (! tag.equals("") && ! tag.equals("*"))
236
          d++;
237
 
238
        elements[i] = tag;
239
        ids[i] = id;
240
        classes[i] = clazz;
241
      }
242
    // An order of 20 should be enough for everybody.
243
    specificity = a * 20 ^ 3 + b * 20 ^ 2 + c * 20 + d;
244
  }
245
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.