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 Mike Bowler
29 * @author Christian Sell
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 }