5 Replies Latest reply on Sep 2, 2016 2:38 PM by wstafford

    A few questions, mostly about parameterization

    wstafford

      Hello,

       

      Currently I have code that looks something like this:

       

      public class MyCustomProvider extends AbstractRuleProvider{

        static ArrayList<String> list = new ArrayList<String>();

        static int counter = 0;

       

        public MyCustomProvider() {

        super(MetadataBuilder.forProvider(MyCustomProvider.class));

        }

       

        @Override

        public Configuration getConfiguration(GraphContext context)

        {

        return ConfigurationBuilder.begin()

           .addRule()

            .when(XmlFile.matchesXpath("//rf:Transition/@Source").namespace(...).as("test"))

       

            .perform(myMethod("{test}")

            .where("test").matches(".*")

            .withId("CustomProvider_1");

        }

       

        public Operation myMethod(String source) {

           if (list.contains(source)) {

                counter++;

           } else {

                list.add(source);

           }

        return Classification.as("Title: ").withDescription("Count: " + count);

        }

      }

       

       

       

      Now I have a few questions.

       

      First off, the syntax for parameterization is a bit confusing. From what I gather here:

      https://github.com/windup/windup/wiki/Rules-Java-based-Rule-Structure

      and from this example here:

      windup-quickstarts/EjbBeanUtilsAsyncUsageRuleProvider.java at master · windup/windup-quickstarts · GitHub

      The name of the variable doesn't need curly braces when:

      1. it is defined in .as(...)
      2. when it is customized in .where(...)
      3. when it is iterated over in Iteration.over(...)

      Anywhere else, it seems that it needs curly braces to extract the value. In both the quickstart example and in the rewrite documentation (rewrite/index.asciidoc at master · ocpsoft/rewrite · GitHub) it seems even if you are defining the variable, if it is not within the .as(..) method, it needs curly braces. Please correct me if I am wrong about any of that.

       

      -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

       

      Second, I would like to take the value of the parameter and pass it into a custom method, as shown in the code above:

      myMethod("{test}");

      Obviously the syntax above does not work. I'd like to know what the best way to go about this is.

       

      What I would like to do, is to take the text from each Source attribute of my Transition tags in my XML file and then do the following:

      • Check the text against a list
      • If the text is already in the list, increment a counter
      • If not, add the text to the list

      I'm essentially testing for duplicate text in those tags. I promise that this does have relevance to an application migration.

       

      -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

       

      Lastly, (this might be several discussions worth of questions, sorry about that) my counter is a static field that starts at 0. I've attempted to just increment the counter every time myMethod is called. There are 8 Source attributes in my file. In theory, the counter should then also increment to 8. In reality, the counter only increments twice. To be clear, the test looked like this:

       

      ...

      static int counter = 0;

      ...

      .when(...)

      .perform(myMethod())

      ...

       

      public Operation myMethod() {

           counter++;

         return Classification.as("Title: ").withDescription("Count: " + counter); 

      }

       

       

      The report that generates then looks like this:

      Capture.PNG

      Capture2.PNG

      Optimally, I'd want that to only print once, but that's another issue for another time. Right now I'm interested in why the counter is perpetually stuck at two? And also why it doesn't start at 0. I'm having trouble wrapping my head around it.

       

      -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

       

      In summary, three questions:

      1. Is my understanding of parameterization correct?
      2. How can I pass the parameter or the value of the parameter to my method in .perform()?
      3. What is going on with my counter?

       

      Thanks!

        • 1. Re: A few questions, mostly about parameterization
          wstafford

          Hello, just commenting to say I still need some help with this. Any advice or direction would be appreciated, thanks!

          • 2. Re: A few questions, mostly about parameterization
            manarh

            Hi Wesley,

             

            sorry for a delay - summer time, vacations, but I noticed your question just now.

             

            You have really great question(s)

             

            ad 1. there is probably wrong understanding what variable and parameter is. Parameter needs to be in curly brackets, but variable not.

             

            ad 2. parameter is passed in where method with matches regular expression. See your referenced WIKI and look for:

            .where("myMatch").matches("java.lang.String.toString\(.*\)")

             

            ad 3. your counter property is static. Every rule is tested on every file it is found in your application. So you probably have 8 files and then counter value is just reused there. I would remove static and it should be ok I think.

            • 3. Re: A few questions, mostly about parameterization
              wstafford

              Hello, thank you for the reply!

               

              I was under the impression that the where method was simply to match the the value of the variable against a regex. In my case I wanted all of the text in the file under the Source attributes in the Transition tags. So my where method was just:

              .where("test").matches(".*")

              and I wasn't even really sure if I needed to have that line.

               

              I assumed that the value being stored into the variable "test" came from:

              .when(XmlFile.matchesXPath(...).namespace(...).as("test"))

              and that that would store the values I get back from XPath into the variable "test", which in this case should be the text inside the Source tags.

               

              So if that's right, then I'm still unsure of how to pass the value of the variable "test" to myMethod as a parameter so that I can perform further operations on it before returning a Classification.

               

              Also changing the counter from static to non-static just gives me "Count: 1" instead of "Count: 2" 8 times.

               

              I only have one xml file to match against and that file has 8 Source attributes.

               

              I think I gleaned from messing with it that, when there is no .as specified in the .when the .perform is called once for each match. The .as, I guess must create a list, because with a(n) .as the .perform is only called once. The only proof I have for this is that with a(n) .as my Classification is only printed one time in the report, as opposed to the 8 times without. The counter is still out of funk no matter what though so I'm really confused about what's happening there. I think If I'm able to pass this list of matching text though over then the counter thing shouldn't be a problem, maybe.

              • 4. Re: A few questions, mostly about parameterization
                jsightler

                Hi Wesley,

                 

                It looks like this should be sufficient for the when conditional in your case:

                XmlFile.matchesXpath("//rf:Transition/@Source").namespace(...)

                 

                If you only have a single conditional, it can be placed into the default variable.

                 

                The thing passed into "perform" should be an operation. I suggest creating a subclass of AbstractIterationOperation with a perform method that looks something like this (this could be in an inner class if you want):

                 

                public abstract void perform(GraphRewrite event, EvaluationContext context, FileLocationModel payload) {

                    if (list.contains(source)) {

                          counter++;

                    } else {

                          list.add(source);

                     }

                     ClassificationService classificationService = new ClassificationService(graphContext);

                     classificationService.attachClassification(context, payload.getFIle(), "Title: " + payload.getSourceSnippit(), "Count: " + counter);

                }

                 

                I think that is closer to what you are trying to achieve.

                • 5. Re: A few questions, mostly about parameterization
                  wstafford

                  Alright, I'm going to look into this approach. I'll mark it correct for now, but I might reopen if I have some trouble implementing it. Thanks guys!