1 /* 2 * Copyright (C) 2015, Ivan Motsch <ivan.motsch@bsiag.com>, 3 * Copyright (C) 2017, Obeo (mathieu.cartaud@obeo.fr) 4 * 5 * This program and the accompanying materials are made available 6 * under the terms of the Eclipse Distribution License v1.0 which 7 * accompanies this distribution, is reproduced below, and is 8 * available at http://www.eclipse.org/org/documents/edl-v10.php 9 * 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * - Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials provided 22 * with the distribution. 23 * 24 * - Neither the name of the Eclipse Foundation, Inc. nor the 25 * names of its contributors may be used to endorse or promote 26 * products derived from this software without specific prior 27 * written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 30 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 34 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 38 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 41 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 */ 43 44 package org.eclipse.jgit.attributes; 45 46 import java.util.ArrayList; 47 import java.util.Collection; 48 import java.util.LinkedHashMap; 49 import java.util.Map; 50 51 import org.eclipse.jgit.attributes.Attribute.State; 52 import org.eclipse.jgit.lib.Constants; 53 54 /** 55 * Represents a set of attributes for a path 56 * 57 * @since 4.2 58 */ 59 public final class Attributes { 60 private final Map<String, Attribute> map = new LinkedHashMap<>(); 61 62 /** 63 * Creates a new instance 64 * 65 * @param attributes 66 * a {@link org.eclipse.jgit.attributes.Attribute} 67 */ 68 public Attributes(Attribute... attributes) { 69 if (attributes != null) { 70 for (Attribute a : attributes) { 71 put(a); 72 } 73 } 74 } 75 76 /** 77 * Whether the set of attributes is empty 78 * 79 * @return true if the set does not contain any attributes 80 */ 81 public boolean isEmpty() { 82 return map.isEmpty(); 83 } 84 85 /** 86 * Get the attribute with the given key 87 * 88 * @param key 89 * a {@link java.lang.String} object. 90 * @return the attribute or null 91 */ 92 public Attribute get(String key) { 93 return map.get(key); 94 } 95 96 /** 97 * Get all attributes 98 * 99 * @return all attributes 100 */ 101 public Collection<Attribute> getAll() { 102 return new ArrayList<>(map.values()); 103 } 104 105 /** 106 * Put an attribute 107 * 108 * @param a 109 * an {@link org.eclipse.jgit.attributes.Attribute} 110 */ 111 public void put(Attribute a) { 112 map.put(a.getKey(), a); 113 } 114 115 /** 116 * Remove attribute with given key 117 * 118 * @param key 119 * an attribute name 120 */ 121 public void remove(String key) { 122 map.remove(key); 123 } 124 125 /** 126 * Whether there is an attribute with this key 127 * 128 * @param key 129 * key of an attribute 130 * @return true if the {@link org.eclipse.jgit.attributes.Attributes} 131 * contains this key 132 */ 133 public boolean containsKey(String key) { 134 return map.containsKey(key); 135 } 136 137 /** 138 * Return the state. 139 * 140 * @param key 141 * key of an attribute 142 * @return the state (never returns <code>null</code>) 143 */ 144 public Attribute.State getState(String key) { 145 Attribute a = map.get(key); 146 return a != null ? a.getState() : Attribute.State.UNSPECIFIED; 147 } 148 149 /** 150 * Whether the attribute is set 151 * 152 * @param key 153 * a {@link java.lang.String} object. 154 * @return true if the key is 155 * {@link org.eclipse.jgit.attributes.Attribute.State#SET}, false in 156 * all other cases 157 */ 158 public boolean isSet(String key) { 159 return (getState(key) == State.SET); 160 } 161 162 /** 163 * Whether the attribute is unset 164 * 165 * @param key 166 * a {@link java.lang.String} object. 167 * @return true if the key is 168 * {@link org.eclipse.jgit.attributes.Attribute.State#UNSET}, false 169 * in all other cases 170 */ 171 public boolean isUnset(String key) { 172 return (getState(key) == State.UNSET); 173 } 174 175 /** 176 * Whether the attribute with the given key is unspecified 177 * 178 * @param key 179 * a {@link java.lang.String} object. 180 * @return true if the key is 181 * {@link org.eclipse.jgit.attributes.Attribute.State#UNSPECIFIED}, 182 * false in all other cases 183 */ 184 public boolean isUnspecified(String key) { 185 return (getState(key) == State.UNSPECIFIED); 186 } 187 188 /** 189 * Is this a custom attribute 190 * 191 * @param key 192 * a {@link java.lang.String} object. 193 * @return true if the key is 194 * {@link org.eclipse.jgit.attributes.Attribute.State#CUSTOM}, false 195 * in all other cases see {@link #getValue(String)} for the value of 196 * the key 197 */ 198 public boolean isCustom(String key) { 199 return (getState(key) == State.CUSTOM); 200 } 201 202 /** 203 * Get attribute value 204 * 205 * @param key 206 * an attribute key 207 * @return the attribute value (may be <code>null</code>) 208 */ 209 public String getValue(String key) { 210 Attribute a = map.get(key); 211 return a != null ? a.getValue() : null; 212 } 213 214 /** 215 * Test if the given attributes implies to handle the related entry as a 216 * binary file (i.e. if the entry has an -merge or a merge=binary attribute) 217 * or if it can be content merged. 218 * 219 * @return <code>true</code> if the entry can be content merged, 220 * <code>false</code> otherwise 221 * @since 4.9 222 */ 223 public boolean canBeContentMerged() { 224 if (isUnset(Constants.ATTR_MERGE)) { 225 return false; 226 } else if (isCustom(Constants.ATTR_MERGE) 227 && getValue(Constants.ATTR_MERGE) 228 .equals(Constants.ATTR_BUILTIN_BINARY_MERGER)) { 229 return false; 230 } 231 return true; 232 } 233 234 /** {@inheritDoc} */ 235 @Override 236 public String toString() { 237 StringBuilder buf = new StringBuilder(); 238 buf.append(getClass().getSimpleName()); 239 buf.append("["); //$NON-NLS-1$ 240 buf.append(" "); //$NON-NLS-1$ 241 for (Attribute a : map.values()) { 242 buf.append(a.toString()); 243 buf.append(" "); //$NON-NLS-1$ 244 } 245 buf.append("]"); //$NON-NLS-1$ 246 return buf.toString(); 247 } 248 249 /** {@inheritDoc} */ 250 @Override 251 public int hashCode() { 252 return map.hashCode(); 253 } 254 255 /** {@inheritDoc} */ 256 @Override 257 public boolean equals(Object obj) { 258 if (this == obj) 259 return true; 260 if (!(obj instanceof Attributes)) 261 return false; 262 Attributes other = (Attributes) obj; 263 return this.map.equals(other.map); 264 } 265 266 }