001    /*
002     * JBoss DNA (http://www.jboss.org/dna)
003     * See the COPYRIGHT.txt file distributed with this work for information
004     * regarding copyright ownership.  Some portions may be licensed
005     * to Red Hat, Inc. under one or more contributor license agreements.
006     * See the AUTHORS.txt file in the distribution for a full listing of 
007     * individual contributors. 
008     *
009     * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
010     * is licensed to you under the terms of the GNU Lesser General Public License as
011     * published by the Free Software Foundation; either version 2.1 of
012     * the License, or (at your option) any later version.
013     *
014     * JBoss DNA is distributed in the hope that it will be useful,
015     * but WITHOUT ANY WARRANTY; without even the implied warranty of
016     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017     * Lesser General Public License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this software; if not, write to the Free
021     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
022     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
023     */
024    package org.jboss.dna.graph.property.basic;
025    
026    import java.util.ArrayList;
027    import java.util.Collection;
028    import java.util.Iterator;
029    import java.util.List;
030    import org.jboss.dna.common.util.CheckArg;
031    import org.jboss.dna.graph.property.Name;
032    import org.jboss.dna.graph.property.Property;
033    import org.jboss.dna.graph.property.PropertyFactory;
034    import org.jboss.dna.graph.property.PropertyType;
035    import org.jboss.dna.graph.property.ValueFactories;
036    import org.jboss.dna.graph.property.ValueFactory;
037    
038    /**
039     * @author Randall Hauch
040     */
041    public class BasicPropertyFactory implements PropertyFactory {
042    
043        private final ValueFactories factories;
044    
045        /**
046         * @param valueFactories the value factories
047         * @throws IllegalArgumentException if the reference to the value factories is null
048         */
049        public BasicPropertyFactory( ValueFactories valueFactories ) {
050            CheckArg.isNotNull(valueFactories, "value factories");
051            this.factories = valueFactories;
052        }
053    
054        /**
055         * {@inheritDoc}
056         */
057        public Property create( Name name,
058                                Iterable<?> values ) {
059            return create(name, PropertyType.OBJECT, values);
060        }
061    
062        /**
063         * {@inheritDoc}
064         */
065        public Property create( Name name,
066                                Iterator<?> values ) {
067            return create(name, PropertyType.OBJECT, values);
068        }
069    
070        /**
071         * {@inheritDoc}
072         */
073        public Property create( Name name,
074                                Object... values ) {
075            return create(name, PropertyType.OBJECT, values);
076        }
077    
078        /**
079         * {@inheritDoc}
080         */
081        public Property create( Name name,
082                                PropertyType desiredType,
083                                Object... values ) {
084            CheckArg.isNotNull(name, "name");
085            if (values == null || values.length == 0) {
086                return new BasicEmptyProperty(name);
087            }
088            final int len = values.length;
089            if (desiredType == null) desiredType = PropertyType.OBJECT;
090            final ValueFactory<?> factory = factories.getValueFactory(desiredType);
091            if (values.length == 1) {
092                Object value = values[0];
093                // Check whether the sole value was a collection ...
094                if (value instanceof Collection) {
095                    // The single value is a collection, so create property with the collection's contents ...
096                    return create(name, (Collection<?>)value);
097                }
098                value = factory.create(values[0]);
099                return new BasicSingleValueProperty(name, value);
100            }
101            List<Object> valueList = new ArrayList<Object>(len);
102            for (int i = 0; i != len; ++i) {
103                Object value = factory.create(values[i]);
104                valueList.add(value);
105            }
106            return new BasicMultiValueProperty(name, valueList);
107        }
108    
109        /**
110         * {@inheritDoc}
111         */
112        @SuppressWarnings( "unchecked" )
113        public Property create( Name name,
114                                PropertyType desiredType,
115                                Iterable<?> values ) {
116            CheckArg.isNotNull(name, "name");
117            List<Object> valueList = null;
118            if (values instanceof Collection) {
119                Collection<Object> originalValues = (Collection<Object>)values;
120                if (originalValues.isEmpty()) {
121                    return new BasicEmptyProperty(name);
122                }
123                valueList = new ArrayList<Object>(originalValues.size());
124            } else {
125                // We don't know the size
126                valueList = new ArrayList<Object>();
127            }
128            // Copy the values, ensuring that the values are the correct type ...
129            if (desiredType == null) desiredType = PropertyType.OBJECT;
130            final ValueFactory<?> factory = factories.getValueFactory(desiredType);
131            for (Object value : values) {
132                valueList.add(factory.create(value));
133            }
134            if (valueList.isEmpty()) { // may not have been a collection earlier
135                return new BasicEmptyProperty(name);
136            }
137            if (valueList.size() == 1) {
138                return new BasicSingleValueProperty(name, valueList.get(0));
139            }
140            return new BasicMultiValueProperty(name, valueList);
141        }
142    
143        /**
144         * {@inheritDoc}
145         */
146        public Property create( Name name,
147                                PropertyType desiredType,
148                                Iterator<?> values ) {
149            CheckArg.isNotNull(name, "name");
150            final List<Object> valueList = new ArrayList<Object>();
151            if (desiredType == null) desiredType = PropertyType.OBJECT;
152            final ValueFactory<?> factory = factories.getValueFactory(desiredType);
153            while (values.hasNext()) {
154                Object value = values.next();
155                value = factory.create(value);
156                valueList.add(value);
157            }
158            if (valueList.isEmpty()) {
159                return new BasicEmptyProperty(name);
160            }
161            if (valueList.size() == 1) {
162                return new BasicSingleValueProperty(name, valueList.get(0));
163            }
164            return new BasicMultiValueProperty(name, valueList);
165        }
166    
167    }