From 317a362f3146bcf288aa560d4338272cd1f32f91 Mon Sep 17 00:00:00 2001 From: Sande Gilda Date: Fri, 12 Dec 2014 14:33:02 -0500 Subject: [PATCH] Fix broken links in guides and copy in missing pages --- Dev-Dependencies.adoc | 125 ++++++++++ Get-Involved.adoc | 2 +- Review-the-Report.adoc | 2 +- Rules-Available-Rules-Utilities.adoc | 111 +++++++++ Rules-Create-a-Basic-XML-Rule.adoc | 2 +- Rules-Java-based-Rule-Structure.adoc | 2 +- Rules-Windup-Models.adoc | 26 +++ Windup-Rules-Development-Guide.adoc | 5 +- Windup-User-Guide.adoc | 1 + WindupRulesDevelopmentGuide.html | 335 ++++++++++++++++++++++++++- WindupUserGuide.html | 45 +++- 11 files changed, 642 insertions(+), 14 deletions(-) create mode 100644 Dev-Dependencies.adoc create mode 100644 Rules-Available-Rules-Utilities.adoc create mode 100644 Rules-Windup-Models.adoc diff --git a/Dev-Dependencies.adoc b/Dev-Dependencies.adoc new file mode 100644 index 0000000000..30e5917bf9 --- /dev/null +++ b/Dev-Dependencies.adoc @@ -0,0 +1,125 @@ +[[Dev-Dependencies]] +=== Dependencies (Forge add-ons) + +DRAFT _Based on +https://github.com/OndraZizka/windup/commit/3574e81900cbad2b3a83d0bd6c263eb22c48e55e[this] +discussion._ + +==== Maven Add-on Structure + +The following is the typical structure of Maven `add-on` modules. + +------------------------------------------- +myaddon-parent ++--- myaddon - jar, classifier: forge-addon ++--- myaddon-api - jar ++--- myaddon-impl - jar ++--- myaddon-tests - jar +------------------------------------------- + +The `add-on` POM file can declare dependencies on other forge-addons. +To prevent exporting the add-on to dependent modules, use `true`. + +[source,xml] +---- + + org.jboss.forge.furnace.container + cdi + forge-addon + true + +---- + +The `add-on` POM files may also declare a dependency on typical Maven artifacts. +To prevent exporting the add-on to dependent modules, use `true`. + +[source,xml] +---- + + com.thinkaurelius.titan + titan-lucene + ${version.titangraph.lucene} + +---- + +_One more question regarding dependencies. Is it advisable to depend on the`forge-addon` +artifact from add-on's subparts?_ + +Add-ons should reference the `forge-addon` +artifact from other add-ons. + +==== Add-on sub-parts + +Add-on sub-parts declare dependency preferably on forge add-on APIs, not +on the add-ons themselves, wherever possible (wherever an add-on has an +explicit API). These dependencies must be marked as `provided` scope. + +[source,xml] +---- + + org.jboss.forge.furnace.container + cdi-api + forge-addon + provided + +---- + +They may instead depend on the primary add-on dependency, e.g. +`forge-addon`. The latter makes the POM files simpler, but can be confusing, +because the add-on dependency still needs to be declared in the depending +add-on's POM. + +[source,xml] +---- + + org.jboss.forge.furnace.container + cdi-api + +---- + +Declaring a `forge-addon` depencendy anywhere else than the +`forge-addon` pom doesn't actually cause Furnace to establish an add-on +dependency. I.e. classes from the dep won't be available unless you +declare it in the `forge-addon`'s pom. + +Add-on's sub-parts may also declare dependencies on other normal maven +dependencies, and these are treated as normal. + +[NOTE] +========================== +Add-on depends on API , scope `compile` > Addon +depends on Impl , scope `compile` with `true` - +prevents exporting this dependency to consumers of the add-on. +========================== + +==== Test dependencies + +For test dependencies on add-ons: Any addon/sub-part requiring an addon +for testing purposes should use `test`. + +[source,xml] +---- + + org.jboss.windup.graph + windup-graph + ${project.version} + forge-addon + test + +---- + +==== Dependencies between sub-parts within the same add-on + + +Subpart may declare dependency on other subpart. E.g. `impl` typically +depends on `api`. In that case, the scope should be set appropriately +for the given situation - typically `provided` or `compile` scope. + +[source,xml] +---- + + org.jboss.windup.graph + windup-graph-api + compile + +---- diff --git a/Get-Involved.adoc b/Get-Involved.adoc index df805e4bfe..ebc4f7e82b 100644 --- a/Get-Involved.adoc +++ b/Get-Involved.adoc @@ -10,7 +10,7 @@ To help us make Windup cover most application constructs and server configuratio * Identify application components and problem areas that may be difficult to migrate. ** Write a short description of these problem migration areas. ** Write a brief guide describing how to solve the problem migration areas. -* link:Execute-Windup[Try Windup] on your application. Be sure to link:Report-Issues-with-Windup[report any issues] you encounter. +* xref:Execute-Windup[Try Windup] on your application. Be sure to xref:Report-Issues-with-Windup[report any issues] you encounter. * Write an Windup rule to automate the migration process. ** Create a test for the new rule. * You can contribute Windup rules. For details, see the _Windup Rules Development Guide_. diff --git a/Review-the-Report.adoc b/Review-the-Report.adoc index 22340300e0..8c9ad5c6b8 100644 --- a/Review-the-Report.adoc +++ b/Review-the-Report.adoc @@ -95,7 +95,7 @@ The `OUTPUT_REPORT_DIRECTORY/reports/ruleproviders.html` page provides the list ===== Individual File Analysis Reports -You can directly access the the xref:Review-the-Report#file-analysis-pages[file analysis report pages] described above by browsing for them by name in the `OUTPUT_REPORT_DIRECTORY/reports/` directory. Because the same common file names can exist in multiple archives, for example "manifest.mf" or "web.xml", Windup adds a unique numeric suffix to each report file name. +You can directly access the the file analysis report pages described above by browsing for them by name in the `OUTPUT_REPORT_DIRECTORY/reports/` directory. Because the same common file names can exist in multiple archives, for example "manifest.mf" or "web.xml", Windup adds a unique numeric suffix to each report file name. image:images/report-directory-file-list.png[Report Directory File List, 500] diff --git a/Rules-Available-Rules-Utilities.adoc b/Rules-Available-Rules-Utilities.adoc new file mode 100644 index 0000000000..e5632fd225 --- /dev/null +++ b/Rules-Available-Rules-Utilities.adoc @@ -0,0 +1,111 @@ +[[Rules-Available-Rules-Utilities]] +=== Available Rule Utilities + +==== Programmatically Access the Graph + +_Note: Needs update. This is out of date!_ + +(Lower Level API, to cover cases not provided by high level API) + + +This topic describes how to to programmatically access or update graph data when you create a Java-based rule addon. + +===== Query the graph + +There are several ways - including Query API, Gremlin support, or +GraphService methods. + +====== Query the Graph Within the .when() method + +Building a rule contains the method when(), which is used to create a +*condition*. Vertices that fulfill the condition, are passed to the +perform() method. + +For the queries in the when() method, class Query is used. There are +several methods which you can use to specify the condition. For example: +* *find()* specifies the Model type of the vertex * *as()* method +specifies the name of the final list, that is passed to the perform() +method * *from(String name)* starts the query not on the all vertices, +but only on the vertices already stored in the the given *name* (used to +begin query on the result of the other one) * *withProperty()* specify +the property value of the given vertex + +The following are examples of simple queries. + +Return a list of archives + +[source,java] +---- +Query.find(ArchiveModel.class) +---- + +[source,java] +---- +Query.find(ApplicationReportModel.class).as(VAR_APPLICATION_REPORTS) +---- + + +====== Iteration + +[source,java] +---- +ConfigurationBuilder.begin().addRule() + .when( + GraphSearchConditionBuilderGremlin.create("javaFiles", new ArrayList()) + .V().framedType( JavaFileModel.class ).has("analyze") + ) + .perform( + // For all java files... + Iteration.over("javaFiles").var("javaFile").perform( +---- + +====== Nested Iteration + +[source,java] +---- +code,java +// For all java files... +Iteration.over("javaFiles").var("javaFile").perform( + // A nested rule. + RuleSubset.evaluate( + ConfigurationBuilder.begin().addRule() + .when(...) + .perform( + Iteration.over("regexes").var(RegexModel.class, "regex").perform( + new AbstractIterationOperator( RegexModel.class, "regex" ) { + public void perform( GraphRewrite event, EvaluationContext context, RegexModel regex ) { + //... + } + } + ) + .endIteration() + )// perform() + ) +) +---- + +==== Modify Graph Data + +For more custom operations dealing with Graph data that are not covered by the `Query` mechanism, use the GraphService. + +[source,java] +---- +GraphService fooService = new GraphService(graph,FooModel.class); + +List = fooService.findAll(); +FooModel = fooService.create(); + +// etc ... +---- + +GraphService<> can also be used to query the graph for models of the specified type: + +[source,java] +---- +FooModel foo = new GraphService<>(graphContext, FooModel.class).getUnique(); +---- + +[source,java] +---- +FooModel foo = new GraphService<>(graphContext, FooModel.class).getUniqueByProperty("size", 1); +---- diff --git a/Rules-Create-a-Basic-XML-Rule.adoc b/Rules-Create-a-Basic-XML-Rule.adoc index 1931116c16..f856a15afe 100644 --- a/Rules-Create-a-Basic-XML-Rule.adoc +++ b/Rules-Create-a-Basic-XML-Rule.adoc @@ -69,7 +69,7 @@ The following is an example of an XML rule. The XML rule consists of the following level elements: * ****: This element defines this as a Windup rule. -* ****: This element specifies when the ruleset should execute. See xref:Rules-Rules-Execution-Lifecycle#rule-phases[Rule Phases in the Rule Execution Lifecyle] for more information. +* ****: This element specifies when the ruleset should execute. See xref:Rules-Rule-Execution-Lifecycle[Rule Execution Lifecyle] for more information about rule phases. * ****: element contains the individual rules. ** ****: This element is a child of the **rules** element. One or more rules can be defined for a ruleset. Each `rule` contains the following elements. *** ****: This element defines the condition to match on. diff --git a/Rules-Java-based-Rule-Structure.adoc b/Rules-Java-based-Rule-Structure.adoc index a69258360c..f9d114a26b 100644 --- a/Rules-Java-based-Rule-Structure.adoc +++ b/Rules-Java-based-Rule-Structure.adoc @@ -132,4 +132,4 @@ and not actually used, is `RuleMetadata.CATEGORY`. ==== Available utilities For a list of what key services and constructs can be used in the rule, -see xref:Rules-Available-Utilities[Available Rules Utilities]. \ No newline at end of file +see xref:Rules-Available-Rules-Utilities[Available Rules Utilities]. diff --git a/Rules-Windup-Models.adoc b/Rules-Windup-Models.adoc new file mode 100644 index 0000000000..ef7c83bb93 --- /dev/null +++ b/Rules-Windup-Models.adoc @@ -0,0 +1,26 @@ +[[Rules-Windup-Models]] +=== Windup Models + +Windup models are the classes extending WindupVertexFrame. +They are used to model the data in the graph database to Java objects. + +This is an overview of the most important models. +The complete and up-to-date list of models is in link:http://windup.github.io/windup/docs/javadoc/latest/org/jboss/windup/graph/model/WindupVertexFrame.html[Javadoc]. + +image:img/WindupModels-NbScreenshot.png[Windup Models Graphic] + +==== Meta Models + +* User input +* Rules and Rule Providers metadata + +==== Core Models + +FileModel ArchiveModel + +==== Reporting Models + + +==== Custom Models (coming from Addons) + +See respective ruleset's documentation. \ No newline at end of file diff --git a/Windup-Rules-Development-Guide.adoc b/Windup-Rules-Development-Guide.adoc index 584755ea4b..320701bb94 100644 --- a/Windup-Rules-Development-Guide.adoc +++ b/Windup-Rules-Development-Guide.adoc @@ -73,15 +73,16 @@ include::Dev-Troubleshoot-Windup-Issues.adoc[tabsize=4] == Additional Resources +include::Rules-Available-Rules-Utilities.adoc[tabsize=4] include::Review-the-Windup-Quickstarts.adoc[tabsize=4] - include::Known-Issues.adoc[tabsize=4] - include::Glossary.adoc[tabsize=4] == Appendix include::Dev-Windup-Architectural-Components.adoc[tabsize=4] +include::Dev-Dependencies.adoc[tabsize=4] +include::Rules-Windup-Models.adoc[tabsize=4] diff --git a/Windup-User-Guide.adoc b/Windup-User-Guide.adoc index bc1e7c886b..6aa7590665 100644 --- a/Windup-User-Guide.adoc +++ b/Windup-User-Guide.adoc @@ -42,6 +42,7 @@ include::Glossary.adoc[tabsize=4] == Appendix include::Dev-Windup-Architectural-Components.adoc[tabsize=4] +include::Rules-Rule-Story-Points.adoc[tabsize=4] diff --git a/WindupRulesDevelopmentGuide.html b/WindupRulesDevelopmentGuide.html index 0cd5618bd2..cd147769c4 100644 --- a/WindupRulesDevelopmentGuide.html +++ b/WindupRulesDevelopmentGuide.html @@ -474,6 +474,7 @@

Windup User Guide

  • Additional Resources @@ -776,7 +779,7 @@

    How can you help?

  • -

    Try Windup on your application. Be sure to report any issues you encounter.

    +

    Try Windup on your application. Be sure to report any issues you encounter.

  • Write an Windup rule to automate the migration process.

    @@ -1319,7 +1322,7 @@
    Rule Provider Execution Report
    Individual File Analysis Reports
    -

    You can directly access the the file analysis report pages described above by browsing for them by name in the OUTPUT_REPORT_DIRECTORY/reports/ directory. Because the same common file names can exist in multiple archives, for example "manifest.mf" or "web.xml", Windup adds a unique numeric suffix to each report file name.

    +

    You can directly access the the file analysis report pages described above by browsing for them by name in the OUTPUT_REPORT_DIRECTORY/reports/ directory. Because the same common file names can exist in multiple archives, for example "manifest.mf" or "web.xml", Windup adds a unique numeric suffix to each report file name.

    Report Directory File List

    @@ -1861,7 +1864,7 @@
    Metadata

    Available utilities

    For a list of what key services and constructs can be used in the rule, -see Available Rules Utilities.

    +see Available Rules Utilities.

    @@ -2579,7 +2582,7 @@
    Create the XML Rule

    <ruleset>: This element defines this as a Windup rule.

  • -

    <phase>: This element specifies when the ruleset should execute. See Rule Phases in the Rule Execution Lifecyle for more information.

    +

    <phase>: This element specifies when the ruleset should execute. See Rule Execution Lifecyle for more information about rule phases.

  • <rules>: element contains the individual rules.

    @@ -2898,7 +2901,7 @@
    Rule Provider Execution Report
    Individual File Analysis Reports
    -

    You can directly access the the file analysis report pages described above by browsing for them by name in the OUTPUT_REPORT_DIRECTORY/reports/ directory. Because the same common file names can exist in multiple archives, for example "manifest.mf" or "web.xml", Windup adds a unique numeric suffix to each report file name.

    +

    You can directly access the the file analysis report pages described above by browsing for them by name in the OUTPUT_REPORT_DIRECTORY/reports/ directory. Because the same common file names can exist in multiple archives, for example "manifest.mf" or "web.xml", Windup adds a unique numeric suffix to each report file name.

    Report Directory File List

    @@ -3124,6 +3127,132 @@

    Classloading Problems

    Additional Resources

    +

    Available Rule Utilities

    +
    +

    Programmatically Access the Graph

    +
    +

    Note: Needs update. This is out of date!

    +
    +
    +

    (Lower Level API, to cover cases not provided by high level API)

    +
    +
    +

    This topic describes how to to programmatically access or update graph data when you create a Java-based rule addon.

    +
    +
    +
    Query the graph
    +
    +

    There are several ways - including Query API, Gremlin support, or +GraphService methods.

    +
    +
    +
    Query the Graph Within the .when() method
    +
    +

    Building a rule contains the method when(), which is used to create a +condition. Vertices that fulfill the condition, are passed to the +perform() method.

    +
    +
    +

    For the queries in the when() method, class Query is used. There are +several methods which you can use to specify the condition. For example: +* find() specifies the Model type of the vertex * as() method +specifies the name of the final list, that is passed to the perform() +method * from(String name) starts the query not on the all vertices, +but only on the vertices already stored in the the given name (used to +begin query on the result of the other one) * withProperty() specify +the property value of the given vertex

    +
    +
    +

    The following are examples of simple queries.

    +
    +
    +

    Return a list of archives

    +
    +
    +
    +
    Query.find(ArchiveModel.class)
    +
    +
    +
    +
    +
    Query.find(ApplicationReportModel.class).as(VAR_APPLICATION_REPORTS)
    +
    +
    +
    +
    +
    Iteration
    +
    +
    +
    ConfigurationBuilder.begin().addRule()
    +    .when(
    +        GraphSearchConditionBuilderGremlin.create("javaFiles", new ArrayList())
    +        .V().framedType( JavaFileModel.class ).has("analyze")
    +    )
    +    .perform(
    +        // For all java files...
    +        Iteration.over("javaFiles").var("javaFile").perform(
    +
    +
    +
    +
    +
    Nested Iteration
    +
    +
    +
    code,java
    +// For all java files...
    +Iteration.over("javaFiles").var("javaFile").perform(
    +    // A nested rule.
    +    RuleSubset.evaluate(
    +        ConfigurationBuilder.begin().addRule()
    +        .when(...)
    +        .perform(
    +            Iteration.over("regexes").var(RegexModel.class, "regex").perform(
    +                new AbstractIterationOperator<RegexModel>( RegexModel.class, "regex" ) {
    +                    public void perform( GraphRewrite event, EvaluationContext context, RegexModel regex ) {
    +                        //...
    +                    }
    +                }
    +            )
    +            .endIteration()
    +        )// perform()
    +    )
    +)
    +
    +
    +
    +
    +
    +
    +

    Modify Graph Data

    +
    +

    For more custom operations dealing with Graph data that are not covered by the Query mechanism, use the GraphService.

    +
    +
    +
    +
    GraphService<FooModel> fooService = new GraphService<FooModel>(graph,FooModel.class);
    +
    +List<FooModel> = fooService.findAll();
    +FooModel = fooService.create();
    +
    +// etc ...
    +
    +
    +
    +

    GraphService<> can also be used to query the graph for models of the specified type:

    +
    +
    +
    +
    FooModel foo = new GraphService<>(graphContext, FooModel.class).getUnique();
    +
    +
    +
    +
    +
    FooModel foo = new GraphService<>(graphContext, FooModel.class).getUniqueByProperty("size", 1);
    +
    +
    +
    +
    +

    Review the Windup Quickstarts

    The Windup quickstarts provide working examples of how to create custom Java-based rule addons and XML rules. You can use them as a starting point for creating your own custom rules. The quickstarts are available on GitHub here: https://github.com/windup/windup-quickstarts

    @@ -3408,12 +3537,206 @@

    OCPsoft Rewrite

    +
    +

    Dependencies (Forge add-ons)

    +
    +

    DRAFT Based on +this +discussion.

    +
    +
    +

    Maven Add-on Structure

    +
    +

    The following is the typical structure of Maven add-on modules.

    +
    +
    +
    +
    myaddon-parent
    ++--- myaddon - jar, classifier: forge-addon
    ++--- myaddon-api - jar
    ++--- myaddon-impl - jar
    ++--- myaddon-tests - jar
    +
    +
    +
    +

    The add-on POM file can declare dependencies on other forge-addons. +To prevent exporting the add-on to dependent modules, use <optional>true</optional>.

    +
    +
    +
    +
    <dependency>
    +    <groupId>org.jboss.forge.furnace.container</groupId>
    +    <artifactId>cdi</artifactId>
    +    <classifier>forge-addon</classifier>
    +    <optional>true</optional>
    +</dependency>
    +
    +
    +
    +

    The add-on POM files may also declare a dependency on typical Maven artifacts. +To prevent exporting the add-on to dependent modules, use <optional>true</optional>.

    +
    +
    +
    +
    <dependency>
    +    <groupId>com.thinkaurelius.titan</groupId>
    +    <artifactId>titan-lucene</artifactId>
    +    <version>${version.titangraph.lucene}</version>
    +</dependency>
    +
    +
    +
    +

    One more question regarding dependencies. Is it advisable to depend on the`forge-addon` +artifact from add-on’s subparts?

    +
    +
    +

    Add-ons should reference the <classifier>forge-addon</classifier> +artifact from other add-ons.

    +
    +
    +
    +

    Add-on sub-parts

    +
    +

    Add-on sub-parts declare dependency preferably on forge add-on APIs, not +on the add-ons themselves, wherever possible (wherever an add-on has an +explicit API). These dependencies must be marked as provided scope.

    +
    +
    +
    +
    <dependency>
    +    <groupId>org.jboss.forge.furnace.container</groupId>
    +    <artifactId>cdi-api</artifactId>
    +    <classifier>forge-addon</classifier>
    +    <scope>provided</scope>
    +</dependency>
    +
    +
    +
    +

    They may instead depend on the primary add-on dependency, e.g. +forge-addon. The latter makes the POM files simpler, but can be confusing, +because the add-on dependency still needs to be declared in the depending +add-on’s POM.

    +
    +
    +
    +
    <dependency>
    +    <groupId>org.jboss.forge.furnace.container</groupId>
    +    <artifactId>cdi-api</artifactId>
    +</dependency>
    +
    +
    +
    +

    Declaring a forge-addon depencendy anywhere else than the +forge-addon pom doesn’t actually cause Furnace to establish an add-on +dependency. I.e. classes from the dep won’t be available unless you +declare it in the `forge-addon’s pom.

    +
    +
    +

    Add-on’s sub-parts may also declare dependencies on other normal maven +dependencies, and these are treated as normal.

    +
    +
    + + + + + +
    +
    Note
    +
    +
    +

    Add-on depends on API , scope compile > Addon +depends on Impl , scope compile with <optional>true</optional> - +prevents exporting this dependency to consumers of the add-on.

    +
    +
    +
    +
    +
    +

    Test dependencies

    +
    +

    For test dependencies on add-ons: Any addon/sub-part requiring an addon +for testing purposes should use <scope>test</scope>.

    +
    +
    +
    +
    <dependency>
    +    <groupId>org.jboss.windup.graph</groupId>
    +    <artifactId>windup-graph</artifactId>
    +    <version>${project.version}</version>
    +    <classifier>forge-addon</classifier>
    +    <scope>test</scope>
    +</dependency>
    +
    +
    +
    +
    +

    Dependencies between sub-parts within the same add-on

    +
    +

    Subpart may declare dependency on other subpart. E.g. impl typically +depends on api. In that case, the scope should be set appropriately +for the given situation - typically provided or compile scope.

    +
    +
    +
    +
    <dependency>
    +    <groupId>org.jboss.windup.graph</groupId>
    +    <artifactId>windup-graph-api</artifactId>
    +    <scope>compile</scope>
    +</dependency>
    +
    +
    +
    +
    +
    +

    Windup Models

    +
    +

    Windup models are the classes extending WindupVertexFrame. +They are used to model the data in the graph database to Java objects.

    +
    +
    +

    This is an overview of the most important models. +The complete and up-to-date list of models is in Javadoc.

    +
    +
    +

    Windup Models Graphic

    +
    +
    +

    Meta Models

    +
    +
      +
    • +

      User input

      +
    • +
    • +

      Rules and Rule Providers metadata

      +
    • +
    +
    +
    +
    +

    Core Models

    +
    +

    FileModel ArchiveModel

    +
    +
    +
    +

    Reporting Models

    + +
    +
    +

    Custom Models (coming from Addons)

    +
    +

    See respective ruleset’s documentation.

    +
    +
    +
    diff --git a/WindupUserGuide.html b/WindupUserGuide.html index fac03690c9..e91b233314 100644 --- a/WindupUserGuide.html +++ b/WindupUserGuide.html @@ -442,6 +442,7 @@

    Windup User Guide

  • Appendix
  • @@ -736,7 +737,7 @@

    How can you help?

  • -

    Try Windup on your application. Be sure to report any issues you encounter.

    +

    Try Windup on your application. Be sure to report any issues you encounter.

  • Write an Windup rule to automate the migration process.

    @@ -1577,12 +1578,52 @@

    OCPsoft Rewrite

    +
    +

    Rule Story Points

    +
    +

    What are Story Points?

    +
    +

    Story points are an abstract metric used in Scrum methodology to estimate the level of effort for various tasks. They are based on a modified Fibonacci sequence. In a similar manner, Windup uses story points to express the level of effort needed to migrate particular application constructs, and in a sum, the application as a whole.

    +
    +
    +
    +

    How to Estimate Story Points in a Rule

    +
    +

    TODO: TBD.

    +
    +
    +

    This could contain relative examples like:

    +
    +
    +
      +
    • +

      Pure copy’n’paste - when we know for sure it will need no migration: 0

      +
    • +
    • +

      When we don’t know if it will need a migration: Could depend on number of unknown imports, size +of the file, …​

      +
    • +
    • +

      Changing parameter name, or value units: 2.

      +
    • +
    • +

      Porting one web page (or similar concept) from one web framework to +the other: Could depend on complexity, e.g. number of components. E.g. +20 per component.

      +
    • +
    • +

      Porting MyBatis to JPA: 20 per query.

      +
    • +
    +
    +
    +