[151795] Allows empty value in an ODA extension defined Property
diff --git a/plugins/org.eclipse.datatools.connectivity.oda/META-INF/MANIFEST.MF b/plugins/org.eclipse.datatools.connectivity.oda/META-INF/MANIFEST.MF
index 04917ce..778f5dd 100644
--- a/plugins/org.eclipse.datatools.connectivity.oda/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.datatools.connectivity.oda/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: DTP Open Data Access
 Bundle-SymbolicName: org.eclipse.datatools.connectivity.oda; singleton:=true
-Bundle-Version: 3.0.2.200607071
+Bundle-Version: 3.0.2.200607281
 Bundle-Vendor: Eclipse.org
 Bundle-Localization: plugin
 Export-Package: org.eclipse.datatools.connectivity.oda,
diff --git a/plugins/org.eclipse.datatools.connectivity.oda/schema-doc/org_eclipse_datatools_connectivity_oda_datasource.html b/plugins/org.eclipse.datatools.connectivity.oda/schema-doc/org_eclipse_datatools_connectivity_oda_datasource.html
index 1cdbdb5..70d7875 100644
--- a/plugins/org.eclipse.datatools.connectivity.oda/schema-doc/org_eclipse_datatools_connectivity_oda_datasource.html
+++ b/plugins/org.eclipse.datatools.connectivity.oda/schema-doc/org_eclipse_datatools_connectivity_oda_datasource.html
@@ -2,8 +2,8 @@
 <HTML>
 <HEAD><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <title>Open Data Access</title>
-<style>@import url("file:/c:/V3/3.1/eclipse/plugins/org.eclipse.sdk_3.1.0/book.css");</style>
-<style>@import url("file:/c:/V3/3.1/eclipse/plugins/org.eclipse.platform.doc.isv_3.1.0/schema.css");</style>
+<style>@import url("file:/D:/Lang/eclipse_32/plugins/org.eclipse.sdk_3.2.0.v20060605/book.css");</style>
+<style>@import url("file:/D:/Lang/eclipse_32/configuration/org.eclipse.osgi/bundles/69/1/.cp/schema.css");</style>
 </HEAD>
 <BODY>
 <H1><CENTER>Open Data Access</CENTER></H1>
@@ -115,7 +115,7 @@
 </ul>
 <br><p class=code id=dtd>&lt;!ELEMENT <a name="e.property">property</a> (<a href="#e.choice">choice</a>*)&gt;</p>
 <p class=code id=dtd>&lt;!ATTLIST property</p>
-<p class=code id=dtdAttlist>name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CDATA #REQUIRED<p class=code id=dtdAttlist>defaultDisplayName&nbsp;CDATA #IMPLIED<p class=code id=dtdAttlist>type&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(string|choice) "string"<p class=code id=dtdAttlist>canInherit&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(true | false) "true"<p class=code id=dtdAttlist>defaultValue&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CDATA #IMPLIED<p class=code id=dtdAttlist>isEncryptable&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(true | false) "false"&gt;</p>
+<p class=code id=dtdAttlist>name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CDATA #REQUIRED<p class=code id=dtdAttlist>defaultDisplayName&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CDATA #IMPLIED<p class=code id=dtdAttlist>type&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(string|choice) "string"<p class=code id=dtdAttlist>canInherit&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(true | false) "true"<p class=code id=dtdAttlist>defaultValue&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CDATA #IMPLIED<p class=code id=dtdAttlist>isEncryptable&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(true | false) "false"<p class=code id=dtdAttlist>allowsEmptyValueAsNull&nbsp;(true | false) "true"&gt;</p>
 <p></p>
 <p class=ConfigMarkup id=elementDesc>
 A property whose value can be edited at design-time using an ODA consumer application's designer tool.  Its value is then passed to the ODA runtime driver during run-time.</p>
@@ -127,6 +127,7 @@
 <li><b>canInherit</b> - Reserved.</li>
 <li><b>defaultValue</b> - Default value of the property, if no property value is set.</li>
 <li><b>isEncryptable</b> - A flag indicating whether this property value is encryptable.  Setting it to "true" indicates to an ODA consumer application that this property's value should be encrypted.</li>
+<li><b>allowsEmptyValueAsNull</b> - A flag that indicates whether an empty value of this property can be treated as a null value.  This attribute setting applies when passing a property value to this ODA runtime driver.  This attribute may be used to accommodate the case where a property value's input control does not provide the means to specify a null value.</li>
 </ul>
 <br><p class=code id=dtd>&lt;!ELEMENT <a name="e.propertyGroup">propertyGroup</a> (<a href="#e.property">property</a>+)&gt;</p>
 <p class=code id=dtd>&lt;!ATTLIST propertyGroup</p>
diff --git a/plugins/org.eclipse.datatools.connectivity.oda/schema/datasource.exsd b/plugins/org.eclipse.datatools.connectivity.oda/schema/datasource.exsd
index 404ff50..77f8bd5 100644
--- a/plugins/org.eclipse.datatools.connectivity.oda/schema/datasource.exsd
+++ b/plugins/org.eclipse.datatools.connectivity.oda/schema/datasource.exsd
@@ -348,6 +348,13 @@
                </documentation>

             </annotation>

          </attribute>

+         <attribute name="allowsEmptyValueAsNull" type="boolean" use="default" value="true">

+            <annotation>

+               <documentation>

+                  A flag that indicates whether an empty value of this property can be treated as a null value.  Default value is true.  This attribute setting applies when an ODA consumer passes the property&apos;s value to this ODA runtime driver.  This optional attribute may be used to accommodate the case where a property value&apos;s input control does not provide the means to specify a null value.

+               </documentation>

+            </annotation>

+         </attribute>

       </complexType>

    </element>

 

diff --git a/plugins/org.eclipse.datatools.connectivity.oda/src/org/eclipse/datatools/connectivity/oda/util/manifest/DataSetType.java b/plugins/org.eclipse.datatools.connectivity.oda/src/org/eclipse/datatools/connectivity/oda/util/manifest/DataSetType.java
index 14c58a5..3a03338 100644
--- a/plugins/org.eclipse.datatools.connectivity.oda/src/org/eclipse/datatools/connectivity/oda/util/manifest/DataSetType.java
+++ b/plugins/org.eclipse.datatools.connectivity.oda/src/org/eclipse/datatools/connectivity/oda/util/manifest/DataSetType.java
@@ -168,7 +168,7 @@
     }
 	
 	/**
-	 * Returns an array of Property instances that represent
+	 * Returns an array of Property definition instances that represent
 	 * the properties defined by this data set element.
 	 * The collection includes both top-level properties and
 	 * those in a group.
@@ -184,6 +184,27 @@
 	    }
 	    return m_properties;
 	}
+    
+    /**
+     * Returns the Property definition instance that matches the specified name
+     * in the list of properties defined by this data set element.
+     * @param propertyName  the name of a property
+     * @return  the matching Property definition, or null if no match is found.
+     */
+    public Property getProperty( String propertyName )
+    {
+        if ( propertyName == null || propertyName.length() == 0 )
+            return null;
+        
+        Property[] props = getProperties();
+        for( int i = 0; i < props.length; i++ )
+        {
+            if ( propertyName.equals( props[ i ].getName() ))
+                return props[ i ];
+        }
+        
+        return null;    // no matching property
+    }
 
 	/**
 	 * Returns a Properties collecton of property visibilty settings.
diff --git a/plugins/org.eclipse.datatools.connectivity.oda/src/org/eclipse/datatools/connectivity/oda/util/manifest/ExtensionManifest.java b/plugins/org.eclipse.datatools.connectivity.oda/src/org/eclipse/datatools/connectivity/oda/util/manifest/ExtensionManifest.java
index 695808c..9f28c6b 100644
--- a/plugins/org.eclipse.datatools.connectivity.oda/src/org/eclipse/datatools/connectivity/oda/util/manifest/ExtensionManifest.java
+++ b/plugins/org.eclipse.datatools.connectivity.oda/src/org/eclipse/datatools/connectivity/oda/util/manifest/ExtensionManifest.java
@@ -377,7 +377,7 @@
 	}
 	
 	/**
-	 * Returns an array of Property instances that represent
+	 * Returns an array of Property definition instances that represent
 	 * the properties defined by this data source extension.
 	 * The collection includes both top-level properties and
 	 * those in a group.
@@ -393,6 +393,27 @@
 	    }
 	    return m_properties;
 	}
+    
+    /**
+     * Returns the Property definition instance that matches the specified name
+     * in the list of properties defined by this data source extension.
+     * @param propertyName  the name of a property
+     * @return  the matching Property definition, or null if no match is found.
+     */
+    public Property getProperty( String propertyName )
+    {
+        if ( propertyName == null || propertyName.length() == 0 )
+            return null;
+        
+        Property[] props = getProperties();
+        for( int i = 0; i < props.length; i++ )
+        {
+            if ( propertyName.equals( props[ i ].getName() ))
+                return props[ i ];
+        }
+        
+        return null;    // no matching property
+    }
 
 	/**
 	 * Returns a Properties collecton of property visibilty settings.
diff --git a/plugins/org.eclipse.datatools.connectivity.oda/src/org/eclipse/datatools/connectivity/oda/util/manifest/Property.java b/plugins/org.eclipse.datatools.connectivity.oda/src/org/eclipse/datatools/connectivity/oda/util/manifest/Property.java
index 00671bf..b2818e8 100644
--- a/plugins/org.eclipse.datatools.connectivity.oda/src/org/eclipse/datatools/connectivity/oda/util/manifest/Property.java
+++ b/plugins/org.eclipse.datatools.connectivity.oda/src/org/eclipse/datatools/connectivity/oda/util/manifest/Property.java
@@ -34,15 +34,24 @@
     private static final String LITERAL_TRUE = "true"; //$NON-NLS-1$
     private static final String LITERAL_FALSE = "false"; //$NON-NLS-1$
     
+    private static final String NAME_ATTR = "name";  //$NON-NLS-1$
+    private static final String TYPE_ATTR = "type";  //$NON-NLS-1$
+    private static final String DEFAULT_VALUE_ATTR = "defaultValue";  //$NON-NLS-1$
+    private static final String ENCRYPTABLE_ATTR = "isEncryptable";  //$NON-NLS-1$
+    private static final String CAN_INHERIT_ATTR = "canInherit";  //$NON-NLS-1$
+    private static final String EMPTY_VALUE_TYPE_ATTR = "allowsEmptyValueAsNull";  //$NON-NLS-1$
+    private static final String CHOICE_ELEMENT = "choice";   //$NON-NLS-1$
+    
     private String m_name;
     private String m_displayName;
     private String m_groupName;
     private String m_groupDisplayName;
     private String m_type;
-    private boolean m_canInherit = true;	// default value
+    private boolean m_canInherit;
     private String m_defaultValue;
-    private boolean m_isEncryptable = false;	// default value
+    private boolean m_isEncryptable;
     private PropertyChoice[] m_choices = null;
+    private boolean m_allowsEmptyValueAsNull;
 
     Property( IConfigurationElement propertyElement )
     {
@@ -59,36 +68,30 @@
             String groupName, String groupDisplayName )
     {
         // no validation is done; up to the consumer to process
-        m_name = propertyElement.getAttribute( "name" ); //$NON-NLS-1$
+        m_name = propertyElement.getAttribute( NAME_ATTR );
         m_displayName = ManifestExplorer.getElementDisplayName( propertyElement );  
         m_groupName = groupName;
         m_groupDisplayName = groupDisplayName;
-        m_type = propertyElement.getAttribute( "type" ); //$NON-NLS-1$
+        m_type = propertyElement.getAttribute( TYPE_ATTR );
         if( m_type == null || m_type.length() == 0 )	// assign default
         	m_type = "string"; //$NON-NLS-1$
-        m_defaultValue = propertyElement.getAttribute( "defaultValue" ); //$NON-NLS-1$
+        m_defaultValue = propertyElement.getAttribute( DEFAULT_VALUE_ATTR );
 
-        m_isEncryptable = false;
-        String encryptableValue = propertyElement.getAttribute( "isEncryptable" ); //$NON-NLS-1$
- 		if( encryptableValue != null )
-		{
-		    if ( encryptableValue.equalsIgnoreCase( LITERAL_TRUE ) || 
-		         encryptableValue.equalsIgnoreCase( LITERAL_FALSE ) )
-		        m_isEncryptable = Boolean.valueOf( encryptableValue ).booleanValue();
-		}
+        Boolean boolValue = convertBooleanValue( 
+                propertyElement.getAttribute( ENCRYPTABLE_ATTR ) );
+        m_isEncryptable = ( boolValue != null ) ? boolValue.booleanValue() : false;
 
- 		m_canInherit = true;
-        String canInherit = propertyElement.getAttribute( "canInherit" ); //$NON-NLS-1$
-		if( canInherit != null )
-		{
-		    if ( canInherit.equalsIgnoreCase( LITERAL_TRUE ) || 
-			     canInherit.equalsIgnoreCase( LITERAL_FALSE ) )
-		        m_canInherit = Boolean.valueOf( canInherit ).booleanValue();
-		}
+        boolValue = convertBooleanValue( 
+                propertyElement.getAttribute( CAN_INHERIT_ATTR ) );
+        m_canInherit = ( boolValue != null ) ? boolValue.booleanValue() : true;
 		
+        boolValue = convertBooleanValue( 
+                propertyElement.getAttribute( EMPTY_VALUE_TYPE_ATTR ) );
+        m_allowsEmptyValueAsNull = ( boolValue != null ) ? boolValue.booleanValue() : true;
+        
 		// choice elements
 		IConfigurationElement[] choiceElements = 
-		    propertyElement.getChildren( "choice" ); //$NON-NLS-1$
+		    propertyElement.getChildren( CHOICE_ELEMENT );
 		int numChoices = choiceElements.length;
 		if ( numChoices <= 0 )
 		    return;		// done
@@ -101,8 +104,19 @@
 		}
 		m_choices = (PropertyChoice[]) choices.toArray( new PropertyChoice[ numChoices ] );
 
-   }
+    }
 
+    private Boolean convertBooleanValue( String value )
+    {
+        if ( value == null || value.length() == 0 )
+            return null;
+        
+        if ( value.equalsIgnoreCase( LITERAL_TRUE ) || 
+             value.equalsIgnoreCase( LITERAL_FALSE ) )
+            return Boolean.valueOf( value );
+        return null;
+    }
+    
     /**
      * Returns the property name.
      * @return	property name
@@ -177,7 +191,7 @@
     /**
      * Returns a flag indicating whether this property value should be encrypted
      * in the persistent report design file.
-     * @return	'true' or 'false' value indicating wehther
+     * @return	'true' or 'false' value that indicates whether
      * 			the property value should be encrypted.
      */
     public boolean isEncryptable()
@@ -186,6 +200,17 @@
     }
 
     /**
+     * Returns a flag that indicates whether an empty value of this property 
+     * can be treated as a null value.
+     * @return  'true' or 'false' value that indicates whether
+     *          this property value can be treated as a null value.
+     */
+    public boolean allowsEmptyValueAsNull()
+    {
+        return m_allowsEmptyValueAsNull;
+    }
+
+    /**
      * Returns the selection list of choices for the property value.
      * An empty array is returned if no choices are specified.
      * @return	an array of PropertyChoice instances that