KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > idaremedia > antx > feedback > GroupingMapper


1 /**
2  * $Id: GroupingMapper.java 186 2007-03-16 13:42:35Z ssmc $
3  * Copyright 2003-2004 iDare Media, Inc. All rights reserved.
4  *
5  * Originally written by iDare Media, Inc. for release into the public domain. This
6  * library, source form and binary form, is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License as published by the
8  * Free Software Foundation; either version 2.1 of the License, or (at your option) any
9  * later version.<p>
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU LGPL (GNU Lesser General Public License) for more details.<p>
14  *
15  * You should have received a copy of the GNU Lesser General Public License along with this
16  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite
17  * 330, Boston, MA 02111-1307 USA. The LGPL can be found online at
18  * http://www.fsf.org/copyleft/lesser.html<p>
19  *
20  * This product has been influenced by several projects within the open-source community.
21  * The JWare developers wish to acknowledge the open-source community's support. For more
22  * information regarding the open-source products used within JWare, please visit the
23  * JWare website.
24  *----------------------------------------------------------------------------------------*
25  * WEBSITE- http://www.jware.info EMAIL- inquiries@jware.info
26  *----------------------------------------------------------------------------------------*
27  **/

28
29 package com.idaremedia.antx.feedback;
30
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33
34 import org.apache.tools.ant.BuildEvent;
35 import org.apache.tools.ant.BuildException;
36 import org.apache.tools.ant.Project;
37 import org.apache.tools.ant.Target;
38 import org.apache.tools.ant.Task;
39 import org.apache.tools.ant.types.Reference;
40 import org.apache.tools.ant.types.RegularExpression;
41 import org.apache.tools.ant.util.RegexpPatternMapper;
42 import org.apache.tools.ant.util.regexp.Regexp;
43
44 import com.idaremedia.antx.AntX;
45 import com.idaremedia.antx.AntXFixture;
46 import com.idaremedia.antx.AssertableDataType;
47 import com.idaremedia.antx.FixtureComponent;
48 import com.idaremedia.antx.apis.Nameable;
49 import com.idaremedia.antx.helpers.Tk;
50 import com.idaremedia.antx.parameters.IgnoreCaseEnabled;
51
52 /**
53  * Type that maps a BuildEvent to a diagnostics grouping using the event's information
54  * and a user-defined set of mappings. This class does <em>not</em> assume it's being
55  * used solely by {@linkplain EventEmitConduit} items; it can handle "raw" build events
56  * that haven't been massaged by a conduit. Needs to be called by a build listener
57  * to be useful.
58  * <p>
59  * The primary task (client) methods are: {@linkplain #pathFrom pathFrom}, {@linkplain
60  * #getLabel getLabel}, and {@linkplain #isEmpty isEmpty}. Most of the other methods are
61  * used by Ant's introspection methods as they construct a mapper from a build script.
62  * <p>
63  * <b>Examples:</b><pre>
64  * &lt;emitmappings id="default.labels"&gt;
65  * &lt;mapping type="indicator" name="problems" label="OohTheHumanity"/&gt;
66  * &lt;mapping type="project" like=".*" label="AntX"/&gt;
67  * &lt;/emitmappings&gt;
68  *
69  * &lt;emitmappings id="local.labels" inherit="default.labels"&gt;
70  * &lt;mapping type="task" name="property" label="Property"/&gt;
71  * &lt;mapping type="task" names="callforeach,foreach" label="ForEach"/&gt;
72  * &lt;mapping type="target" name="testABC" label="AABBCC"/&gt;
73  * &lt;mapping type="message"
74  * like="^AntX (task|type){1} \{(.*)\} loading resource .*"
75  * labelexpr="AntX\.Tools\.Resources\.\2"/&gt;
76  * &lt;/emitmappings&gt;
77  * </pre>
78  *
79  * @since JWare/AntX 0.3
80  * @author ssmc, &copy;2003-2004 <a HREF="http://www.jware.info">iDare&nbsp;Media,&nbsp;Inc.</a>
81  * @version 0.5
82  * @.safety multiple (once fully configured)
83  * @.group impl,helper
84  * @see EmitLogsTask
85  * @see EventEmitConduit
86  **/

87
88 public class GroupingMapper extends AssertableDataType
89     implements FixtureComponent, Cloneable JavaDoc
90 {
91 // ---------------------------------------------------------------------------------------
92
// Individual Mappings
93
// ---------------------------------------------------------------------------------------
94
/**
95      * Mapping from a field match to a human-readable diagnostics category.
96      * <br>
97      * Some examples:<pre>
98      * &lt;mapping type="task" names="property,copyproperty" label="Property"/&gt;
99      * &lt;mapping type="target" name="--init" label="Initialization"/&gt;
100      * &lt;mapping type="target" like="^test.*" label="Tests"/&gt;
101      * </pre>
102      *
103      * @since JWare/AntX 0.3
104      * @author ssmc, &copy;2003-2004 <a HREF="http://www.jware.info">iDare&nbsp;Media,&nbsp;Inc.</a>
105      * @version 0.5
106      * @.safety multiple (once fully configured)
107      * @.group impl,helper
108      **/

109     public static class Item extends AssertableDataType
110         implements Cloneable JavaDoc, IgnoreCaseEnabled
111     {
112         private static final String JavaDoc ONLY_ONE_ERR= "task.only.oneof.attr";
113
114
115         /**
116          * Initializes a new partially-defined match item. This new
117          * item's type and match criteria must be assigned before it
118          * is used to test values.
119          **/

120         public Item()
121         {
122             super(AntX.feedback);
123         }
124
125         /**
126          * Returns a full clone of this match item. The returned
127          * copy includes an independent copy of all underlying criteria
128          * elements (like regular expressions, etc.)
129          **/

130         public Object JavaDoc clone()
131         {
132             try {
133                 Item cloned = (Item)super.clone();
134                 if (m_re!=null) {
135                     cloned.setLike(getLike());
136                 }
137                 return cloned;
138             } catch(CloneNotSupportedException JavaDoc clnx) {
139                 throw new Error JavaDoc(uistrs().get(AntX.CLONE_BROKEN_MSGID));
140             }
141         }
142
143         /**
144          * Captures a script-declared identifier for this match item.
145          * @see #getId
146          **/

147         public void setId(String JavaDoc id)
148         {
149             m_Id= id;
150         }
151
152         /**
153          * Returns this item's Ant reference identifier. Never returns
154          * <i>null</i>.
155          **/

156         public String JavaDoc getId()
157         {
158             if (m_Id!=null) {
159                 return m_Id;
160             }
161             return super.getId();
162         }
163
164         /**
165          * Initializes this item's source type category. Must be
166          * done once before this item used for matching.
167          * @see #getType
168          **/

169         public void setType(String JavaDoc f)
170         {
171             require_(f!=null,"setTyp- nonzro fld");
172             m_field = MainField.from(f,MainField.UNKNOWN);//So we can get singletons
173
}
174
175         /**
176          * Returns this item's associated source type category.
177          * Returns the "<span class="isrc">UNKNOWN</span>" if never
178          * assigned.
179          **/

180         public final MainField getType()
181         {
182             return m_field;
183         }
184
185         /**
186          * Sets this item to match source identifier by name.
187          * @param name the (exact) name that must match (non-null)
188          * @throws BuildException if this item already assigned to match
189          * by any other means (like by-name)
190          * @see #isIgnoreCase
191          **/

192         public void setName(String JavaDoc name)
193         {
194             require_(name!=null,"setNam- nonzro nam");
195             if (m_re!=null || m_names!=null) {
196                 String JavaDoc error = uistrs().get(ONLY_ONE_ERR,"name|names|like");
197                 throw new BuildException(error);
198             }
199             m_name = name;
200         }
201
202         /**
203          * Returns this item's match by-name value. Will return <i>null</i>
204          * if this item isn't matching by name.
205          **/

206         public final String JavaDoc getName()
207         {
208             return m_name;
209         }
210
211         /**
212          * Sets this item to match one of a set of names.
213          * @param list the comma-delimited list of names (non-null,non-empty)
214          * @throws BuildException if this item already assigned to match
215          * by any other means (like by-pattern)
216          * @since JWare/AntX 0.4
217          **/

218         public void setNames(String JavaDoc list)
219         {
220             require_(list!=null,"setNamLst- nonzro liststr");
221             if (m_re!=null || m_name!=null) {
222                 String JavaDoc error = uistrs().get(ONLY_ONE_ERR,"name|names|like");
223                 throw new BuildException(error);
224             }
225             List JavaDoc l= Tk.splitList(list);
226             if (l.isEmpty()) {
227                 throw new BuildException(uistrs().get("emit.mapr.bad.namelist"));
228             }
229             m_names= (String JavaDoc[])l.toArray(new String JavaDoc[l.size()]);
230             l=null;
231         }
232
233         /**
234          * Returns a <em>copy</em> of the match-to name list for this
235          * item. Will return <i>null</i> if this item isn't matching by
236          * name list.
237          * @since JWare/AntX 0.4
238          **/

239         public final String JavaDoc[] getNames()
240         {
241             String JavaDoc[] copy=null;
242             if (m_names!=null) {
243                 copy= new String JavaDoc[m_names.length];
244                 for (int i=0;i<copy.length;i++) {
245                     copy[i]= m_names[i];
246                 }
247             }
248             return copy;
249         }
250
251         /**
252          * Sets this item to match source identifier by pattern. The
253          * pattern must be compatible with the surrounding Ant runtime's
254          * regular expression spi.
255          * @param rexp the regular expression pattern (non-null)
256          * @throws BuildException if this item already assigned to match
257          * by any other means (like by-name)
258          **/

259         public void setLike(String JavaDoc rexp)
260         {
261             require_(rexp!=null,"setRE- nonzro RE");
262             if (m_name!=null || m_names!=null) {
263                 String JavaDoc error = uistrs().get(ONLY_ONE_ERR,"name|names|like");
264                 throw new BuildException(error);
265             }
266             m_re = new RegularExpression();
267             m_re.setPattern(rexp);
268         }
269
270         /**
271          * Returns this item's like expression as a pattern string.
272          * Will return <i>null</i> if this item isn't matching by pattern.
273          **/

274         public final String JavaDoc getLike()
275         {
276             return (m_re!=null) ? m_re.getPattern(getProject()) : null;
277         }
278
279         /**
280          * Returns this item's like expression as a full Regexp object.
281          * Will return <i>null</i> if this item isn't matching by pattern.
282          **/

283         public final Regexp getLikeRE()
284         {
285             return (m_re!=null) ? m_re.getRegexp(getProject()) : null;
286         }
287
288         /**
289          * Sets this item's script-assigned label. This label is used
290          * to map into the external logging system's cataloging mechanism.
291          * @param label the label (non-null)
292          **/

293         public void setLabel(String JavaDoc label)
294         {
295             require_(label!=null,"setLbl- nonzro lbl");
296             if (m_isMapper!=null) {
297                 String JavaDoc error = uistrs().get(ONLY_ONE_ERR,"label|labelexpr");
298                 throw new BuildException(error);
299             }
300             m_label = label;
301             m_isMapper = Boolean.FALSE;
302         }
303
304         /**
305          * Sets this items's script-assigned label match regular expression.
306          * This expression can contain grouping references of the
307          * {@linkplain #setLike like} expression.
308          * @since JWare/AntX 0.4
309          **/

310         public void setLabelExpr(String JavaDoc re)
311         {
312             require_(re!=null,"setLblExpr- nonzro re");
313             if (m_isMapper!=null) {
314                 String JavaDoc error = uistrs().get(ONLY_ONE_ERR,"label|labelexpr");
315                 throw new BuildException(error);
316             }
317             m_label = re;
318             m_isMapper = Boolean.TRUE;
319         }
320
321
322         /**
323          * Returns this item's assigned label. Returns the empty string
324          * if never assigned. Never returns <i>null</i>.
325          **/

326         public String JavaDoc getLabel()
327         {
328             return m_label;
329         }
330
331         /**
332          * Returns target label if the given string is a match for this
333          * item. Returns <i>null</i> if is not match.
334          * @param s the string-under-test (can be <i>null</i>)
335          **/

336         public String JavaDoc isMatch(String JavaDoc s)
337         {
338             if (s==null) {
339                 return null;
340             }
341             if (m_isMapper!=null && m_isMapper.booleanValue()) {
342                 RegexpPatternMapper helper= new RegexpPatternMapper();
343                 helper.setTo(getLabel());
344                 helper.setFrom(getLike());
345                 String JavaDoc[] rslt = helper.mapFileName(s);
346                 helper = null;
347                 return (rslt!=null) ? rslt[0] : null;
348             }
349
350             boolean hit = false;;
351             Regexp RE = getLikeRE();
352             if (RE!=null) {
353                 hit= RE.matches(s,isIgnoreCase() ? Regexp.MATCH_CASE_INSENSITIVE: 0);
354             }
355             else if (m_names!=null) {
356                 boolean caseins= isIgnoreCase();
357                 for (int i=0;i<m_names.length && !hit;i++) {
358                     if (caseins) {
359                         if (m_names[i].equalsIgnoreCase(s)) {
360                             hit = true;
361                         }
362                     } else {
363                         if (m_names[i].equals(s)) {
364                             hit = true;
365                         }
366                     }
367                 }
368             }
369             else {
370                 hit = isIgnoreCase() ? m_name.equalsIgnoreCase(s) : m_name.equals(s);
371             }
372             return hit ? getLabel() : null;
373         }
374
375         /**
376          * Tells this match item to ignore case when matching values.
377          * Applies to both names and patterns. Defaults <i>false</i>.
378          * @param ignore <i>true</i> to ignore case
379          **/

380         public void setIgnoreCase(boolean ignore)
381         {
382             m_ignoreCase = ignore;
383         }
384
385         /**
386          * Returns <i>true</i> if this match item will ignore case when
387          * testing values.
388          **/

389         public boolean isIgnoreCase()
390         {
391             return m_ignoreCase;
392         }
393
394         /**
395          * Unsupported inherited attribute.
396          * @throws BuildException always
397          **/

398         public void setRefid(String JavaDoc xxx)
399         {
400             throw new BuildException
401                 (uistrs().get("task.unsupported.attr","mapping/item",
402                               "refid"));
403         }
404
405         private String JavaDoc m_Id;
406         private MainField m_field= MainField.UNKNOWN;
407         private String JavaDoc m_label= "";
408         private String JavaDoc m_name, m_names[];
409         private RegularExpression m_re;
410         private boolean m_ignoreCase;
411         private Boolean JavaDoc m_isMapper;
412     }
413
414 // ---------------------------------------------------------------------------------------
415
// Construction, Parameters:
416
// ---------------------------------------------------------------------------------------
417

418     /**
419      * Initializes a new empty GroupingMapper instance.
420      **/

421     public GroupingMapper()
422     {
423         super(AntX.feedback);
424     }
425
426
427
428     /**
429      * Returns this mapping's reference strongly typed. This
430      * mapper must be a reference.
431      **/

432     protected final GroupingMapper getOtherMapper()
433     {
434         return (GroupingMapper)getCheckedRef(GroupingMapper.class,"mappings");
435     }
436
437
438
439     /**
440      * Returns a clone of this grouping mapper. Supports copying
441      * of mappers between parent and forked child projects. If this
442      * mapper is a reference, that referred-to object's clone method
443      * is invoked.
444      **/

445     public Object JavaDoc clone()
446     {
447         if (isReference()) {
448             return getOtherMapper().clone();
449         }
450         try {
451             GroupingMapper cloned = (GroupingMapper)super.clone();
452             cloned.m_items = AntXFixture.newListCopy(m_items);
453             for (int i=0,N=cloned.m_items.size();i<N;i++) {
454                 cloned.m_items.set(i,((Item)m_items.get(i)).clone());
455             }
456             return cloned;
457         } catch(CloneNotSupportedException JavaDoc clnx) {
458             throw new Error JavaDoc(uistrs().get(AntX.CLONE_BROKEN_MSGID));
459         }
460     }
461
462
463
464     /**
465      * Capture our identifier for feedback since types don't
466      * always get correct location information.
467      **/

468     public void setId(String JavaDoc id)
469     {
470         m_Id= id;
471     }
472
473
474
475     /**
476      * Returns a unique identifier for this GroupingMapper.
477      **/

478     public final String JavaDoc getId()
479     {
480         if (m_Id!=null) {
481             return m_Id;
482         }
483         if (isReference()) {
484             return getOtherMapper().getId();
485         }
486         return super.getId();
487     }
488
489
490
491     /**
492      * Defines a referred-to mapper when there are no matches
493      * in this mapper.
494      * @param refid reference to existing mapper (non-null)
495      * @since JWare/AntX 0.4
496      **/

497     public void setInherit(Reference refid)
498     {
499         require_(refid!=null,"setInherited- nonzro refid");
500         m_referToMapper = refid;
501     }
502
503
504
505     /**
506      * Returns this mapper's referred-to mapper for when there
507      * are no local matches. Will return <i>null</i> if never
508      * set explicitly.
509      * @since JWare/AntX 0.4
510      **/

511     public synchronized final GroupingMapper getInheritedMapper()
512     {
513         if (m_referToMapper instanceof Reference) {
514             m_referToMapper = getReferencedObject
515                 (null, ((Reference)m_referToMapper).getRefId(),
516                  GroupingMapper.class);
517
518             //FIXME: need proper circular-reference check here!
519
verify_(m_referToMapper!=this,"inherit- not circular");
520         }
521         return (GroupingMapper)m_referToMapper;
522     }
523
524
525
526     /**
527      * Adds a new user-supplied mapping to this mapper.
528      * @param itm the new (fully-configured) mapping (non-null)
529      * @throws BuildException if this mapper is a reference
530      **/

531     public void addConfiguredMapping(Item itm)
532     {
533         require_(itm!=null,"addMapin- nonzro itm");
534         if (isReference()) {
535             throw tooManyAttributes();
536         }
537         getItems().add(itm);
538         edited();
539     }
540
541
542
543     /**
544      * Returns <i>true</i> if this mapper contains no mappings.
545      **/

546     public final boolean isEmpty()
547     {
548         if (isReference()) {
549             return getOtherMapper().isEmpty();
550         }
551         return m_items.isEmpty();
552     }
553
554
555
556     /**
557      * Returns the underlying list of mapper items. Do not expose
558      * via a public interface! Never returns <i>null</i>.
559      **/

560     protected final List JavaDoc getItems()
561     {
562         return m_items;
563     }
564
565
566 // ---------------------------------------------------------------------------------------
567
// Matching event fields to custom label mappings:
568
// ---------------------------------------------------------------------------------------
569

570
571     /**
572      * Tries to determine a project's name. Never returns <i>null</i>.
573      * @since JWare/AntX 0.4
574      **/

575     private static String JavaDoc projectName(Project project)
576     {
577         String JavaDoc pn = project.getName();
578         if (pn==null) {
579             pn = project.getProperty("ant.project.name");
580             if (pn==null) {
581                 pn= "project@"+System.identityHashCode(project);
582             }
583         }
584         return pn;
585     }
586
587
588
589     /**
590      * Returns <i>true</i> if given item is a local match for a build event.
591      * This method does <em>not</em> check this mapper's inherited mapper.
592      * @param itm the item against which match is checked (non-null)
593      * @param e the event being checked (non-null)
594      * @param iz candidate zone for event (non-null)
595      **/

596     public boolean isMatch(Item itm, BuildEvent e, IndicatorZone iz)
597     {
598         require_(itm!=null && e!=null,"isMatch- nonzro event+item");
599         require_(iz!=null,"isMatch- nonzro izone");
600
601         if (isReference()) {
602             return getOtherMapper().isMatch(itm,e,iz);
603         }
604
605         return isMatch_(itm,e,iz)!=null;
606     }
607
608
609
610     /**
611      * Actual work method that determines if a local mapping matches a build
612      * event. This is an internal method that assumes the caller has already
613      * verified calling prerequisites.
614      **/

615     protected final String JavaDoc isMatch_(Item itm, BuildEvent e, IndicatorZone iz)
616     {
617         switch(itm.getType().getIndex()) {
618             case MainField.TASK_INDEX: {
619                 if (e.getTask()!=null) {
620                     return itm.isMatch(e.getTask().getTaskName());
621                 }
622                 break;
623             }
624             case MainField.TARGET_INDEX: {
625                 if (e.getTarget()!=null) {
626                     return itm.isMatch(e.getTarget().getName());
627                 }
628                 break;
629             }
630             case MainField.PROJECT_INDEX: {
631                 if (e.getProject()!=null) {
632                     return itm.isMatch(projectName(e.getProject()));
633                 }
634                 break;
635             }
636             case MainField.INDICATOR_INDEX: {
637                 return itm.isMatch(iz.getValue());
638             }
639             case MainField.MESSAGE_INDEX: {
640                 if (e.getMessage()!=null) {
641                     return itm.isMatch(e.getMessage());
642                 }
643                 break;
644             }
645         }//switch
646
return null;
647     }
648
649 // ---------------------------------------------------------------------------------------
650
// Converting an event to a category grouping:
651
// ---------------------------------------------------------------------------------------
652

653     /**
654      * Returns best match label for a specific build event field. If
655      * mapping not found locally or in inherited mapper, this method returns
656      * <i>null</i>.
657      * @param want [optional] the required field (non-null)
658      * @param e the event being checked (non-null)(itm.getType()==want) {
659      * @param iz candidate zone for event (non-null)
660      **/

661     public String JavaDoc getLabel(MainField want, BuildEvent e, IndicatorZone iz)
662     {
663         require_(want!=null && e!=null,"getLabel- nonzro event+field");
664         require_(iz!=null,"isMatch- nonzro izone");
665
666         if (isReference()) {
667             return getOtherMapper().getLabel(want,e,iz);
668         }
669         return getLabel_(want,e,iz);
670     }
671
672
673
674     /**
675      * Actual work method that determines a specific field's label. This
676      * is an internal method that assumes the caller has already verified
677      * calling prerequisites. Inherited mapper is also checked.
678      **/

679     protected final String JavaDoc getLabel_(MainField want, BuildEvent e, IndicatorZone iz)
680     {
681         if (!m_items.isEmpty()) {
682             Iterator JavaDoc itr= m_items.iterator();
683             while (itr.hasNext()) {
684                 Item itm = (Item)itr.next();
685                 if (itm.getType()==want) {
686                     String JavaDoc label = isMatch_(itm, e, iz);
687                     if (label!=null) {
688                         return label;
689                     }
690                 }
691             }
692         }
693         if (getInheritedMapper()!=null) {
694             return getInheritedMapper().getLabel_(want,e,iz);
695         }
696         return null;
697     }
698
699
700
701     /**
702      * Determine the diagnostic grouping for the logged message event.
703      * Never returns <i>null</i>. Does not match message mappings; caller
704      * has that option. Will omit fields if incoming event has no
705      * source information; for example, will omit task field if event was
706      * triggered by a target's log event.
707      * @param e the build event (non-null)
708      * @param iz the root category zone (non-null)
709      * @param allowed grouping hints (see MainField.INCLUDE_* constants)
710      * @param fieldseparator string used to separate fields in returned path
711      **/

712     public String JavaDoc pathFrom(BuildEvent e, IndicatorZone iz,
713                            int allowed, String JavaDoc fieldseparator)
714     {
715         require_(e!=null && iz!=null, "pathFrom- nonzro event+izone");
716
717         if (isReference()) {
718             return getOtherMapper().pathFrom(e,iz,allowed,fieldseparator);
719         }
720
721         final String JavaDoc SEP= (fieldseparator!=null) ? fieldseparator :
722             DefaultEmitConfiguration.INSTANCE.getGroupingPathSeparator();
723
724         StringBuffer JavaDoc sb = AntXFixture.newStringBuffer();
725         String JavaDoc field;
726
727         sb.append(indicatorLabel(e,iz,allowed));//NB:always
728

729         if ((allowed&MainField.INCLUDE_PROJECT)!=0) {
730             field = projectLabel(e,iz,allowed);
731             if (field!=null) {
732                 sb.append(SEP);
733                 sb.append(field);
734             }
735         }
736         if ((allowed&MainField.INCLUDE_TARGET)!=0) {
737             field = targetLabel(e,iz,allowed);
738             if (field!=null) {
739                 sb.append(SEP);
740                 sb.append(field);
741             }
742         }
743         if ((allowed&MainField.INCLUDE_TASK)!=0) {
744             field = taskLabel(e,iz,allowed);
745             if (field!=null) {
746                 sb.append(SEP);
747                 sb.append(field);
748             }
749         }
750
751         return sb.substring(0);
752     }
753
754
755
756     /**
757      * Determine the diagnostic grouping for the logged message event.
758      * Never returns <i>null</i>. Does not match message mappings; caller
759      * has that option. Will insert placeholder field labels for fields
760      * that event is missing.
761      * @param e the build event (non-null)
762      * @param iz the root category zone (non-null)
763      * @param allowed grouping hints (see MainField.INCLUDE_* constants)
764      * @param fieldseparator string used to separate fields in returned path
765      * @since JWare/AntX 0.4
766      **/

767     public String JavaDoc pathFromAllFields(BuildEvent e, IndicatorZone iz,
768                                     int allowed, String JavaDoc fieldseparator)
769     {
770         require_(e!=null && iz!=null, "pathFrom- nonzro event+izone");
771
772         if (isReference()) {
773             return getOtherMapper().pathFrom(e,iz,allowed,fieldseparator);
774         }
775
776         final String JavaDoc SEP= (fieldseparator!=null) ? fieldseparator :
777             DefaultEmitConfiguration.INSTANCE.getGroupingPathSeparator();
778
779         StringBuffer JavaDoc sb = AntXFixture.newStringBuffer();
780
781         sb.append(indicatorLabel(e,iz,allowed));
782
783         if ((allowed&MainField.INCLUDE_PROJECT)!=0) {
784             sb.append(SEP);
785             sb.append(projectLabelNoNull(e,iz,allowed));
786         }
787         if ((allowed&MainField.INCLUDE_TARGET)!=0) {
788             sb.append(SEP);
789             sb.append(targetLabelNoNull(e,iz,allowed));
790         }
791         if ((allowed&MainField.INCLUDE_TASK)!=0) {
792             sb.append(SEP);
793             sb.append(taskLabelNoNull(e,iz,allowed));
794         }
795
796         return sb.substring(0);
797     }
798
799
800     /**
801      * Returns a best-guess indicator label. Never returns <i>null</i>.
802      **/

803     private String JavaDoc indicatorLabel(BuildEvent e, IndicatorZone iz, int mask)
804     {
805         String JavaDoc s = getLabel_(MainField.INDICATOR,e,iz);
806         return (s!=null) ? s : iz.getValue();
807     }
808
809
810     /**
811      * Returns a best-guess project category name. Returns <i>null</i> if
812      * event not associated with any project(?!).
813      **/

814     private String JavaDoc projectLabel(BuildEvent e, IndicatorZone iz, int mask)
815     {
816         Project myproject = e.getProject();
817         if (myproject==null) {
818             return null;
819         }
820         String JavaDoc s = getLabel_(MainField.PROJECT,e,iz);
821         if (s==null) {
822             s = projectName(myproject);
823         }
824         return s;
825     }
826
827
828     /**
829      * Returns a best-guess project category name. Never returns <i>null</i>.
830      * @since JWare/AntX 0.4
831      **/

832     private String JavaDoc projectLabelNoNull(BuildEvent e, IndicatorZone iz, int mask)
833     {
834         String JavaDoc label = projectLabel(e,iz,mask);
835         if (label==null) {
836             label = uistrs().get("emit.unknown.project.grp");
837         }
838         return label;
839     }
840
841
842     /**
843      * Returns a best-guess target category name. Returns <i>null</i> if
844      * event not associated with any target.
845      **/

846     private String JavaDoc targetLabel(BuildEvent e, IndicatorZone iz, int mask)
847     {
848         Target target = e.getTarget();
849         if (target==null) {
850             return null;
851         }
852         String JavaDoc s = getLabel_(MainField.TARGET,e,iz);
853         if (s==null) {
854             s = target.getName();
855             if (s==null) {
856                 s = "target@"+System.identityHashCode(target);
857             }
858         }
859         return s;
860     }
861
862
863     /**
864      * Returns a best-guess target category name. Never returns <i>null</i>.
865      * @since JWare/AntX 0.4
866      **/

867     private String JavaDoc targetLabelNoNull(BuildEvent e, IndicatorZone iz, int mask)
868     {
869         String JavaDoc label = targetLabel(e,iz,mask);
870         if (label==null) {
871             label = uistrs().get("emit.unknown.target.grp");
872         }
873         return label;
874     }
875
876
877     /**
878      * Returns a best-guess task category name. Returns <i>null</i> if
879      * event not associated with any task.
880      **/

881     private String JavaDoc taskLabel(BuildEvent e, IndicatorZone iz, int mask)
882     {
883         Task task = e.getTask();
884         if (task==null) {
885             return null;
886         }
887         String JavaDoc s = getLabel_(MainField.TASK,e,iz);
888         if (s==null) {
889             if ((task instanceof Nameable) && (mask&MainField.INCLUDE_NESTED)!=0) {
890                 String JavaDoc name = ((Nameable)task).getName();
891                 if (name!=null) {
892                     return name;
893                 }
894             }
895             if (task.getTaskName()==null) {
896                 return "task@"+System.identityHashCode(task);
897             }
898             return task.getTaskName();
899         }
900         return s;
901     }
902
903
904     /**
905      * Returns a best-guess task category name. Never returns <i>null</i>.
906      * @since JWare/AntX 0.4
907      **/

908     private String JavaDoc taskLabelNoNull(BuildEvent e, IndicatorZone iz, int mask)
909     {
910         String JavaDoc label = taskLabel(e,iz,mask);
911         if (label==null) {
912             label = uistrs().get("emit.unknown.task.grp");
913         }
914         return label;
915     }
916
917 // ---------------------------------------------------------------------------------------
918

919     private List JavaDoc m_items = AntXFixture.newList();
920     private String JavaDoc m_Id;
921     private Object JavaDoc m_referToMapper;
922 }
923
924 /* end-of-GroupingMapper.java */
925
Popular Tags