001/* 
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.felix.ipojo.architecture;
020
021import org.apache.felix.ipojo.ConfigurationException;
022import org.apache.felix.ipojo.handlers.configuration.ConfigurationHandler;
023import org.apache.felix.ipojo.util.Property;
024import org.osgi.framework.BundleContext;
025
026/**
027 * Property Information.
028 * 
029 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
030 */
031public class PropertyDescription {
032
033    /**
034     * Name of the property.
035     */
036    private String m_name;
037
038    /**
039     * Type of the property.
040     */
041    private String m_type;
042
043    /**
044     * Value of the property.
045     */
046    private String m_value = null;
047    
048    /**
049     * Attached property object.
050     */
051    private Property m_property;
052    
053    
054    /**
055     * Immutable property flag
056     * If set to <code>true</code>, the property cannot be override by the instance configuration.
057     * Moreover, immutable properties are exposed on the factory service too.
058     */
059    private boolean m_immutable = false;
060    
061    /**
062     * A property is mandatory. So, either the component type description provides a value or
063     * the instance configuration must provide a value. Immutable properties are mandatories. 
064     */
065    private boolean m_isMandatory = false;
066
067    /**
068     * Constructor.
069     * 
070     * @param name the name of the property
071     * @param type the type of the property
072     * @param value the default value of the property, can be <code>null</code>
073     */
074    public PropertyDescription(String name, String type, String value) {
075        m_name = name;
076        m_type = type;
077        m_value = value;
078    }
079    
080    /**
081     * Constructor.
082     * 
083     * @param prop the attache Property object.
084     */
085    public PropertyDescription(Property prop) {
086        m_property = prop;
087        m_name = prop.getName();
088        m_type = prop.getType();
089        m_value = null; // Living property, value will be asked at runtime.
090    }
091    
092    /**
093     * Constructor.
094     * 
095     * @param name the name of the property
096     * @param type the type of the property
097     * @param value the default value (String form) of the property, can be <code>null</code>
098     * @param immutable the property is immutable.
099     */
100    public PropertyDescription(String name, String type, String value, boolean immutable) {
101        m_name = name;
102        m_type = type;
103        m_value = value;
104        m_immutable = immutable;
105    }
106
107    /**
108     * Gets the current property name.
109     * @return the property name.
110     */
111    public String getName() {
112        return m_name;
113    }
114
115    /**
116     * Gets the current property type.
117     * @return the property type.
118     */
119    public String getType() {
120        return m_type;
121    }
122
123    /**
124     * Gets the current property value.
125     * @return the default value for the property,
126     * <code>null</code> if the property hasn't a value..
127     */
128    public String getValue() {
129        if (m_property == null) {
130            return m_value;
131        } else {
132            Object value =  m_property.getValue();
133            if (value == null) {
134                return "null";
135            } else if (value == Property.NO_VALUE) {
136                return Property.UNVALUED;
137            } else {
138                return value.toString();
139            }
140        }
141    }
142    
143    /**
144     * Sets the property value.
145     * This method can only be called on 'living' property
146     * (properties with a {@link Property} object).
147     * @param value the new value.
148     */
149    public void setValue(Object value) {
150        if (m_property == null) {
151            throw new UnsupportedOperationException("Cannot set the value of a non 'living' property");
152        } else {
153            ConfigurationHandler handler = (ConfigurationHandler) m_property.getHandler();
154            handler.reconfigureProperty(m_property, value);
155        }
156    }
157    
158    /**
159     * Is the property immutable.
160     * @return <code>true</code> if the property is immutable.
161     */
162    public boolean isImmutable() {
163        return m_immutable;
164    }
165    
166    /**
167     * Sets the property as mandatory.
168     */
169    public void setMandatory() {
170        m_isMandatory = true;
171    }
172    
173    /**
174     * Is the property mandatory.
175     * @return <code>true</code> if the property is mandatory,
176     * <code>false</code> otherwise.
177     */
178    public boolean isMandatory() {
179        return m_isMandatory;
180    }
181    
182    /**
183     * Gets the object value of the current immutable property.
184     * @param context  the bundle context to use to load classes.
185     * @return the object value of the current property or <code>
186     * null</code> if the current value is <code>null</code>.
187     */
188    public Object getObjectValue(BundleContext context) {
189        if (m_value == null) {
190            return null;
191        }
192
193        Class type = null;
194        try {
195            type = Property.computeType(m_type, context);
196            return Property.create(type, m_value);
197        } catch (ConfigurationException e) {
198            return m_value; // Cannot create the object.
199        }
200    }
201
202    /**
203     * Gets the current value of the property as object.
204     * @return the current value
205     * @since 1.11.1
206     */
207    public Object getCurrentValue() {
208        if (m_property == null) {
209            return m_value;
210        } else {
211            return m_property.getValue();
212        }
213    }
214
215}