001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 * 
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 * 
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.launcher.types;
019
020import java.util.ArrayList;
021import java.util.Stack;
022import org.apache.commons.launcher.Launcher;
023import org.apache.tools.ant.BuildException;
024import org.apache.tools.ant.types.DataType;
025import org.apache.tools.ant.types.Reference;
026
027/**
028 * A class that represents a set of nested elements of
029 * {@link ConditionalArgument} objects.
030 *
031 * @author Patrick Luby
032 */
033public class ConditionalArgumentSet extends DataType {
034
035    //------------------------------------------------------------------ Fields
036
037    /**
038     * Cached arguments and nested ConditionalArgumentSet objects
039     */
040    private ArrayList list = new ArrayList();
041
042    //----------------------------------------------------------------- Methods
043
044    /**
045     * Add a {@link ConditionalArgument}.
046     *
047     * @param argument the {@link ConditionalArgument} to be
048     *  added
049     */
050    protected void addConditionalargument(ConditionalArgument argument) {
051
052        if (isReference())
053            throw noChildrenAllowed();
054        list.add(argument);
055
056    }
057
058    /**
059     * Add a {@link ConditionalArgumentSet}.
060     *
061     * @param set the {@link ConditionalArgumentSet} to be added
062     */
063    protected void addConditionalargumentset(ConditionalArgumentSet set) {
064
065        if (isReference())
066            throw noChildrenAllowed();
067        list.add(set);
068
069    }
070
071    /**
072     * Get {@link ConditionalArgument} instances.
073     *
074     * @return the {@link ConditionalArgument} instances
075     */
076    public ArrayList getList() {
077
078        // Make sure we don't have a circular reference to this instance
079        if (!checked) {
080            Stack stk = new Stack();
081            stk.push(this);
082            dieOnCircularReference(stk, project);
083        }
084
085        // Recursively work through the tree of ConditionalArgumentSet objects
086        // and accumulate the list of ConditionalArgument objects.
087        ArrayList mergedList = new ArrayList(list.size());
088        for (int i = 0; i < list.size(); i++) {
089            Object o = list.get(i);
090            ConditionalArgumentSet nestedSet = null;
091            if (o instanceof Reference) {
092                o = ((Reference)o).getReferencedObject(project);
093                // Only references to this class are allowed
094                if (!o.getClass().isInstance(this))
095                    throw new BuildException(Launcher.getLocalizedString("cannot.reference", this.getClass().getName()));
096                nestedSet = (ConditionalArgumentSet)o;
097            } else if (o.getClass().isInstance(this)) {
098                nestedSet = (ConditionalArgumentSet)o;
099            } else if (o instanceof ConditionalArgument) {
100                mergedList.add(o);
101            } else {
102                throw new BuildException(Launcher.getLocalizedString("cannot.nest", this.getClass().getName()));
103            }
104            if (nestedSet != null)
105                mergedList.addAll(nestedSet.getList());
106        }
107
108        return mergedList;
109
110    }
111
112    /**
113     * Makes this instance a reference to another instance. You must not
114     * set another attribute or nest elements inside this element if you
115     * make it a reference.
116     *
117     * @param r the reference to another {@link ConditionalArgumentSet}
118     *  instance
119     */
120    public void setRefid(Reference r) throws BuildException {
121
122        if (!list.isEmpty())
123            throw tooManyAttributes();
124        list.add(r);
125        super.setRefid(r);
126
127    }
128
129}