1 00:00:00,410 --> 00:00:03,770 If you didn't take the time earlier to scan the logic of this class, go ahead and 2 00:00:03,770 --> 00:00:05,640 pause the video now and take a peek. 3 00:00:05,640 --> 00:00:07,780 When you get the gist of it, un-pause and we'll continue. 4 00:00:08,860 --> 00:00:11,750 Everything that needs to be done is documented with a to do comment, so 5 00:00:11,750 --> 00:00:13,230 let's jump right in. 6 00:00:13,230 --> 00:00:15,690 To check if an annotation is present on a class or 7 00:00:15,690 --> 00:00:18,800 a method, the code is quite simple and intuitive. 8 00:00:18,800 --> 00:00:23,000 We'll use the class objects, isAnnotationPresent() method. 9 00:00:23,000 --> 00:00:27,251 So in place of true, I will type clazz. 10 00:00:27,251 --> 00:00:30,302 I'm gonna call this variable clazz, so 11 00:00:30,302 --> 00:00:35,000 it's not confused with class, isAnnotationPresent(). 12 00:00:35,000 --> 00:00:36,970 And I'll press Doc.class. 13 00:00:36,970 --> 00:00:41,300 So, I tell the class object exactly what annotation I'm looking for. 14 00:00:42,570 --> 00:00:45,710 Next up is looping over the declared methods of the class object. 15 00:00:45,710 --> 00:00:46,910 We did this while practicing. 16 00:00:46,910 --> 00:00:52,507 So here, instead of looping over an empty array, which I have right here, we'll use 17 00:00:52,507 --> 00:00:58,044 the getDeclaredMethods method to return an array of the classesDeclared methods. 18 00:00:58,044 --> 00:01:02,610 clazz.getDeclaredMethods(). 19 00:01:04,630 --> 00:01:07,040 Now, let's get the modifiers the current method. 20 00:01:07,040 --> 00:01:09,520 This is accomplished with the get modifiers method. 21 00:01:09,520 --> 00:01:11,750 Remember, this comes back as an int. 22 00:01:11,750 --> 00:01:14,730 We'll be making more meaningful use of this int in just a moment. 23 00:01:14,730 --> 00:01:19,720 So in place of this string approach that we took in practicing reflection, 24 00:01:19,720 --> 00:01:21,470 we're gonna store this as an int. 25 00:01:21,470 --> 00:01:27,170 int, and I'll call it modifierInt 26 00:01:27,170 --> 00:01:31,740 = method.getModifiers. 27 00:01:31,740 --> 00:01:34,110 Getting the method name was also simple and straightforward. 28 00:01:34,110 --> 00:01:35,490 We use the getName() method. 29 00:01:36,870 --> 00:01:41,239 So in place of null, method.getName(). 30 00:01:41,239 --> 00:01:43,120 Now back to those modifiers. 31 00:01:43,120 --> 00:01:46,420 We need to use what's store in modifierInts to check whether or 32 00:01:46,420 --> 00:01:48,470 not the private modifier is present. 33 00:01:48,470 --> 00:01:50,310 We could use the approach we did earlier. 34 00:01:50,310 --> 00:01:52,120 Convert the int to a modifier string and 35 00:01:52,120 --> 00:01:55,510 then check to see if that string contains the word private. 36 00:01:55,510 --> 00:01:58,790 But, there's another method in the Modifier class 37 00:01:58,790 --> 00:02:01,090 that will get us there one step sooner. 38 00:02:01,090 --> 00:02:04,610 It's the isPrivate() method, and it's a static method. 39 00:02:04,610 --> 00:02:10,389 So in place of true I will check to see if the modifier is private and 40 00:02:10,389 --> 00:02:18,079 I'll pass it the modifierInt that I got back from calling getModifiers() up above. 41 00:02:18,079 --> 00:02:22,328 Now of course, I want to check to see if the method is non-private, so I'm going to 42 00:02:22,328 --> 00:02:26,810 negate this boolean value that comes back with the exclamation point. 43 00:02:26,810 --> 00:02:29,660 I also realized that I'd introduced the Modifier class for 44 00:02:29,660 --> 00:02:31,090 the first time in this file. 45 00:02:31,090 --> 00:02:35,397 So let's go to the top and import the modifier class. 46 00:02:35,397 --> 00:02:40,511 Import java.lang.reflect.Modifier. 47 00:02:40,511 --> 00:02:43,370 Brilliant, scrolling back down, 48 00:02:43,370 --> 00:02:47,550 next we'll need to check and see if the annotation appears on the method. 49 00:02:48,730 --> 00:02:50,160 Right here, in place of this true, 50 00:02:50,160 --> 00:02:53,850 will also call the isAnnotationPresent() on the method. 51 00:02:53,850 --> 00:02:59,300 So, I'll call method.isAnnotationPresent(). 52 00:02:59,300 --> 00:03:03,790 Again, pass the .class, so it knows which annotation we're actually looking for. 53 00:03:05,160 --> 00:03:08,490 The next to do is a critical one, and one we haven't practiced yet, but 54 00:03:08,490 --> 00:03:10,500 it's also really easy. 55 00:03:10,500 --> 00:03:14,130 This will be the piece of code that gives us access to the actual element values 56 00:03:14,130 --> 00:03:16,580 on the individually placed annotations. 57 00:03:16,580 --> 00:03:20,330 That is, we'll be able to read the details of a specific annotation. 58 00:03:20,330 --> 00:03:24,240 For example, what description was indeed provided? 59 00:03:24,240 --> 00:03:28,070 Or, how many parameters were actually documented? 60 00:03:28,070 --> 00:03:32,980 What we need to do is fetch the annotation itself as a doc object, so that we can 61 00:03:32,980 --> 00:03:37,230 call the interface methods, or elements, that we defined in the annotation. 62 00:03:37,230 --> 00:03:41,829 To do this, we'll call the methods getAnnotation() method. 63 00:03:41,829 --> 00:03:46,370 method.getAnnotation(), again specifying which 64 00:03:46,370 --> 00:03:48,120 annotation it is that we'd like to get. 65 00:03:50,090 --> 00:03:53,775 The rest of our coding falls into the two methods at the bottom of the class. 66 00:03:53,775 --> 00:03:58,940 getNumMissingParams(), right here, as well as hasReturnDescription(), 67 00:03:58,940 --> 00:04:00,940 the last method at the bottom here. 68 00:04:00,940 --> 00:04:03,070 Let's start with getNumMissingParams(). 69 00:04:04,510 --> 00:04:07,420 Our first order of business is comparing the number of parameters to 70 00:04:07,420 --> 00:04:09,430 the number of parameters document. 71 00:04:09,430 --> 00:04:12,470 We'll first put each piece of information into a variable and 72 00:04:12,470 --> 00:04:14,970 then use those values in simple comparison. 73 00:04:14,970 --> 00:04:17,530 So, after these to do comments, I'll create a couple of variables. 74 00:04:17,530 --> 00:04:21,740 The first one I'm gonna call annotedParamCount. 75 00:04:21,740 --> 00:04:25,690 This will be the number of parameters that were documented in the annotation itself. 76 00:04:26,800 --> 00:04:32,750 So, to find that I will say doc.params().length. 77 00:04:32,750 --> 00:04:36,760 Remember, the params element that we declared in the annotation is 78 00:04:36,760 --> 00:04:38,190 a string array. 79 00:04:38,190 --> 00:04:42,810 Since it's a string array, we have access to the length property. 80 00:04:42,810 --> 00:04:46,540 Okay, my next variable I'm going to call actualParamCount. 81 00:04:47,990 --> 00:04:52,330 This variable will store the actual number of parameters on the method object. 82 00:04:52,330 --> 00:04:55,651 method.GetParameterCount(). 83 00:04:57,991 --> 00:05:00,767 Finally, to compare the two values in place of true, 84 00:05:00,767 --> 00:05:05,620 we'll use those two variable names that we just declared and stored values into. 85 00:05:05,620 --> 00:05:12,069 So if the annotatedParamCount < actualParamCount 86 00:05:14,249 --> 00:05:16,430 Then we must have some missing parameters. 87 00:05:16,430 --> 00:05:17,780 So, how do we calculate that? 88 00:05:17,780 --> 00:05:21,580 Well, that is simply a subtraction problem between those two values. 89 00:05:21,580 --> 00:05:28,541 So, numMissing = actualParamCount- annotatedParamCount. 90 00:05:31,421 --> 00:05:35,440 On to our last method, hasReturnDescription(). 91 00:05:35,440 --> 00:05:39,250 For this method, we want to return true in two scenarios. 92 00:05:39,250 --> 00:05:41,570 Either a, the method is a void method, or 93 00:05:41,570 --> 00:05:46,140 b, the method's annotation has a non-empty return val element. 94 00:05:46,140 --> 00:05:49,190 Let's write a boolean expression for just that. 95 00:05:49,190 --> 00:05:51,350 To return true in the first scenario, 96 00:05:51,350 --> 00:05:53,990 I'll check to see if the method's return type is Void. 97 00:05:53,990 --> 00:05:58,345 To do this, I'll call the getReturnType() method on the method object, 98 00:05:58,345 --> 00:06:05,199 getReturnType(), and we'll see if its value equals Void.TYPE. 99 00:06:06,350 --> 00:06:07,320 In the second scenario, 100 00:06:07,320 --> 00:06:13,270 we wanna return true when the annotations returnVal element is empty. 101 00:06:13,270 --> 00:06:19,760 So to check that, we'll say doc.returnVal.isEmpty. 102 00:06:19,760 --> 00:06:22,520 We wanna check for nonempty returnVals, so 103 00:06:22,520 --> 00:06:26,640 again, I'll negate that boolean value with the exclamation point. 104 00:06:29,370 --> 00:06:32,790 At this point we've finished coding the analysis of our annotation. 105 00:06:32,790 --> 00:06:35,430 One of the cool things here, is that there's nothing that we wrote that is 106 00:06:35,430 --> 00:06:39,230 specific to the MathUtils class, which means that we can 107 00:06:39,230 --> 00:06:44,500 use this DocProcessor class to analyze the doc annotation of any class we like. 108 00:06:44,500 --> 00:06:47,600 Let's test all this code by hopping over to the Main class and 109 00:06:47,600 --> 00:06:50,440 calling the DocProcessor's, processor method. 110 00:06:50,440 --> 00:06:53,431 I'll first remove all of our test code that we wrote while we were practicing 111 00:06:53,431 --> 00:06:53,998 reflection. 112 00:06:56,719 --> 00:07:03,099 So I'll call DocProcessor.process and pass it MathUtils. 113 00:07:05,659 --> 00:07:08,650 And we're ready to compile and run. 114 00:07:08,650 --> 00:07:12,240 So back in our console, I'll compile with javac. 115 00:07:12,240 --> 00:07:17,535 Specify the out directory as a placement for our class files, set the class 116 00:07:17,535 --> 00:07:22,849 path as the src directory, and we'll type the file that we wanna compile. 117 00:07:30,269 --> 00:07:31,770 It looks like we have an error here. 118 00:07:31,770 --> 00:07:34,189 Let's check it out and see if we can troubleshoot this. 119 00:07:35,929 --> 00:07:40,910 Looks like I mistyped a variable name in DocProcessor.java on line 109. 120 00:07:40,910 --> 00:07:44,529 Let's hop over there and correct that error and recompile. 121 00:07:44,529 --> 00:07:49,069 Line 109 is right here. 122 00:07:49,069 --> 00:07:52,335 Looks like that should be annotatedParamCount. 123 00:07:52,335 --> 00:07:55,219 I'll correct that, and let's see if that was our only error. 124 00:07:55,219 --> 00:07:57,380 It's saying one error in our compiler results. 125 00:07:57,380 --> 00:07:58,500 So, I'm pretty confident here. 126 00:08:00,280 --> 00:08:01,314 Recompile. 127 00:08:04,334 --> 00:08:06,050 Great, I'm gonna clear. 128 00:08:06,050 --> 00:08:07,800 Give myself a little more room for output. 129 00:08:09,090 --> 00:08:11,665 And let's run this program. 130 00:08:11,665 --> 00:08:16,124 I'll set the class path as the out directory and 131 00:08:16,124 --> 00:08:20,929 let's run com.teamtreehouse.docgen.Main. 132 00:08:23,169 --> 00:08:25,598 Great, it finds both our sufficient and 133 00:08:25,598 --> 00:08:29,630 insufficient documentation on the MathUtils class. 134 00:08:29,630 --> 00:08:32,830 I'll leave fixing the insufficient documentation as an exercise for 135 00:08:32,830 --> 00:08:33,970 you after this video. 136 00:08:35,130 --> 00:08:37,820 Now that we've looked at the basics of annotations, 137 00:08:37,820 --> 00:08:40,320 experimented with the built-in annotations and 138 00:08:40,320 --> 00:08:44,450 even built one of our own, you're ready to encounter them in the wild. 139 00:08:44,450 --> 00:08:46,960 I've linked to some resources in the teacher's notes for 140 00:08:46,960 --> 00:08:51,500 further research, including a few popular libraries that utilize annotations. 141 00:08:52,550 --> 00:08:54,800 Having trouble with a specific library? 142 00:08:54,800 --> 00:08:57,640 Be sure to hit up the forums of those libraries, or 143 00:08:57,640 --> 00:09:00,640 even broader coding forums like StackOverflow. 144 00:09:00,640 --> 00:09:01,470 Chances are, 145 00:09:01,470 --> 00:09:05,230 the answer you're looking for is sitting out there waiting for your visit. 146 00:09:05,230 --> 00:09:06,090 Happy annotating!