File D:\maven-qcr-plugin-testsunitaires\qcr4java\jenkins-master\target\site\qc\core\src\main\java\hudson\util\DescribableList.java.html

1 /*
2 * The MIT License
3 *
4 * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 package hudson.util;
25
26 import com.thoughtworks.xstream.converters.Converter;
27 import com.thoughtworks.xstream.converters.MarshallingContext;
28 import com.thoughtworks.xstream.converters.UnmarshallingContext;
29 import com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter;
30 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
31 import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
32 import com.thoughtworks.xstream.mapper.Mapper;
33 import hudson.model.AbstractProject;
34 import jenkins.model.DependencyDeclarer;
35 import hudson.model.DependencyGraph;
36 import hudson.model.Describable;
37 import hudson.model.Descriptor;
38 import hudson.model.Descriptor.FormException;
39 import hudson.model.ReconfigurableDescribable;
40 import hudson.model.Saveable;
41 import net.sf.json.JSONObject;
42 import org.kohsuke.stapler.StaplerRequest;
43
44 import java.io.IOException;
45 import java.util.ArrayList;
46 import java.util.Collection;
47 import java.util.List;
48 import java.util.Map;
49
50 /**
51 * Persisted list of {@link Describable}s with some operations specific
52 * to {@link Descriptor}s.
53 *
54 * <p>
55 * This class allows multiple instances of the same descriptor. Some clients
56 * use this semantics, while other clients use it as "up to one instance per
57 * one descriptor" model.
58 *
59 * Some of the methods defined in this class only makes sense in the latter model,
60 * such as {@link #remove(Descriptor)}.
61 *
62 * @author Kohsuke Kawaguchi
63 */
64 public class DescribableList<T extends Describable<T>, D extends Descriptor<T>> extends PersistedList<T> {
65 protected DescribableList() {
66 }
67
68 /**
69 * @deprecated since 2008-08-15.
70 * Use {@link #DescribableList(Saveable)}
71 */
72 public DescribableList(Owner owner) {
73 setOwner(owner);
74 }
75
76 public DescribableList(Saveable owner) {
77 setOwner(owner);
78 }
79
80 public DescribableList(Saveable owner, Collection<? extends T> initialList) {
81 super(initialList);
82 setOwner(owner);
83 }
84
85 /**
86 * @deprecated since 2008-08-15.
87 * Use {@link #setOwner(Saveable)}
88 */
89 public void setOwner(Owner owner) {
90 this.owner = owner;
91 }
92
93 /**
94 * Removes all instances of the same type, then add the new one.
95 */
96 public void replace(T item) throws IOException {
97 removeAll((Class)item.getClass());
98 data.add(item);
99 onModified();
100 }
101
102 /**
103 * Binds items in the collection to URL.
104 */
105 public T getDynamic(String id) {
106 // by ID
107 for (T t : data)
108 if(t.getDescriptor().getId().equals(id))
109 return t;
110
111 // by position
112 try {
113 return data.get(Integer.parseInt(id));
114 } catch (NumberFormatException e) {
115 // fall through
116 }
117
118 return null;
119 }
120
121 public T get(D descriptor) {
122 for (T t : data)
123 if(t.getDescriptor()==descriptor)
124 return t;
125 return null;
126 }
127
128 public boolean contains(D d) {
129 return get(d)!=null;
130 }
131
132 public void remove(D descriptor) throws IOException {
133 for (T t : data) {
134 if(t.getDescriptor()==descriptor) {
135 data.remove(t);
136 onModified();
137 return;
138 }
139 }
140 }
141
142 /**
143 * Creates a detached map from the current snapshot of the data, keyed from a descriptor to an instance.
144 */
145 @SuppressWarnings("unchecked")
146 public Map<D,T> toMap() {
147 return (Map)Descriptor.toMap(data);
148 }
149
150 /**
151 * Rebuilds the list by creating a fresh instances from the submitted form.
152 *
153 * <p>
154 * This method is almost always used by the owner.
155 * This method does not invoke the save method.
156 *
157 * @param json
158 * Structured form data that includes the data for nested descriptor list.
159 */
160 public void rebuild(StaplerRequest req, JSONObject json, List<? extends Descriptor<T>> descriptors) throws FormException, IOException {
161 List<T> newList = new ArrayList<T>();
162
163 for (Descriptor<T> d : descriptors) {
164 T existing = get((D)d);
165 String name = d.getJsonSafeClassName();
166 JSONObject o = json.optJSONObject(name);
167
168 T instance = null;
169 if (o!=null) {
170 if (existing instanceof ReconfigurableDescribable)
171 instance = (T)((ReconfigurableDescribable)existing).reconfigure(req,o);
172 else
173 instance = d.newInstance(req, o);
174 } else {
175 if (existing instanceof ReconfigurableDescribable)
176 instance = (T)((ReconfigurableDescribable)existing).reconfigure(req,null);
177 }
178
179 if (instance!=null)
180 newList.add(instance);
181 }
182
183 replaceBy(newList);
184 }
185
186 /**
187 * @deprecated as of 1.271
188 * Use {@link #rebuild(StaplerRequest, JSONObject, List)} instead.
189 */
190 public void rebuild(StaplerRequest req, JSONObject json, List<? extends Descriptor<T>> descriptors, String prefix) throws FormException, IOException {
191 rebuild(req,json,descriptors);
192 }
193
194 /**
195 * Rebuilds the list by creating a fresh instances from the submitted form.
196 *
197 * <p>
198 * This version works with the the &lt;f:hetero-list> UI tag, where the user
199 * is allowed to create multiple instances of the same descriptor. Order is also
200 * significant.
201 */
202 public void rebuildHetero(StaplerRequest req, JSONObject formData, Collection<? extends Descriptor<T>> descriptors, String key) throws FormException, IOException {
203 replaceBy(Descriptor.newInstancesFromHeteroList(req,formData,key,descriptors));
204 }
205
206 /**
207 * Picks up {@link DependencyDeclarer}s and allow it to build dependencies.
208 */
209 public void buildDependencyGraph(AbstractProject owner,DependencyGraph graph) {
210 for (Object o : this) {
211 if (o instanceof DependencyDeclarer) {
212 DependencyDeclarer dd = (DependencyDeclarer) o;
213 dd.buildDependencyGraph(owner,graph);
214 }
215 }
216 }
217
218 /*
219 The following two seemingly pointless method definitions are necessary to produce
220 backward compatible binary signatures. Without this we only get
221 get(Ljava/lang/Class;)Ljava/lang/Object; from PersistedList where we need
222 get(Ljava/lang/Class;)Lhudson/model/Describable;
223 */
224 public <U extends T> U get(Class<U> type) {
225 return super.get(type);
226 }
227
228 public T[] toArray(T[] array) {
229 return super.toArray(array);
230 }
231
232 /**
233 * @deprecated since 2008-08-15.
234 * Just implement {@link Saveable}.
235 */
236 public interface Owner extends Saveable {
237 }
238
239 /**
240 * {@link Converter} implementation for XStream.
241 *
242 * Serializaion form is compatible with plain {@link List}.
243 */
244 public static class ConverterImpl extends AbstractCollectionConverter {
245 CopyOnWriteList.ConverterImpl copyOnWriteListConverter;
246
247 public ConverterImpl(Mapper mapper) {
248 super(mapper);
249 copyOnWriteListConverter = new CopyOnWriteList.ConverterImpl(mapper());
250 }
251
252 public boolean canConvert(Class type) {
253 // handle subtypes in case the onModified method is overridden.
254 return DescribableList.class.isAssignableFrom(type);
255 }
256
257 public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
258 for (Object o : (DescribableList) source)
259 writeItem(o, context, writer);
260 }
261
262 public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
263 CopyOnWriteList core = copyOnWriteListConverter.unmarshal(reader, context);
264
265 try {
266 DescribableList r = (DescribableList)context.getRequiredType().newInstance();
267 r.data.replaceBy(core);
268 return r;
269 } catch (InstantiationException e) {
270 InstantiationError x = new InstantiationError();
271 x.initCause(e);
272 throw x;
273 } catch (IllegalAccessException e) {
274 IllegalAccessError x = new IllegalAccessError();
275 x.initCause(e);
276 throw x;
277 }
278 }
279 }
280 }
281