hlship 2004/08/11 04:41:35
Modified: framework/src/java/org/apache/hivemind/impl
ImplStrings.properties ImplMessages.java
SchemaElement.java
framework/src/java/org/apache/hivemind/schema/impl
AttributeModelImpl.java
framework/src/java/org/apache/hivemind/schema
AttributeModel.java
. status.xml
framework/src/java/org/apache/hivemind/parse
DescriptorParser.java DescriptorParser.properties
src/documentation/content/xdocs descriptor.xml
Added: framework/src/test/hivemind/test/config
UniqueAttributeDefinition.xml
TestUniqueElementAttribute.java
UniqueAttributeBroken.xml
framework/src/test/hivemind/test/config/impl FooHolder.java
Log:
HIVEMIND-43: Add uniqueness check for contribution attributes.
Revision Changes Path
1.7 +1 -1
jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/ImplStrings.properties
Index: ImplStrings.properties
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/ImplStrings.properties,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- ImplStrings.properties 17 Jul 2004 23:50:38 -0000 1.6
+++ ImplStrings.properties 11 Aug 2004 11:41:34 -0000 1.7
@@ -25,7 +25,6 @@
no-such-service-point=Service point {0} does not exist.
no-service-point-for-interface=There is no service point for interface {0}.
multiple-service-points-for-interface=There are multiple service points for
interface {0}: {1}.
-registry-already-started=The HiveMind Registry has been started.
unable-to-load-class=Could not load class {0} from {1}: {2}
null-interceptor=Service {0} generated a null interceptor (for service point
{1}).
interceptor-does-not-implement-interface=The service interceptor ({0})
generated by service {1} for service point {2} does not implement the {3}
interface defined by the service point.
@@ -49,6 +48,7 @@
symbol-source-contribution=symbol source
unknown-attribute=Attribute ''{0}'' is not defined in the schema.
missing-attribute=Attribute ''{0}'' is required but no value was provided.
+unique-attribute-constraint-broken=Value for attribute ''{0}'' (''{1}'')
duplicates a prior instance at {2}.
element-errors=Element {0} (at {1}) contains errors:
unknown-element=Element {0} is not allowed here.
bad-interface=Unable to find interface {0} (for service {1}).
1.13 +9 -1
jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/ImplMessages.java
Index: ImplMessages.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/ImplMessages.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- ImplMessages.java 17 Jul 2004 23:50:38 -0000 1.12
+++ ImplMessages.java 11 Aug 2004 11:41:34 -0000 1.13
@@ -238,6 +238,14 @@
return _formatter.format("missing-attribute", name);
}
+ public static String uniqueAttributeConstraintBroken(
+ String name,
+ String value,
+ Location priorLocation)
+ {
+ return _formatter.format("unique-attribute-constraint-broken", name,
value, priorLocation);
+ }
+
public static String elementErrors(SchemaProcessor processor, Element
element)
{
return _formatter.format(
@@ -322,7 +330,7 @@
following = true;
}
-
+
buffer.append("}");
return _formatter.format(
1.5 +44 -6
jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/SchemaElement.java
Index: SchemaElement.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/SchemaElement.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- SchemaElement.java 9 Jun 2004 14:52:14 -0000 1.4
+++ SchemaElement.java 11 Aug 2004 11:41:34 -0000 1.5
@@ -25,6 +25,7 @@
import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.Attribute;
import org.apache.hivemind.Element;
+import org.apache.hivemind.Location;
import org.apache.hivemind.schema.AttributeModel;
import org.apache.hivemind.schema.ElementModel;
import org.apache.hivemind.schema.Rule;
@@ -42,22 +43,27 @@
{
private SchemaProcessor _processor;
private ElementModel _model;
- private List _requiredAttributes;
- private Set _knownAttributes;
+ private List _requiredAttributes = new ArrayList();
+ private Set _knownAttributes = new HashSet();
private Map _nestedElements;
/**
* Keyed on attribute name, value is string (possibly null) used to
access a translator.
*/
private Map _attributeTranslators = new HashMap();
+ /**
+ * Map of Maps. The outer key is an attribute name string, this
indicates
+ * that the attribute values should be unique. Inner map is keyed on
attribute value
+ * (as a string), the value is the [EMAIL PROTECTED]
org.apache.hivemind.Location} defining
+ * that value.
+ */
+ private Map _attributeValues = new HashMap();
+
SchemaElement(SchemaProcessor processor, ElementModel model)
{
_processor = processor;
_model = model;
- _requiredAttributes = new ArrayList();
- _knownAttributes = new HashSet();
-
List attributeModels = model.getAttributeModels();
int count = attributeModels.size();
@@ -72,6 +78,12 @@
if (am.isRequired())
_requiredAttributes.add(name);
+ // If the attribute should be unique, add a map for that
attribute
+ // to track unique values for that attribute.
+
+ if (am.isUnique())
+ _attributeValues.put(name, new HashMap());
+
_attributeTranslators.put(name, am.getTranslator());
}
}
@@ -129,8 +141,9 @@
if (!_knownAttributes.contains(name))
errors.add(ImplMessages.unknownAttribute(name));
- required.remove(name);
+ checkUniquness(name, a.getValue(), element.getLocation(),
errors);
+ required.remove(name);
}
Iterator it = required.iterator();
@@ -156,7 +169,32 @@
buffer.append(errors.get(i).toString());
}
+ // TODO: refactor to use the ErrorHandler rather than throw an
exception
+ // (these errors are somewhat recoverable).
+
throw new ApplicationRuntimeException(buffer.toString(),
element.getLocation(), null);
+ }
+
+ private void checkUniquness(String name, String value, Location
location, List errors)
+ {
+ Map valuesMap = (Map) _attributeValues.get(name);
+
+ // If null, then not checking on uniqueness.
+
+ if (valuesMap == null)
+ return;
+
+ Location prior = (Location) valuesMap.get(value);
+
+ if (prior == null)
+ {
+ valuesMap.put(value, location);
+ return;
+ }
+
+ // A conflict.
+
+ errors.add(ImplMessages.uniqueAttributeConstraintBroken(name, value,
prior));
}
void fireBegin(Element element)
1.1
jakarta-hivemind/framework/src/test/hivemind/test/config/UniqueAttributeDefinition.xml
Index: UniqueAttributeDefinition.xml
===================================================================
<?xml version="1.0"?>
<!--
Copyright 2004 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<module id="hivemind.test.parse" version="1.0.0">
Description of the Module.
<schema id="UniqueAttributeBroken">
<element name="foo">
Identifies a foo that will be fnorded.
<attribute name="unique" unique="true"/>
<rules>
<create-object
class="hivemind.test.config.impl.FooHolder"/>
<read-attribute property="unique"
attribute="unique"/>
<invoke-parent method="addElement"/>
</rules>
</element>
</schema>
<configuration-point id="MyExtensionPoint" occurs="1..n"
schema-id="UniqueAttributeBroken">
Description of MyExtensionPoint.
</configuration-point>
<schema id="FalseUniqueAttribute">
<element name="foo">
Identifies a foo that will be fnorded.
<attribute name="unique" unique="false"/>
<rules>
<create-object
class="hivemind.test.config.impl.FooHolder"/>
<read-attribute property="unique"
attribute="unique"/>
<invoke-parent method="addElement"/>
</rules>
</element>
</schema>
<configuration-point id="MyExtensionPoint2" occurs="1..n"
schema-id="FalseUniqueAttribute">
Description of MyExtensionPoint.
</configuration-point>
<schema id="NoUniqueAttribute">
<element name="foo">
Identifies a foo that will be fnorded.
<attribute name="unique"/>
<rules>
<create-object
class="hivemind.test.config.impl.FooHolder"/>
<read-attribute property="unique"
attribute="unique"/>
<invoke-parent method="addElement"/>
</rules>
</element>
</schema>
<configuration-point id="MyExtensionPoint3" occurs="1..n"
schema-id="FalseUniqueAttribute">
Description of MyExtensionPoint.
</configuration-point>
<contribution configuration-id="MyExtensionPoint">
<foo unique="jeje"/>
<foo unique="jeje2"/>
</contribution>
<contribution configuration-id="MyExtensionPoint2">
<foo unique="jeje"/>
<foo unique="jeje2"/>
</contribution>
<contribution configuration-id="MyExtensionPoint3">
<foo unique="jeje"/>
<foo unique="jeje2"/>
</contribution>
</module>
1.1
jakarta-hivemind/framework/src/test/hivemind/test/config/TestUniqueElementAttribute.java
Index: TestUniqueElementAttribute.java
===================================================================
// Copyright 2004 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package hivemind.test.config;
import hivemind.test.FrameworkTestCase;
import org.apache.hivemind.Registry;
import org.apache.hivemind.ApplicationRuntimeException;
import java.util.List;
/** Test for checking the uniqueness of element attributes.
*/
public class TestUniqueElementAttribute extends FrameworkTestCase
{
/**
* Test with unique="true"
*/
public void testUniquenessViolated() throws Exception
{
Registry r =
buildFrameworkRegistry(
new String[] { "UniqueAttributeDefinition.xml",
"UniqueAttributeBroken.xml" });
List elements =
r.getConfiguration("hivemind.test.parse.MyExtensionPoint");
try
{
// This constructs the actual backing list
elements.size();
unreachable();
}
catch (ApplicationRuntimeException ex)
{
assertExceptionSubstring(
ex,
"Value for attribute 'unique' ('jeje') duplicates a prior
instance at");
}
}
/**
* Test with unique="false"
*/
public void testFalseUniqueAttributeConstraint() throws Exception
{
Registry r =
buildFrameworkRegistry(
new String[] { "UniqueAttributeDefinition.xml",
"UniqueAttributeBroken.xml" });
List elements =
r.getConfiguration("hivemind.test.parse.MyExtensionPoint2");
assertEquals(3, elements.size());
}
/**
* Test with unique unspecified (defaults to false).
*/
public void testNoUniqueAttributeConstraint() throws Exception
{
Registry r =
buildFrameworkRegistry(
new String[] { "UniqueAttributeDefinition.xml",
"UniqueAttributeBroken.xml" });
List elements =
r.getConfiguration("hivemind.test.parse.MyExtensionPoint3");
assertEquals(3, elements.size());
}
}
1.1
jakarta-hivemind/framework/src/test/hivemind/test/config/UniqueAttributeBroken.xml
Index: UniqueAttributeBroken.xml
===================================================================
<?xml version="1.0"?>
<!--
Copyright 2004 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<module id="hivemind.test.parse.broken" version="1.0.0">
<contribution configuration-id="hivemind.test.parse.MyExtensionPoint">
<foo unique="jeje"/>
</contribution>
<contribution configuration-id="hivemind.test.parse.MyExtensionPoint2">
<foo unique="jeje"/>
</contribution>
<contribution configuration-id="hivemind.test.parse.MyExtensionPoint3">
<foo unique="jeje"/>
</contribution>
</module>
1.4 +11 -0
jakarta-hivemind/framework/src/java/org/apache/hivemind/schema/impl/AttributeModelImpl.java
Index: AttributeModelImpl.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/schema/impl/AttributeModelImpl.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- AttributeModelImpl.java 17 Jun 2004 15:16:15 -0000 1.3
+++ AttributeModelImpl.java 11 Aug 2004 11:41:34 -0000 1.4
@@ -26,6 +26,7 @@
{
private String _name;
private boolean _required;
+ private boolean _unique;
private String _translator;
public String getName()
@@ -47,6 +48,16 @@
{
_required = b;
}
+
+ public void setUnique(boolean b)
+ {
+ _unique = b;
+ }
+
+ public boolean isUnique()
+ {
+ return _unique;
+ }
public String getTranslator()
{
1.4 +7 -1
jakarta-hivemind/framework/src/java/org/apache/hivemind/schema/AttributeModel.java
Index: AttributeModel.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/schema/AttributeModel.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- AttributeModel.java 17 Jun 2004 15:16:14 -0000 1.3
+++ AttributeModel.java 11 Aug 2004 11:41:34 -0000 1.4
@@ -40,6 +40,12 @@
* Returns the translator used to convert the attribute value. This is
used
* to locate a [EMAIL PROTECTED] org.apache.hivemind.schema.Translator}.
*/
-
public String getTranslator();
+
+ /**
+ * Returns true if the attribute is supposed to be considered unique in
relation to the configuration point.
+ * @return True if the attribute must be unique with respect to it's
xpath, otherwise false
+ */
+ public boolean isUnique();
+
}
1.43 +4 -0 jakarta-hivemind/status.xml
Index: status.xml
===================================================================
RCS file: /home/cvs/jakarta-hivemind/status.xml,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -r1.42 -r1.43
--- status.xml 10 Aug 2004 14:25:08 -0000 1.42
+++ status.xml 11 Aug 2004 11:41:34 -0000 1.43
@@ -53,6 +53,10 @@
<action type="update" dev="HLS">
Improvements to HiveBuild to properly handle changing versions or
useages of artifacts.
</action>
+ <action type="add" dev="HLS" fixes-bug="HIVEMIND-43" due-to="Johan
Lindquist">
+ Add ability to mark attributes of an element as unique, such that
+ duplicate values in contributions result in errors.
+ </action>
</release>
<release version="1.0-beta-2" date="Aug 1 2004">
1.1
jakarta-hivemind/framework/src/test/hivemind/test/config/impl/FooHolder.java
Index: FooHolder.java
===================================================================
// Copyright 2004 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package hivemind.test.config.impl;
/** Internal class for storing simple element attribute for test
*/
public class FooHolder
{
private String _unique;
public String getUnique()
{
return _unique;
}
public void setUnique(String unique)
{
_unique = unique;
}
public String toString()
{
return "FooHolder{" + "unique='" + _unique + "'" + "}";
}
}
1.27 +1 -1
jakarta-hivemind/framework/src/java/org/apache/hivemind/parse/DescriptorParser.java
Index: DescriptorParser.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/parse/DescriptorParser.java,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- DescriptorParser.java 10 Aug 2004 22:20:20 -0000 1.26
+++ DescriptorParser.java 11 Aug 2004 11:41:34 -0000 1.27
@@ -60,7 +60,6 @@
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
-import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
@@ -736,6 +735,7 @@
attributeModel.setName(getAttribute("name"));
attributeModel.setRequired(getBooleanAttribute("required", false));
+ attributeModel.setUnique(getBooleanAttribute("unique", false));
attributeModel.setTranslator(getAttribute("translator", "smart"));
elementModel.addAttributeModel(attributeModel);
1.10 +1 -0
jakarta-hivemind/framework/src/java/org/apache/hivemind/parse/DescriptorParser.properties
Index: DescriptorParser.properties
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/parse/DescriptorParser.properties,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- DescriptorParser.properties 9 Aug 2004 14:53:46 -0000 1.9
+++ DescriptorParser.properties 11 Aug 2004 11:41:34 -0000 1.10
@@ -45,6 +45,7 @@
required.attribute.name=true
required.attribute.required=false
+required.attribute.unique=false
required.attribute.translator=false
required.create-object.class=true
1.9 +7 -0
jakarta-hivemind/src/documentation/content/xdocs/descriptor.xml
Index: descriptor.xml
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/src/documentation/content/xdocs/descriptor.xml,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- descriptor.xml 10 Aug 2004 21:21:07 -0000 1.8
+++ descriptor.xml 11 Aug 2004 11:41:34 -0000 1.9
@@ -59,6 +59,13 @@
configuration element. The
default is false.</td>
</tr>
<tr>
+ <td>unique</td>
+ <td>boolean</td>
+ <td>no</td>
+ <td>If true, the attribute must contain
a unique value with respect to
+ all other contributions to the same
configuration point. The default is false.</td>
+ </tr>
+ <tr>
<td>translator</td>
<td>string</td>
<td>no</td>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]