diff --git a/build.gradle b/build.gradle index 33c84c1..ba42435 100644 --- a/build.gradle +++ b/build.gradle @@ -40,10 +40,11 @@ dependencies { // Look for it in the local build directory // You must run `./gradle build -x test` in the BoxLang project // compileOnly files( '../boxlang/build/libs/boxlang-' + boxlangVersion + '-all.jar' ) + compileOnly files( '../../boxlang/build/distributions/boxlang-' + boxlangVersion + '-all.jar' ) compileOnly files( 'src/test/resources/libs/boxlang-' + boxlangVersion + '-all.jar' ) // Testing Dependencies - // testImplementation files( '../boxlang/build/libs/boxlang-' + boxlangVersion + '-all.jar' ) + testImplementation files( '../../boxlang/build/distributions/boxlang-' + boxlangVersion + '-all.jar' ) testImplementation files( 'src/test/resources/libs/boxlang-' + boxlangVersion + '-all.jar' ) testImplementation "org.junit.jupiter:junit-jupiter:5.+" testImplementation "org.mockito:mockito-core:5.+" diff --git a/changelog.md b/changelog.md index e452641..9dbac89 100644 --- a/changelog.md +++ b/changelog.md @@ -9,6 +9,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +* `CFIDE` mapping for compatibility for `orm` and `scheduler` interfaces +* More integration tests +* `Client` scope +* Many more test scenarios +* `struckKeyExists()` transpilers + ## [1.12.0] - 2024-11-15 ## [1.11.0] - 2024-10-31 diff --git a/src/main/bx/CFIDE/orm/IEventHandler.cfc b/src/main/bx/CFIDE/orm/IEventHandler.cfc new file mode 100755 index 0000000..8b8bc4c --- /dev/null +++ b/src/main/bx/CFIDE/orm/IEventHandler.cfc @@ -0,0 +1,59 @@ +/** + * Event handler for ORM Events. This should be used as a global application wide handler that can be set in the application + * using ormsettings.eventHandler=MyEventHandler. These events can be handled by the application to perform any pre or post + * actions for all ORM operations. + */ +Interface +{ + /** + * Called before injecting property values into a newly loaded entity instance. + */ + public void function preLoad(any entity); + + /** + * Called after an entity is fully loaded. + */ + public void function postLoad(any entity); + + /** + * Called before inserting the enetity into the database. + */ + public void function preInsert(any entity); + + /** + * Called after the entity is inserted into the database. + */ + public void function postInsert(any entity); + + /** + * Called before the entity is updated in the database. + */ + public void function preUpdate(any entity, Struct oldData); + + /** + * Called after the entity is updated in the database. + */ + public void function postUpdate(any entity); + + + /** + * Called before the entity is deleted from the database. + */ + public void function preDelete(any entity); + + /** + * Called after deleting an item from the datastore + */ + public void function postDelete(any entity); + + /** + * Called before the session is flushed. + */ + public void function preFlush(any entities); + + /** + * Called after the session is flushed. + */ + public void function postFlush(any entities); + +} diff --git a/src/main/bx/CFIDE/orm/INamingStrategy.cfc b/src/main/bx/CFIDE/orm/INamingStrategy.cfc new file mode 100755 index 0000000..58158bb --- /dev/null +++ b/src/main/bx/CFIDE/orm/INamingStrategy.cfc @@ -0,0 +1,21 @@ +/** + * Strategy to specify the table name for a CFC and column name for a property in the cfc. + * This can be used to specify the application specific table and column naming convention. + * This rule will be applied even if the user has specified the table/column name in the mapping so that + * the name can be changed for any application at one place without changing the names in all the code. + */ +interface +{ + /** + * Defines the table name to be used for a specified table name. The specified table name is either + * the table name specified in the mapping or chosen using the entity name. + */ + public string function getTableName(string tableName); + + /** + * Defines the column name to be used for a specified column name. The specified column name is either + * the column name specified in the mapping or chosen using the proeprty name. + */ + public string function getColumnName(string columnName); + +} \ No newline at end of file diff --git a/src/main/bx/CFIDE/scheduler/ITaskEventHandler.cfc b/src/main/bx/CFIDE/scheduler/ITaskEventHandler.cfc new file mode 100755 index 0000000..5a0c88d --- /dev/null +++ b/src/main/bx/CFIDE/scheduler/ITaskEventHandler.cfc @@ -0,0 +1,29 @@ +/** + * Event handler for Scheduler tasks Events. + */ +Interface +{ /** + * Called when job is about to be executed.If this returns false, CF will veto the job and wont execute it + */ + public boolean function onTaskStart(Struct context); + + /** + * Called once execution of the task is over + */ + public void function onTaskEnd(Struct context); + + /** + * Called when a task gets misfired + */ + public void function onMisfire(Struct context); + + /** + * Called when a task throws an runtime exception + */ + public void function onError(Struct context); + + /** + * Called when URL is not specified.Instead this method will be invoked on scheduled times + */ + public void function execute(Struct context); +} diff --git a/src/main/bx/ModuleConfig.bx b/src/main/bx/ModuleConfig.bx index 3bf82bd..59e1c78 100644 --- a/src/main/bx/ModuleConfig.bx +++ b/src/main/bx/ModuleConfig.bx @@ -19,6 +19,12 @@ import ortus.boxlang.runtime.context.BaseBoxContext; property name="moduleRecord"; property name="boxRuntime"; property name="interceptorService"; + property name="functionService"; + property name="componentService"; + property name="cacheService"; + property name="asyncService"; + property name="schedulerService"; + property name="datasourceService"; property name="log"; // Static properties @@ -65,7 +71,7 @@ import ortus.boxlang.runtime.context.BaseBoxContext; /** * This boolean flag tells the module service to skip the module registration/activation process. */ - this.disabled = false; + this.enabled = true; /** * -------------------------------------------------------------------------- @@ -196,6 +202,7 @@ import ortus.boxlang.runtime.context.BaseBoxContext; moduleRecord ); + // Register the Client Scope Cache var cacheService = boxRuntime.getCacheService(); if ( !cacheService.hasCache( "bxClients" ) ) { boxRuntime.getCacheService().createCache( @@ -215,6 +222,9 @@ import ortus.boxlang.runtime.context.BaseBoxContext; } ); } + + // Register the CFIDE Mapping for compatibility + boxRuntime.getConfiguration().registerMapping( "CFIDE", variables.moduleRecord.path & "/CFIDE" ); } /** diff --git a/src/test/java/ortus/boxlang/modules/compat/BaseIntegrationTest.java b/src/test/java/ortus/boxlang/modules/compat/BaseIntegrationTest.java index b42d57f..ba1b07c 100644 --- a/src/test/java/ortus/boxlang/modules/compat/BaseIntegrationTest.java +++ b/src/test/java/ortus/boxlang/modules/compat/BaseIntegrationTest.java @@ -14,6 +14,7 @@ */ package ortus.boxlang.modules.compat; +import java.nio.file.Path; import java.nio.file.Paths; import org.junit.jupiter.api.BeforeAll; @@ -29,7 +30,11 @@ import ortus.boxlang.runtime.services.CacheService; import ortus.boxlang.runtime.services.ModuleService; -public class BaseIntegrationTest { +/** + * Use this as a base integration test for your non web-support package + * modules. If you want web based testing, use the BaseWebIntegrationTest + */ +public abstract class BaseIntegrationTest { protected static BoxRuntime runtime; protected static ModuleService moduleService; @@ -41,11 +46,11 @@ public class BaseIntegrationTest { @BeforeAll public static void setup() { - runtime = BoxRuntime.getInstance( true ); + runtime = BoxRuntime.getInstance( true, Path.of( "src/test/resources/boxlang.json" ).toString() ); moduleService = runtime.getModuleService(); cacheService = runtime.getCacheService(); - context = new ScriptingRequestBoxContext( runtime.getRuntimeContext() ); - loadModule( context ); + // Load the module + loadModule( runtime.getRuntimeContext() ); } @BeforeEach @@ -54,19 +59,21 @@ public void setupEach() { variables = context.getScopeNearby( VariablesScope.name ); } - @SuppressWarnings( "unused" ) protected static void loadModule( IBoxContext context ) { if ( !runtime.getModuleService().hasModule( moduleName ) ) { + System.out.println( "===> Loading module: " + moduleName ); String physicalPath = Paths.get( "./build/module" ).toAbsolutePath().toString(); ModuleRecord moduleRecord = new ModuleRecord( physicalPath ); + moduleService.getRegistry().put( moduleName, moduleRecord ); + // When moduleRecord .loadDescriptor( context ) .register( context ) .activate( context ); - - moduleService.getRegistry().put( moduleName, moduleRecord ); + } else { + System.out.println( "===> Module already loaded: " + moduleName ); } } diff --git a/src/test/java/ortus/boxlang/modules/compat/IntegrationTest.java b/src/test/java/ortus/boxlang/modules/compat/IntegrationTest.java index 8d6f2ca..0937bdf 100644 --- a/src/test/java/ortus/boxlang/modules/compat/IntegrationTest.java +++ b/src/test/java/ortus/boxlang/modules/compat/IntegrationTest.java @@ -5,6 +5,8 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import ortus.boxlang.runtime.scopes.Key; + /** * This loads the module and runs an integration test on the module. */ @@ -14,5 +16,10 @@ public class IntegrationTest extends BaseIntegrationTest { @Test public void testModuleLoads() { assertThat( moduleService.getRegistry().containsKey( moduleName ) ).isTrue(); + + // Verify that the CFIDE mapping was registered + assertThat( + runtime.getConfiguration().hasMapping( Key.of( "CFIDE" ) ) + ).isTrue(); } } diff --git a/src/test/resources/boxlang.json b/src/test/resources/boxlang.json new file mode 100644 index 0000000..1e893c4 --- /dev/null +++ b/src/test/resources/boxlang.json @@ -0,0 +1,3 @@ +{ + "modules": {} +}