JMU JMU - Department of Computer Science
Help Tools
Lab: Experimenting with Enumerated Types


Instructions: Answer the following questions one at a time. After answering each question, check your answer (by clicking on the check-mark icon if it is available) before proceeding to the next question.

Getting Ready: Before going any further, you should:

  1. Setup your development environment.
  2. Depending on your development environment, create either a directory or a project for this lab.
  3. Download the following files:
    to an appropriate directory/folder (e.g., the course downloads directory/folder). In most browsers/OSs, the easiest way to do this is by right-clicking/control-clicking on each of the links above and then selecting Save as... or Save link as....
  4. Add the appropriate files you downloaded to the directory/project you created for this lab.

    .java Files: In most IDEs, .java files (i.e., source files) can just be copied into the project. See the course "Help" page on your IDE for more information.

    .class and .jar Files: In some IDEs it is easier to use .class files and in others it is easier to use a .jar file that contains the .class files. Hence, you have been provided with both. See the course "Help" page on your IDE for more information.

    Resources: In some IDEs, resources (e.g., images, data files) need to be in a special directory whereas in others they need to be in the working directory. See the course "Help" page on your IDE for more information.

1. Background: For this lab you are going to be working with Air Quality Indexes as they are defined by the U.S. Environmental Protection Agency (EPA). You don't need to know much about them, other than the information that is summarized in the following table.
table.png
2. Motivation and Review: To motivate the need for enumerated types, in this part of the lab you are going to construct a small application that makes use of the Announcement class to display air quality information.
  1. Briefly review ShowAQI.java.
  2. Compile ShowAQI.java.
  3. Based on your review of ShowAQI, what is required to execute it "properly?


    It needs to be given a command-line parameter.
    Expand
  4. Execute ShowAQI using what you know is required to execute it "properly" (see the course "Help" page for your IDE if you don't remember how). What happened?


    A window like the following appeared.
    demo.png
    Expand
  5. Review the source code for ShowAQI. Why did the window have the color and text that it did?


    Because the findColor() method always returns yellow and the findDescription() method always returns "Moderate".
    Expand
  6. Why are the findColor() and findDescription() methods static?


    Because they are going to be called from a static context, specifically the main() method. Since main() is static (and will be called without reference to a ShowAQI object), every method/attribute in the ShowAQI class that main() calls/uses must also be static.
    Expand
  7. Why don't they need to be called as ShowAQI.findColor() and ShowAQI.findDescription()?


    Because they, and main(), are all in the ShowAQI class.
    Expand
  8. Modify the findColor() method so that it returns the appropriate Color object. To save time, only consider the first three categories, and treat SENSITIVE as the default. (Don't be fancy -- just use nested if statements or a switch statement and hard-code the ranges.)


        private static Color findColor(int aqi)
        {
            Color    result;
            
            if ((aqi >= 0) && (aqi <= 50))
            {
                result = new Color(0, 228, 0);
            }
            else if ((aqi >= 51) && (aqi <= 100))
            {
                result = new Color(255, 255, 0);
            }
            else
            {
                result = new Color(255, 126, 0);
            }
            
            return result;        
        }
    
    Expand
  9. Modify the findDescription() method so that it returns the appropriate String object. Again, to save time, only consider the first three categories, treat SENSITIVE as the default, and don't be fancy.


        private static String findDescription(int aqi)
        {
            String    result;
            
            if ((aqi >= 0) && (aqi <= 50))
            {
                result = "Good";            
            }
            else if ((aqi >= 51) && (aqi <= 100))
            {
                result = "Moderate";
            }
            else
            {
                result = "Unhealthy for Sensitive Groups";
            }
            
            return result;        
        }
    
    Expand
  10. If you were a system tester (not a unit tester) who had been tasked with building a complete system test suite, what information would you use to identify important test cases?


    The table that was included in the background material.
    Expand
  11. Would this be black-box or white-box testing?


    It would be black-box testing because the tester would not have access to the source code.
    Expand
  12. Conduct a few system tests to see if your application is working. Don't be comprehensive.
  13. The design of the ShowAQI application is not very good. For one thing, the ShowAQI class is not cohesive (i.e., it does too many different kinds of things). For another, the implementations of findColor() and findDescription() contain duplicate code.

    How can these two problems be solved?


    The second problem can be solved by creating a class named AirQuality that contains both a Color and a String (as well as the int AQI). That way, one method could "find" and return both at the same time.

    The first problem can be solved by moving the "find" functionality to the AirQuality class. This would make the ShowAQI class much more cohesive.

    Expand
  14. In the "real world", how many different AirQuality objects are there?


    Six, one for each category in the table above.
    Expand
  15. Given your answer to the previous question, should AirQuality be a class or an enum? In other words, do we need an intensive definition or an extensive definition of the set of AirQuality objects?


    Since there are only six possible AirQuality objects, the right thing to do is just list them all (i.e., use an extensive definition). In other words, AirQuality should be an enum
    Expand
3. An Initial Encapsulation: This part of the lab will get you started designing and implementing enumerated types.
  1. Review the AirQuality enum. How many different AirQuality objects are there?


    As expected, six.
    Expand
  2. Why is the constructor private?


    So that "nobody else" can create an AirQuality object (since, after all, there can only be six).
    Expand
  3. How many different attributes does each AirQuality object have?


    Four, a description, a color, a minimum AQI value, and a maximum AQI value.
    Expand
  4. Add accessors for the color and description.


        /**
         * Get the color associated with this AirQuality object.
         *
         * @return  The Color
         */
        public Color getColor()
        {
            return color;
        }
     
        /**
         * Get the description associated with this AirQuality object.
         *
         * @return  The description
         */
        public String getDescription()
        {
            return description;
        }
    
    Expand
  5. Add a boolean contains(int aqi) method to AirQuality that returns true if aqi is in the interval [min,max] and false otherwise.

    Do not use an if statement, a switch statement, ternary operator, or local variables!


        /**
         * Determine whether a given AQI is within the range of this AirQuality object.
         *
         * @return   true if the AQI is in [min, max]; false otherwise
         */
        public boolean contains(int aqi)
        {
            return ((aqi >= min) && (aqi <= max));
        }
    
    Expand
  6. Replace the Color findColor(int aqi) and String findDescription(int aqi) methods in the ShowAQI class with a AirQuality findAirQuality(int aqi) method. Again, limit your implementation to the first three categories. However, this time, don't use hard-coded ranges. Instead, use the contains() method in the AirQuality enum.


        /**
         * Find the AirQuality object associated with a particular 
         * air quality index (AQI).
         *
         * @param   aqi   The air quality index
         * @return        The associated AirQuality
         */
        private static AirQuality findAirQuality(int aqi)
        {
            AirQuality result;
            
            if (AirQuality.GOOD.contains(aqi))
            {
                result = AirQuality.GOOD;
            }
            else if (AirQuality.MODERATE.contains(aqi))
            {
                result = AirQuality.MODERATE;
            }
            else
            {
                result = AirQuality.SENSITIVE;
            }
    
            return result;
        }
    
    Expand
  7. Modify the main() method of the ShowAQI class so that it uses the findAirQuality() method.


        /**
         * The entry-point of the application.
         *
         * @param args  The command-line arguments (
         */
        public static void main(String[] args)
        {
            AirQuality quality;
            Announcement announcement;       
            int          aqi;        
            
            if ((args == null) || (args.length < 1))
            {
                System.out.println("\nUsage: java ShowAQI aqi\n");
            }
            else
            {
                aqi = Integer.parseInt(args[0]);
                quality = findAirQuality(aqi);
    
                if (quality == null) {
                    System.out.println("\nInvalid AQI. Please try again.\n");
                } else {
                    announcement = new Announcement(quality.getDescription(),
                            quality.getColor());
                    announcement.setVisible(true);
                }
            }
        }
    
    Expand
  8. Test the modified ShowAQI.
  9. Is ShowAQI cohesive?


    Not yet.
    Expand
4. An Improved Encapsulation: This part of the lab will help you understand why and how to build functionality into enumerated types.
  1. Move the findAirQuality() method from the ShowAQI class to the AirQuality enum. (Note: You will have to change the visibility to public.)
  2. Why is the findAirQuality() method static?


    Because it is going to be used to find an AirQuality object. If it weren't static, we would need an AirQuality object before we could call it.
    Expand
  3. Modify the ShowAQI class so that it uses the findAirQuality() method in the AirQuality class.


                    quality = AirQuality.findAirQuality(aqi);
                    
    
    Expand
  4. Why do you now need to include the class name in the call to the method?


    Because findAirQuality() is in the AirQuality class and this statement is in the ShowAQI class.
    Expand
  5. Test the modified ShowAQI.
  6. Is the ShowAQI class cohesive?


    Yes. It now does one thing -- it shows air quality information.
    Expand
  7. Is the findAirQuality() method in the AirQuality class complete?


    No, it only works for three of the six AirQuality objects.
    Expand
  8. Given that there are only six different AirQuality objects, how long would it take to add the other three cases?


    A minute or two.
    Expand
  9. Suppose there were 100 different AirQuality objects, how long would it take to add the other 97 cases?


    It would take some time and it would be annoying.
    Expand
  10. Suppose an AirQuality need to be added to the enum three years from now. How likely is it that you will remember to also modify the findAirQuality() method?


    Very unlikely!
    Expand
  11. Use the values() method and a traditional for loop to fully-implement the findAirQuality() method. (Return null if the if the aqi is out of bounds.)


        /**
         * Find the AirQuality object associated with a particular 
         * air quality index (AQI).
         *
         * @param   aqi   The air quality index
         * @return        The associated AirQuality
         */
        public static AirQuality findAirQuality(int aqi)
        {
            AirQuality[]   all;
            all = AirQuality.values();
            for (int i=0; i<all.length; i++)
            {
                if (all[i].contains(aqi))
                {
                    return all[i];
                }
            }
            return null;
        }
    
    Expand
  12. Test the modified ShowAQI.

Copyright 2022