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 }