001 /*
002 * Copyright 2005 Stephen J. McConnell
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
013 * implied.
014 *
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package net.dpml.library.impl;
020
021 import java.util.ArrayList;
022 import java.util.Enumeration;
023 import java.util.Properties;
024
025 import net.dpml.library.Dictionary;
026 import net.dpml.library.info.AbstractDirective;
027
028 import net.dpml.util.PropertyResolver;
029
030 /**
031 * Utility class used for construction of a module model from an XML source.
032 *
033 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
034 * @version 1.1.2
035 */
036 public class DefaultDictionary implements Dictionary
037 {
038 private final DefaultDictionary m_parent;
039 private final AbstractDirective m_directive;
040 private final Properties m_properties;
041
042 /**
043 * Creation of a new dictionary. The dictionary provides support
044 * for property inheritance within the hierachy of of modules based
045 * an a single root virtual module. When handling a propety request
046 * the dictionary will attempt to resolve the property value using
047 * local property values. If the value is unresolved, the implemenetation
048 * will attempt to delegate the request to a parent dictionary if available.
049 *
050 * @param parent the parent dictionary (possibly null)
051 * @param directive an abstract directive containing local properties
052 */
053 public DefaultDictionary( DefaultDictionary parent, AbstractDirective directive )
054 {
055 if( null == directive )
056 {
057 throw new NullPointerException( "directive" );
058 }
059 m_parent = parent;
060 m_directive = directive;
061
062 Properties properties = getParentProperties();
063 m_properties = new Properties( properties );
064 Properties local = directive.getProperties();
065 String[] keys = getLocalPropertyNames( local );
066 for( int i=0; i<keys.length; i++ )
067 {
068 String key = keys[i];
069 String value = local.getProperty( key );
070 m_properties.setProperty( key, value );
071 }
072 }
073
074 //----------------------------------------------------------------------------
075 // Dictionary
076 //----------------------------------------------------------------------------
077
078 /**
079 * Return the property names associated with the dictionary.
080 * @return the array of property names
081 */
082 public String[] getPropertyNames()
083 {
084 return getLocalPropertyNames( m_properties );
085 }
086
087 /**
088 * Return the local property names associated with the dictionary.
089 * @return the array of local property names
090 */
091 public String[] getLocalPropertyNames()
092 {
093 return getLocalPropertyNames( m_directive.getProperties() );
094 }
095
096 /**
097 * Return a property value.
098 * @param key the property key
099 * @return the property value
100 */
101 public String getProperty( String key )
102 {
103 return getProperty( key, null );
104 }
105
106 /**
107 * Return a property value.
108 * @param key the property key
109 * @param value the default value
110 * @return the property value
111 */
112 public String getProperty( String key, String value )
113 {
114 String result = m_properties.getProperty( key, value );
115 return resolve( result );
116 }
117
118 /**
119 * Return an integer property value.
120 * @param key the property key
121 * @param value the default value
122 * @return the property value as an integer
123 */
124 public int getIntegerProperty( String key, int value )
125 {
126 String result = m_properties.getProperty( key );
127 if( null == result )
128 {
129 return value;
130 }
131 else
132 {
133 String literal = resolve( result );
134 return Integer.parseInt( literal );
135 }
136 }
137
138 /**
139 * Return an boolean property value.
140 * @param key the property key
141 * @param value the default value
142 * @return the property value as an boolean
143 */
144 public boolean getBooleanProperty( String key, boolean value )
145 {
146 String result = m_properties.getProperty( key );
147 if( null != result )
148 {
149 return Boolean.valueOf( result ).booleanValue();
150 }
151 else
152 {
153 return value;
154 }
155 }
156 /**
157 * Evaluate and expand any symbolic references in the supplied value.
158 * @param value the value to resolve
159 * @return the resolved value
160 */
161 public String resolve( String value )
162 {
163 return PropertyResolver.resolve( m_properties, value );
164 }
165
166 //----------------------------------------------------------------------------
167 // internal
168 //----------------------------------------------------------------------------
169
170 void setProperty( String name, String value )
171 {
172 m_properties.setProperty( name, value );
173 }
174
175 AbstractDirective getAbstractDirective()
176 {
177 return m_directive;
178 }
179
180 Properties getProperties()
181 {
182 return m_properties;
183 }
184
185 private Properties getParentProperties()
186 {
187 if( null == m_parent )
188 {
189 return new Properties();
190 }
191 else
192 {
193 return m_parent.getProperties();
194 }
195 }
196
197 private String[] getLocalPropertyNames( Properties properties )
198 {
199 ArrayList list = new ArrayList();
200 Enumeration names = properties.propertyNames();
201 while( names.hasMoreElements() )
202 {
203 list.add( (String) names.nextElement() );
204 }
205 return (String[]) list.toArray( new String[0] );
206 }
207
208 Properties getExportProperties()
209 {
210 String[] keys = getLocalPropertyNames();
211 Properties properties = new Properties();
212 for( int i=0; i<keys.length; i++ )
213 {
214 String key = keys[i];
215 String value = getProperty( key );
216 properties.setProperty( key, value );
217 }
218 return properties;
219 }
220 }