/hudson-core/src/main/java/hudson/util/DescribableList.java
http://github.com/hudson/hudson · Java · 257 lines · 134 code · 27 blank · 96 comment · 9 complexity · b88e385eeede47622a0d1ce6852b9424 MD5 · raw file
- /*
- * The MIT License
- *
- * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
- package hudson.util;
- import com.thoughtworks.xstream.converters.Converter;
- import com.thoughtworks.xstream.converters.MarshallingContext;
- import com.thoughtworks.xstream.converters.UnmarshallingContext;
- import com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter;
- import com.thoughtworks.xstream.io.HierarchicalStreamReader;
- import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
- import com.thoughtworks.xstream.mapper.Mapper;
- import hudson.model.AbstractProject;
- import hudson.model.DependecyDeclarer;
- import hudson.model.DependencyGraph;
- import hudson.model.Describable;
- import hudson.model.Descriptor;
- import hudson.model.Descriptor.FormException;
- import hudson.model.Saveable;
- import net.sf.json.JSONObject;
- import org.kohsuke.stapler.StaplerRequest;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.List;
- import java.util.Map;
- /**
- * Persisted list of {@link Describable}s with some operations specific
- * to {@link Descriptor}s.
- *
- * <p>
- * This class allows multiple instances of the same descriptor. Some clients
- * use this semantics, while other clients use it as "up to one instance per
- * one descriptor" model.
- *
- * Some of the methods defined in this class only makes sense in the latter model,
- * such as {@link #remove(Descriptor)}.
- *
- * @author Kohsuke Kawaguchi
- */
- public class DescribableList<T extends Describable<T>, D extends Descriptor<T>> extends PersistedList<T> {
- protected DescribableList() {
- }
- /**
- * @deprecated since 2008-08-15.
- * Use {@link #DescribableList(Saveable)}
- */
- public DescribableList(Owner owner) {
- setOwner(owner);
- }
- public DescribableList(Saveable owner) {
- setOwner(owner);
- }
- public DescribableList(Saveable owner, Collection<? extends T> initialList) {
- super(initialList);
- setOwner(owner);
- }
- /**
- * @deprecated since 2008-08-15.
- * Use {@link #setOwner(Saveable)}
- */
- public void setOwner(Owner owner) {
- this.owner = owner;
- }
- /**
- * Removes all instances of the same type, then add the new one.
- */
- public void replace(T item) throws IOException {
- removeAll((Class)item.getClass());
- data.add(item);
- onModified();
- }
- public T get(D descriptor) {
- for (T t : data)
- if(t.getDescriptor()==descriptor)
- return t;
- return null;
- }
- public boolean contains(D d) {
- return get(d)!=null;
- }
- public void remove(D descriptor) throws IOException {
- for (T t : data) {
- if(t.getDescriptor()==descriptor) {
- data.remove(t);
- onModified();
- return;
- }
- }
- }
- /**
- * Creates a detached map from the current snapshot of the data, keyed from a descriptor to an instance.
- */
- @SuppressWarnings("unchecked")
- public Map<D,T> toMap() {
- return (Map)Descriptor.toMap(data);
- }
- /**
- * Rebuilds the list by creating a fresh instances from the submitted form.
- * <p/>
- * <p/>
- * This method is almost always used by the owner.
- * This method does not invoke the save method.
- *
- * @param json Structured form data that includes the data for nested descriptor list.
- * @deprecated as of 2.2.0,
- * use {@link DescribableListUtil#buildFromJson(hudson.model.Saveable, org.kohsuke.stapler.StaplerRequest, net.sf.json.JSONObject, java.util.List)}
- */
- public void rebuild(StaplerRequest req, JSONObject json, List<? extends Descriptor<T>> descriptors)
- throws FormException, IOException {
- List<T> newList = new ArrayList<T>();
- for (Descriptor<T> d : descriptors) {
- String name = d.getJsonSafeClassName();
- if (json.has(name)) {
- T instance = d.newInstance(req, json.getJSONObject(name));
- newList.add(instance);
- }
- }
- replaceBy(newList);
- }
- /**
- * @deprecated as of 1.271
- * Use {@link #rebuild(StaplerRequest, JSONObject, List)} instead.
- */
- public void rebuild(StaplerRequest req, JSONObject json, List<? extends Descriptor<T>> descriptors, String prefix) throws FormException, IOException {
- rebuild(req,json,descriptors);
- }
- /**
- * Rebuilds the list by creating a fresh instances from the submitted form.
- * <p/>
- * This version works with the the <f:hetero-list> UI tag, where the user
- * is allowed to create multiple instances of the same descriptor. Order is also
- * significant.
- *
- * @deprecated as of 2.2.0,
- * use {@link DescribableListUtil#buildFromHetero(hudson.model.Saveable, org.kohsuke.stapler.StaplerRequest, net.sf.json.JSONObject, String, java.util.Collection)}
- * or {@link Descriptor#newInstancesFromHeteroList(org.kohsuke.stapler.StaplerRequest, net.sf.json.JSONObject, String, java.util.Collection)}
- */
- public void rebuildHetero(StaplerRequest req,
- JSONObject formData,
- Collection<? extends Descriptor<T>> descriptors,
- String key)
- throws FormException, IOException {
- replaceBy(Descriptor.newInstancesFromHeteroList(req, formData, key, descriptors));
- }
- /**
- * Picks up {@link DependecyDeclarer}s and allow it to build dependencies.
- */
- public void buildDependencyGraph(AbstractProject owner,DependencyGraph graph) {
- for (Object o : this) {
- if (o instanceof DependecyDeclarer) {
- DependecyDeclarer dd = (DependecyDeclarer) o;
- dd.buildDependencyGraph(owner,graph);
- }
- }
- }
- /*
- The following two seemingly pointless method definitions are necessary to produce
- backward compatible binary signatures. Without this we only get
- get(Ljava/lang/Class;)Ljava/lang/Object; from PersistedList where we need
- get(Ljava/lang/Class;)Lhudson/model/Describable;
- */
- public <U extends T> U get(Class<U> type) {
- return super.get(type);
- }
- public T[] toArray(T[] array) {
- return super.toArray(array);
- }
- /**
- * @deprecated since 2008-08-15.
- * Just implement {@link Saveable}.
- */
- public interface Owner extends Saveable {
- }
- /**
- * {@link Converter} implementation for XStream.
- *
- * Serializaion form is compatible with plain {@link List}.
- */
- public static class ConverterImpl extends AbstractCollectionConverter {
- CopyOnWriteList.ConverterImpl copyOnWriteListConverter;
- public ConverterImpl(Mapper mapper) {
- super(mapper);
- copyOnWriteListConverter = new CopyOnWriteList.ConverterImpl(mapper());
- }
- public boolean canConvert(Class type) {
- // handle subtypes in case the onModified method is overridden.
- return DescribableList.class.isAssignableFrom(type);
- }
- public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
- for (Object o : (DescribableList) source)
- writeItem(o, context, writer);
- }
- public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
- CopyOnWriteList core = copyOnWriteListConverter.unmarshal(reader, context);
- try {
- DescribableList r = (DescribableList)context.getRequiredType().newInstance();
- r.data.replaceBy(core);
- return r;
- } catch (InstantiationException e) {
- InstantiationError x = new InstantiationError();
- x.initCause(e);
- throw x;
- } catch (IllegalAccessException e) {
- IllegalAccessError x = new IllegalAccessError();
- x.initCause(e);
- throw x;
- }
- }
- }
- }