001    package edu.nrao.sss.model.source;
002    
003    import java.util.ArrayList;
004    import java.util.HashMap;
005    import java.util.HashSet;
006    import java.util.List;
007    import java.util.Map;
008    import java.util.Set;
009    
010    import edu.nrao.sss.validation.AbstractValidator;
011    import edu.nrao.sss.validation.FailureSeverity;
012    import edu.nrao.sss.validation.Validation;
013    import edu.nrao.sss.validation.ValidationPurpose;
014    import edu.nrao.sss.validation.Validator;
015    
016    /**
017     * A validator of {@link SourceGroup source groups}.
018     * <p>
019     * <u>Validations Performed for All Purposes</u>
020     * <ol>
021     *   <li>No duplicate source names.</li>
022     * </ol></p>
023     * <p>
024     * <u>Extra Validations Performed for Purpose CERTIFY_READY_TO_USE</u>
025     * <ol>
026     *   <li>Validation of contained source lookup tables.<sup>1</sup></li>
027     *   <li>Validation of contained sources.<sup>1</sup></li>
028     * </ol>
029     * <sup>1</sup><i>The particular validations performed depend on the
030     * validators used by this one to operate on those contained components</i>.</p>
031     * <p>
032     * <b>Version Info:</b>
033     * <table style="margin-left:2em">
034     *   <tr><td>$Revision: 1358 $</td></tr>
035     *   <tr><td>$Date: 2008-06-18 14:49:00 -0600 (Wed, 18 Jun 2008) $</td></tr>
036     *   <tr><td>$Author: dharland $</td></tr>
037     * </table></p>
038     * 
039     * @author David M. Harland
040     * @since 2007-02-06
041     */
042    public class SourceGroupValidator
043      extends AbstractValidator<SourceGroup>
044    {
045      private Validator sourceValidator;
046      private Validator tableValidator;
047      
048      /** Creates a new instance. */
049      public SourceGroupValidator()
050      {
051        super(SourceGroupValidator.class.getName(), SourceGroup.class);
052      }
053    
054      /* (non-Javadoc)
055       * @see AbstractValidator#makeValidationList(ValidationPurpose)
056       */
057      @Override
058      protected List<Validation<SourceGroup>>
059        makeValidationList(ValidationPurpose purpose)
060      {
061        List<Validation<SourceGroup>> validations =
062          new ArrayList<Validation<SourceGroup>>();
063        
064        validations.add(new DuplicateMemberNameValidation(this, purpose));
065        
066        return validations; 
067      }
068    
069      /* (non-Javadoc)
070       * @see edu.nrao.sss.model.validation.AbstractValidator#validate()
071       */
072      @Override
073      protected void validate()
074      {
075        super.validate();
076        
077        //Validate the members
078        Validator tableVal  = getTableValidator();
079        Validator sourceVal = getSourceValidator();
080          
081        for (SourceCatalogEntry member : target.getAll())
082        {
083          if (member instanceof SourceLookupTable)
084            failures.addAll(tableVal.validate(member, purpose));
085          else
086            failures.addAll(sourceVal.validate(member, purpose));
087        }
088      }
089      
090      //============================================================================
091      // COMPONENT VALIDATORS
092      //============================================================================
093    
094      /**
095       * Sets the validator to use for the sources of the target group.
096       * It is acceptable to use a <i>null</i> parameter, in which case
097       * this validator will contact its manager for a source validator
098       * or create one itself.
099       * 
100       * @param newValidator a validator to use on the sources of this
101       *                     validator's target group.
102       */
103      public void setSourceValidator(Validator newValidator)
104      {
105        sourceValidator = newValidator;
106      }
107    
108      /** Returns a validator for sources. */
109      public Validator getSourceValidator()
110      {
111        Validator validator = sourceValidator;
112        
113        if (validator == null)
114        {
115          if (manager != null)
116            validator = manager.getValidator(Source.class);
117        
118          if (validator == null)
119            validator = new SourceValidator();
120        }
121        
122        return validator;
123      }
124    
125      /**
126       * Sets the validator to use for the source tables of the target group.
127       * It is acceptable to use a <i>null</i> parameter, in which case
128       * this validator will contact its manager for a source table validator
129       * or create one itself.
130       * 
131       * @param newValidator a validator to use on the source lookup tables 
132       *                     of this validator's target group.
133       */
134      public void setTableValidator(Validator newValidator)
135      {
136        tableValidator = newValidator;
137      }
138    
139      /** Returns a validator for source lookup tables. */
140      public Validator getTableValidator()
141      {
142        Validator validator = tableValidator;
143        
144        if (validator == null)
145        {
146          if (manager != null)
147            validator = manager.getValidator(SourceLookupTable.class);
148        
149          if (validator == null)
150            validator = new SourceLookupTableValidator();
151        }
152        
153        return validator;
154      }
155      
156      //============================================================================
157      // ENSURE THAT NO TWO MEMBERS HAVE THE SAME NAME
158      //============================================================================
159    
160      class DuplicateMemberNameValidation extends Validation<SourceGroup>
161      {
162        private Set<String>          names;
163        private Map<String, Integer> repeatedNames;
164        
165        protected DuplicateMemberNameValidation(
166                    AbstractValidator<SourceGroup> validationContainer,
167                    ValidationPurpose              reasonForValidation)
168        {
169          super(validationContainer, reasonForValidation);
170          
171          severity = FailureSeverity.CONCERN;
172    
173          names         = new HashSet<String>();
174          repeatedNames = new HashMap<String, Integer>();
175        }
176        
177        /** This test is passed if no duplicate names are found. */
178        @Override
179        protected boolean passesTest()
180        {
181          names.clear();
182          repeatedNames.clear();
183          
184          SourceGroup group = container.getTarget();
185          
186          for (SourceCatalogEntry member : group.getAll())
187          {
188            String memberName = member.getName();
189            
190            if (names.contains(memberName))
191            {
192              int nameCount = repeatedNames.containsKey(memberName) ?
193                              1 + repeatedNames.get(memberName) : 2;
194    
195              repeatedNames.put(memberName, nameCount);
196            }
197            else
198            {
199              names.add(memberName);
200            }
201          }
202    
203          return repeatedNames.size() == 0;
204        }
205        
206        /* (non-Javadoc)
207         * @see edu.nrao.sss.validation.Validation#displayMessage()
208         */
209        @Override
210        protected String displayMessage()
211        {
212          SourceGroup group = container.getTarget();
213          
214          StringBuilder buff = new StringBuilder(group.getName());
215          
216          buff.append(" contains entries with identical names. ")
217              .append("These are the names that appear multiple times, with the ")
218              .append("number of times that name appears shown in parentheses: ");
219          
220          for (String name : repeatedNames.keySet())
221          {
222            buff.append(' ').append(name)
223                .append('(').append(repeatedNames.get(name)).append("),");
224          }
225          
226          int buffLen = buff.length();
227          buff.replace(buffLen-1, buffLen, ". ");
228          
229          buff.append("While having duplicate names is not strictly prohibited, ");
230          buff.append("it may lead to problems with your catalog and is strongly discouraged.");
231          
232          return buff.toString();
233        }
234        
235        /* (non-Javadoc)
236         * @see edu.nrao.sss.validation.Validation#debugMessage()
237         */
238        @Override
239        protected String debugMessage()
240        {
241          return "Duplicate source names found in " +
242                  container.getTarget().getName() + "; repeats = " +
243                  repeatedNames;
244        }
245      }
246    }