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 }