View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.css;
16  
17  import java.io.Serializable;
18  import java.util.concurrent.atomic.AtomicLong;
19  
20  import org.htmlunit.cssparser.parser.selector.SelectorSpecificity;
21  
22  /**
23   * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br>
24   *
25   * Contains information about a single style element, including its name, its value, and an index which
26   * can be compared against other indices in order to determine precedence.
27   *
28   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
29   * @author <a href="mailto:cse@dynabean.de">Christian Sell</a>
30   * @author Daniel Gredler
31   * @author Chris Erskine
32   * @author Ahmed Ashour
33   * @author Rodney Gitzel
34   * @author Sudhan Moghe
35   * @author Ronald Brill
36   * @author Frank Danek
37   */
38  public class StyleElement implements Serializable {
39      /** CSS important property constant. */
40      public static final String PRIORITY_IMPORTANT = "important";
41  
42      /** The current style element index. */
43      private static final AtomicLong ELEMENT_INDEX = new AtomicLong();
44  
45      private final String name_;
46      private final String value_;
47      private final String priority_;
48      private final long index_;
49      private final SelectorSpecificity specificity_;
50  
51      /**
52       * Creates a new instance.
53       * @param name the style element's name
54       * @param value the style element's value
55       * @param priority the style element's priority like "important"
56       * @param specificity the specificity of the rule providing this style information
57       * @param index the style element's index
58       */
59      public StyleElement(final String name, final String value, final String priority,
60              final SelectorSpecificity specificity, final long index) {
61          name_ = name;
62          value_ = value;
63          priority_ = priority;
64          specificity_ = specificity;
65          index_ = index;
66      }
67  
68      /**
69       * Creates a new instance.
70       * @param name the style element's name
71       * @param value the style element's value
72       * @param priority the style element's priority like "important"
73       * @param specificity the specificity of the rule providing this style information
74       */
75      public StyleElement(final String name, final String value, final String priority,
76              final SelectorSpecificity specificity) {
77          this(name, value, priority, specificity, ELEMENT_INDEX.incrementAndGet());
78      }
79  
80      /**
81       * Returns the style element's name.
82       * @return the style element's name
83       */
84      public String getName() {
85          return name_;
86      }
87  
88      /**
89       * Returns the style element's value.
90       * @return the style element's value
91       */
92      public String getValue() {
93          return value_;
94      }
95  
96      /**
97       * Returns the style element's priority.
98       * @return the style element's priority
99       */
100     public String getPriority() {
101         return priority_;
102     }
103 
104     /**
105      * @return true if priority is 'important'
106      */
107     public boolean isImportant() {
108         return PRIORITY_IMPORTANT.equals(getPriority());
109     }
110 
111     /**
112      * Returns the specificity of the rule specifying this element.
113      * @return the specificity
114      */
115     public SelectorSpecificity getSpecificity() {
116         return specificity_;
117     }
118 
119     /**
120      * Returns the style element's index.
121      * @return the style element's index
122      */
123     public long getIndex() {
124         return index_;
125     }
126 
127     /**
128      * {@inheritDoc}
129      */
130     @Override
131     public String toString() {
132         return "[" + index_ + "]" + name_  + "=" + value_;
133     }
134 
135     /**
136      * This takes only the importance, the specificity and the index into account.
137      * The name and value properties are ignored.
138      *
139      * @param first the {@link StyleElement} to compare
140      * @param second the {@link StyleElement} to compare with
141      * @return a negative integer, zero, or a positive integer as this object
142      *         is less than, equal to, or greater than the specified object.
143      */
144     public static int compareToByImportanceAndSpecificity(final StyleElement first, final StyleElement second) {
145         if (first == null) {
146             return second == null ? 0 : -1;
147         }
148 
149         if (second == null) {
150             return 1;
151         }
152 
153         if (first == second) {
154             return 0;
155         }
156 
157         if (first.isImportant()) {
158             if (!second.isImportant()) {
159                 return 1;
160             }
161         }
162         else {
163             if (second.isImportant()) {
164                 return -1;
165             }
166         }
167 
168         final int comp = first.getSpecificity().compareTo(second.getSpecificity());
169         if (comp == 0) {
170             return Long.compare(first.getIndex(), second.getIndex());
171         }
172         return comp;
173     }
174 }