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 * <p>
57 *
58 * @since 4.2
59 */
60 public final class Attributes {
61 private final Map<String, Attribute> map = new LinkedHashMap<>();
62
63 /**
64 * Creates a new instance
65 *
66 * @param attributes
67 */
68 public Attributes(Attribute... attributes) {
69 if (attributes != null) {
70 for (Attribute a : attributes) {
71 put(a);
72 }
73 }
74 }
75
76 /**
77 * @return true if the set does not contain any attributes
78 */
79 public boolean isEmpty() {
80 return map.isEmpty();
81 }
82
83 /**
84 * @param key
85 * @return the attribute or null
86 */
87 public Attribute get(String key) {
88 return map.get(key);
89 }
90
91 /**
92 * @return all attributes
93 */
94 public Collection<Attribute> getAll() {
95 return new ArrayList<>(map.values());
96 }
97
98 /**
99 * @param a
100 */
101 public void put(Attribute a) {
102 map.put(a.getKey(), a);
103 }
104
105 /**
106 * @param key
107 */
108 public void remove(String key) {
109 map.remove(key);
110 }
111
112 /**
113 * @param key
114 * @return true if the {@link Attributes} contains this key
115 */
116 public boolean containsKey(String key) {
117 return map.containsKey(key);
118 }
119
120 /**
121 * Returns the state.
122 *
123 * @param key
124 *
125 * @return the state (never returns <code>null</code>)
126 */
127 public Attribute.State getState(String key) {
128 Attribute a = map.get(key);
129 return a != null ? a.getState() : Attribute.State.UNSPECIFIED;
130 }
131
132 /**
133 * @param key
134 * @return true if the key is {@link State#SET}, false in all other cases
135 */
136 public boolean isSet(String key) {
137 return (getState(key) == State.SET);
138 }
139
140 /**
141 * @param key
142 * @return true if the key is {@link State#UNSET}, false in all other cases
143 */
144 public boolean isUnset(String key) {
145 return (getState(key) == State.UNSET);
146 }
147
148 /**
149 * @param key
150 * @return true if the key is {@link State#UNSPECIFIED}, false in all other
151 * cases
152 */
153 public boolean isUnspecified(String key) {
154 return (getState(key) == State.UNSPECIFIED);
155 }
156
157 /**
158 * @param key
159 * @return true if the key is {@link State#CUSTOM}, false in all other cases
160 * see {@link #getValue(String)} for the value of the key
161 */
162 public boolean isCustom(String key) {
163 return (getState(key) == State.CUSTOM);
164 }
165
166 /**
167 * @param key
168 * @return the attribute value (may be <code>null</code>)
169 */
170 public String getValue(String key) {
171 Attribute a = map.get(key);
172 return a != null ? a.getValue() : null;
173 }
174
175 /**
176 * Test if the given attributes implies to handle the related entry as a
177 * binary file (i.e. if the entry has an -merge or a merge=binary attribute)
178 * or if it can be content merged.
179 *
180 * @return <code>true</code> if the entry can be content merged,
181 * <code>false</code> otherwise
182 * @since 4.9
183 */
184 public boolean canBeContentMerged() {
185 if (isUnset(Constants.ATTR_MERGE)) {
186 return false;
187 } else if (isCustom(Constants.ATTR_MERGE)
188 && getValue(Constants.ATTR_MERGE)
189 .equals(Constants.ATTR_BUILTIN_BINARY_MERGER)) {
190 return false;
191 }
192 return true;
193 }
194
195 @Override
196 public String toString() {
197 StringBuilder buf = new StringBuilder();
198 buf.append(getClass().getSimpleName());
199 buf.append("["); //$NON-NLS-1$
200 buf.append(" "); //$NON-NLS-1$
201 for (Attribute a : map.values()) {
202 buf.append(a.toString());
203 buf.append(" "); //$NON-NLS-1$
204 }
205 buf.append("]"); //$NON-NLS-1$
206 return buf.toString();
207 }
208
209 @Override
210 public int hashCode() {
211 return map.hashCode();
212 }
213
214 @Override
215 public boolean equals(Object obj) {
216 if (this == obj)
217 return true;
218 if (!(obj instanceof Attributes))
219 return false;
220 Attributes other = (Attributes) obj;
221 return this.map.equals(other.map);
222 }
223
224 }