commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Robert Watkins <rwatk...@foo-bar.org>
Subject Re: [Digester] addFactoryCreate problem (I think)
Date Fri, 29 Jun 2007 15:30:08 GMT
In the final analysis, I suspect the problem had to do with the order
and way in which Digester is pushing and popping to/from the stack,
and not with ObjectCreationFactory.

The solution I eventually came up with (my this is a quiet list!) was a
refactoring of my approach, using a single Rule at the /schema/types
element and at each of its possible child elements in order to gather
the appropriate data. Here's the code, in case anyone out there is
listening (or for the sake of anyone who ends up with a similar problem
and finds this in the mailing list archive):

 	FieldTypeAnalyzerMappingRule ftamRule = \
 		new FieldTypeAnalyzerMappingRule();
 	digester.addObjectCreate( prefix + "/types", HashMap.class );
 	digester.addRule(prefix + "/types", ftamRule);
 	digester.addRule(prefix + "/types/fieldtype", ftamRule);
 	digester.addRule(prefix + "/types/fieldtype/analyzer", ftamRule);
 	digester.addSetNext( prefix + "/types", "setFieldTypeAnalyzerMap" );

public class FieldTypeAnalyzerMappingRule extends Rule
{
 	protected static HashMap<String, HashMap<String, String>> \
 		fieldTypeAnalyzerMap;
 	protected static String fieldType;
 	protected static HashMap<String, String> analyzerClassMap;

 	public FieldTypeAnalyzerMappingRule()
 	{
 		// empty
 	}

 	@Override
 	@SuppressWarnings("unchecked")
 	public void begin(String namespace, String name, Attributes attrs)
 	{
 		if (name.equals("types")) {
 			fieldTypeAnalyzerMap = \
 				(HashMap<String, HashMap<String, String>>)digester.pop();
 		}
 		else if (name.equals("fieldtype")) {
 			fieldType = attrs.getValue("name");
 			analyzerClassMap = new HashMap<String, String>();
 		}
 		else if (name.equals("analyzer")) {
 			if (attrs != null) {
 				String type = null, className = null;
 				type = attrs.getValue("type");
 				className = attrs.getValue("class");
 				if (type == null) {
 					analyzerClassMap.put("index", className);
 					analyzerClassMap.put("query", className);
 				}
 				else {
 					analyzerClassMap.put(type, className);
 				}
 			}
 		}
 		// push the fieldTypeAnalyzerMap back onto the stack:
 		// this is the only way I can think of to make sure it's
 		// available (and populated) when we leave the "types"
 		// element (see the end() method for more detail)
 		digester.push(fieldTypeAnalyzerMap);
 	}

 	@Override
 	public void end(String namespace, String name)
 	{
 		if (name.equals("fieldtype")) {
 			fieldTypeAnalyzerMap.put(fieldType, analyzerClassMap);
 		}
 		// remove the fieldTypeAnalyzerMap from the Digester stack
 		// unless we are leaving the "types" element:
 		// in that case we want it to remain on the stack so that it can
 		// be used by ContentMeta.setFieldTypeAnalyzerMap
 		// when we call digester.addSetNext
 		if (!name.equals("types")) {
 			digester.pop();
 		}
 	}

Ciao!
-- RW

On Tue, 26 Jun 2007, Robert Watkins wrote:

> This one's been dogging me for hours, and as I've been unable to find an
> answer on the web, it's to the community I go!
>
> A relevant XML fragment is as follows:
>
> 	<types>
> 		<fieldtype name="analyzedField" class="solr.TextField">
> 			<analyzer type="index" class="&index_analyzer;" />
> 			<analyzer type="query" class="&query_analyzer;" />
> 		</fieldtype>
> 		<fieldtype name="verbatimField" class="solr.StrField">
> 	</types>
>
> In my code I've got:
>
> 	digester.addObjectCreate("/schema/types", HashMap.class);
> 	digester.addCallMethod("/schema/types/fieldtype", "put", 2);
> 	digester.addCallParam("/schema/types/fieldtype", 0, "name");
> 	digester.addCallParam("/schema/types/fieldtype", 1, "class");
> 	digester.addSetNext("/schema/types", "setFieldClasses");
>
> So far, this works fine, passing the created HashMap to the
> setFieldClasses() method of the top-level object.
>
> What I want to do is also create a HashMap which has the name attribute
> of the fieldtype element as its key, and as its value another HashMap,
> this time with the type and class of the analyzer element as key and
> value.
>
> As the XML fragment shows, not all fieldtype elements have child
> elements of the type analyzer (and another possibility is a single
> analyzer child with no type attribute, just class). As such, I attempted
> to use Digester.addFactoryCreate() to generate the data:
>
> 	ObjectCreationFactory analyzerClassMapCreationFactory = \
> 		new AnalyzerClassMapCreationFactory();
> 	digester.addFactoryCreate("/schema/types/fieldtype/analyzer", \
> 		analyzerClassMapCreationFactory);
> 	digester.addSetNext("/schema/types/fieldtype", \
> 		"setFieldTypeAnalyzerMap");
>
> These lines were placed just before the digester.addSetNext() line from
> the previous block. As well, the code for the ObjectCreationFactory
> implementation is as follows:
>
> 	public class AnalyzerClassMapCreationFactory \
> 		extends AbstractObjectCreationFactory
> 	{
> 		public AnalyzerClassMapCreationFactory()
> 		{
> 		}
> 		public String getFieldTypeName()
> 		{
> 			HashMap fieldClassMap = (HashMap)digester.peek(0);
> 			String fieldTypeName = \
> 				(String)fieldClassMap.keySet().iterator().next();
> 			return fieldTypeName;
> 		}
> 		@Override
> 		public Object createObject(Attributes attributes)
> 			throws Exception
> 		{
> 			HashMap<String, String> analyzerClassMap = \
> 				new HashMap<String, String>();
> 			String type = null, className = null;
> 			if (attributes != null) {
> 				type = attributes.getValue("type");
> 				className = attributes.getValue("class");
> 				if (type == null) {
> 					analyzerClassMap.put("index", 
> className);
> 					analyzerClassMap.put("query", 
> className);
> 				}
> 				else {
> 					analyzerClassMap.put(type, 
> className);
> 				}
> 			}
> 			String fieldTypeName = this.getFieldTypeName();
> 			HashMap<String, HashMap<String, String>> 
> fieldTypeAnalyzerMap = \
> 				new HashMap<String, HashMap<String, 
> String>>();
> 			fieldTypeAnalyzerMap.put(fieldTypeName, 
> analyzerClassMap);
> 			return fieldTypeAnalyzerMap;
> 		}
> 	}
>
> I realize one of the problems may have to do with the digester.peek()
> call, but even if I don't use that and use a debug String in its place,
> I get the same problem.
>
> The problem is that the previously created HashMap (from the
> setFieldClasses() call) is no longer created. Indeed, it appears that
> the createObject() method of my ObjectCreationFactory implementation is
> never called, and certainly the setFieldTypeAnalyzerMap() method is never
> called.
>
> Any guidance would be appreciated. Thanks,
> -- Robert
>
> --------------------
> Robert Watkins
> rwatkins@foo-bar.org
> --------------------
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-user-help@jakarta.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-user-help@jakarta.apache.org


Mime
View raw message