001    package edu.nrao.sss.model.resource;
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 ResourceGroup resource groups}.
018     * <p>
019     * <u>Validations Performed for All Purposes</u>
020     * <ol>
021     *   <li>No duplicate resource 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 sources.<sup>1</sup></li>
027     * </ol>
028     * <sup>1</sup><i>The particular validations performed depend on the
029     * validators used by this one to operate on those contained components</i>.</p>
030     * <p>
031     * <b>Version Info:</b>
032     * <table style="margin-left:2em">
033     *   <tr><td>$Revision: 1709 $</td></tr>
034     *   <tr><td>$Date: 2008-11-14 11:22:37 -0700 (Fri, 14 Nov 2008) $</td></tr>
035     *   <tr><td>$Author: dharland $</td></tr>
036     * </table></p>
037     * 
038     * @author David M. Harland
039     * @since 2008-05-01
040     */
041    public class ResourceGroupValidator
042      extends AbstractValidator<ResourceGroup>
043    {
044      private Validator resourceValidator;
045      
046      /** Creates a new instance. */
047      public ResourceGroupValidator()
048      {
049        super(ResourceGroupValidator.class.getName(), ResourceGroup.class);
050      }
051    
052      /* (non-Javadoc)
053       * @see AbstractValidator#makeValidationList(ValidationPurpose)
054       */
055      @Override
056      protected List<Validation<ResourceGroup>>
057        makeValidationList(ValidationPurpose purpose)
058      {
059        List<Validation<ResourceGroup>> validations =
060          new ArrayList<Validation<ResourceGroup>>();
061        
062        validations.add(new DuplicateMemberNameValidation(this, purpose));
063        
064        return validations; 
065      }
066    
067      /* (non-Javadoc)
068       * @see edu.nrao.sss.model.validation.AbstractValidator#validate()
069       */
070      @Override
071      protected void validate()
072      {
073        super.validate();
074        
075        //Validate the members
076        Validator resourceVal = getResourceValidator();
077          
078        for (Resource member : target.getAll())
079        {
080          failures.addAll(resourceVal.validate(member, purpose));
081        }
082      }
083      
084      //============================================================================
085      // COMPONENT VALIDATORS
086      //============================================================================
087    
088      /**
089       * Sets the validator to use for the resources of the target group.
090       * It is acceptable to use a <i>null</i> parameter, in which case
091       * this validator will contact its manager for a resource validator
092       * or create one itself.
093       * 
094       * @param newValidator a validator to use on the resources of this
095       *                     validator's target group.
096       */
097      public void setResourceValidator(Validator newValidator)
098      {
099        resourceValidator = newValidator;
100      }
101    
102      /** Returns a validator for sources. */
103      public Validator getResourceValidator()
104      {
105        Validator validator = resourceValidator;
106        
107        if (validator == null)
108        {
109          if (manager != null)
110            validator = manager.getValidator(Resource.class);
111        
112          if (validator == null)
113            validator = new ResourceValidator();
114        }
115        
116        return validator;
117      }
118      
119      //============================================================================
120      // ENSURE THAT NO TWO MEMBERS HAVE THE SAME NAME
121      //============================================================================
122    
123      class DuplicateMemberNameValidation extends Validation<ResourceGroup>
124      {
125        private Set<String>          names;
126        private Map<String, Integer> repeatedNames;
127        
128        protected DuplicateMemberNameValidation(
129                    AbstractValidator<ResourceGroup> validationContainer,
130                    ValidationPurpose                reasonForValidation)
131        {
132          super(validationContainer, reasonForValidation);
133          
134          severity = FailureSeverity.CONCERN;
135    
136          names         = new HashSet<String>();
137          repeatedNames = new HashMap<String, Integer>();
138        }
139        
140        /** This test is passed if no duplicate names are found. */
141        @Override
142        protected boolean passesTest()
143        {
144          names.clear();
145          repeatedNames.clear();
146          
147          ResourceGroup group = container.getTarget();
148          
149          for (Resource member : group.getAll())
150          {
151            String memberName = member.getName();
152            
153            if (names.contains(memberName))
154            {
155              int nameCount = repeatedNames.containsKey(memberName) ?
156                              1 + repeatedNames.get(memberName) : 2;
157    
158              repeatedNames.put(memberName, nameCount);
159            }
160            else
161            {
162              names.add(memberName);
163            }
164          }
165    
166          return repeatedNames.size() == 0;
167        }
168        
169        /* (non-Javadoc)
170         * @see edu.nrao.sss.validation.Validation#displayMessage()
171         */
172        @Override
173        protected String displayMessage()
174        {
175          ResourceGroup group = container.getTarget();
176          
177          StringBuilder buff = new StringBuilder(group.getName());
178          
179          buff.append(" contains entries with identical names. ")
180              .append("These are the names that appear multiple times, with the ")
181              .append("number of times that name appears shown in parentheses: ");
182          
183          for (String name : repeatedNames.keySet())
184          {
185            buff.append(' ').append(name)
186                .append('(').append(repeatedNames.get(name)).append("),");
187          }
188          
189          int buffLen = buff.length();
190          buff.replace(buffLen-1, buffLen, ". ");
191          
192          buff.append("While having duplicate names is not strictly prohibited, ");
193          buff.append("it may lead to problems with your catalog and is strongly discouraged.");
194          
195          return buff.toString();
196        }
197        
198        /* (non-Javadoc)
199         * @see edu.nrao.sss.validation.Validation#debugMessage()
200         */
201        @Override
202        protected String debugMessage()
203        {
204          return "Duplicate resource names found in " +
205                  container.getTarget().getName() + "; repeats = " +
206                  repeatedNames;
207        }
208      }
209    }