Return-Path: Delivered-To: apmail-jakarta-commons-user-archive@www.apache.org Received: (qmail 50325 invoked from network); 17 Jul 2007 18:51:57 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 17 Jul 2007 18:51:57 -0000 Received: (qmail 37316 invoked by uid 500); 17 Jul 2007 18:51:50 -0000 Delivered-To: apmail-jakarta-commons-user-archive@jakarta.apache.org Received: (qmail 37258 invoked by uid 500); 17 Jul 2007 18:51:49 -0000 Mailing-List: contact commons-user-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Help: List-Post: List-Id: "Jakarta Commons Users List" Reply-To: "Jakarta Commons Users List" Delivered-To: mailing list commons-user@jakarta.apache.org Received: (qmail 37246 invoked by uid 99); 17 Jul 2007 18:51:49 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 17 Jul 2007 11:51:49 -0700 X-ASF-Spam-Status: No, hits=1.4 required=10.0 tests=SPF_NEUTRAL X-Spam-Check-By: apache.org Received-SPF: neutral (herse.apache.org: 205.152.59.64 is neither permitted nor denied by domain of rwatkins@foo-bar.org) Received: from [205.152.59.64] (HELO imf16aec.mail.bellsouth.net) (205.152.59.64) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 17 Jul 2007 11:51:43 -0700 Received: from ibm58aec.bellsouth.net ([68.209.119.157]) by imf16aec.mail.bellsouth.net with ESMTP id <20070717185121.KCFA20691.imf16aec.mail.bellsouth.net@ibm58aec.bellsouth.net> for ; Tue, 17 Jul 2007 14:51:21 -0400 Received: from jimwormold ([68.209.119.157]) by ibm58aec.bellsouth.net with ESMTP id <20070717185121.MUWA5940.ibm58aec.bellsouth.net@jimwormold> for ; Tue, 17 Jul 2007 14:51:21 -0400 Date: Tue, 17 Jul 2007 14:51:20 -0400 (EDT) From: Robert Watkins To: Jakarta Commons Users List Subject: Re: [Digester] addFactoryCreate problem (I think) In-Reply-To: <1184682564.6075.26.camel@simon-laptop> Message-ID: References: <1184682564.6075.26.camel@simon-laptop> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed X-Virus-Checked: Checked by ClamAV on apache.org Thanks, Simon, for taking the time to respond even though this posting is no longer fresh. For the sake of completeness, the data structure I want (and now have) is indeed a HashMap of HashMaps: HashMap> Having written the code myself, this of course does not seem all that complicated to me, but then I see not just the abstract maps but the concept underlying them. I never bothered to create a custom class because what I need is already there in the API. Thanks for the tip about the plugins feature of Digester. Fortunately, Analyzer classes do not need configuration, so what I've got does all that it needs to. Thanks again, -- Robert On Tue, 17 Jul 2007, simon wrote: > Hi Robert, > > Sorry you didn't get any feedback from the list. When I saw it involved > hashmaps of hashmaps I decided I'd punt and let someone else figure it > out. I guess everyone else did too :-). > > Actually, having re-read your email several times now I'm still not > clear what datastructure you really want to end up with. Just as a > suggestion, if you created real classes (eg TypeRegistry, FieldType, > AnalyserType) rather than using hashmaps for everything then this might > be easier to understand. However as you've got something working now > there's probably no point in revisiting it. > > However I did see this in your code: > > which I assume means that you allow many different analyser classes to > be configured ("plugged in") here, maybe even ones written by third > parties or which don't exist yet. If analyzer classes need no > configuration of any sort, then this is fine. However if you find at > some point that different analyser classes do need data that would most > naturally be put inline in the input xml file then you might like to > look at the "plugins" feature of Digester. > > > By the way, there are extensive examples on using and extending > Digester. These examples are included in the "source" download bundle, > and can also be browsed directly in the svn repository: > http://svn.apache.org/repos/asf/jakarta/commons/proper/digester/trunk/src/examples/ > > > Regards, > > Simon > > > On Fri, 2007-06-29 at 11:30 -0400, Robert Watkins wrote: >> 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> \ >> fieldTypeAnalyzerMap; >> protected static String fieldType; >> protected static HashMap analyzerClassMap; >> >> public FieldTypeAnalyzerMappingRule() >> { >> // empty >> } >> >> @Override >> @SuppressWarnings("unchecked") >> public void begin(String namespace, String name, Attributes attrs) >> { >> if (name.equals("types")) { >> fieldTypeAnalyzerMap = \ >> (HashMap>)digester.pop(); >> } >> else if (name.equals("fieldtype")) { >> fieldType = attrs.getValue("name"); >> analyzerClassMap = new HashMap(); >> } >> 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: >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> 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 analyzerClassMap = \ >>> new HashMap(); >>> 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> >>> fieldTypeAnalyzerMap = \ >>> new HashMap>> 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 >> > > > --------------------------------------------------------------------- > 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