Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
a0d4f9d
#2750 Added locale to fullcalendar configuration to properly format d…
oleh-maikovych May 27, 2026
231331e
#2750 Implemented entity splitting into parts to add long lasting eve…
oleh-maikovych May 27, 2026
342e19d
#2750 Minor code cleanup.
oleh-maikovych May 27, 2026
d9ad20c
#2755 Trim '@DateOnly' property time portion for 'n' approximation.
jhou-pro May 31, 2026
69c260a
Merge branch 'Issue-#2716-independent-from-#2224' into Issue-#2755
jhou-pro Jun 1, 2026
61291e3
#2755 Resolve the current moment via `now(prop)` instead of `_momentT…
jhou-pro Jun 1, 2026
e90d544
#2755 Convert JS docs to MarkDown style.
jhou-pro Jun 1, 2026
72c074a
Merge branch 'Issue-#2716-independent-from-#2224' into Issue-#2755
jhou-pro Jun 1, 2026
696fd86
#2755 Web tests for date-only 'n' approximations to covert to actual …
jhou-pro Jun 1, 2026
22df49e
#2755 Small correction for web tests.
jhou-pro Jun 1, 2026
038973e
Merge branch 'Issue-#2716-independent-from-#2224' into Issue-#2755
jhou-pro Jun 2, 2026
f997eec
#2765 Remove caching of generic SQL type names
homedirectory Jun 12, 2026
2bf5fb2
Merge branch 'develop' into Issue-#2750
jhou-pro Jun 18, 2026
1c56cdc
Merge pull request #2751 from fieldenms/Issue-#2750
01es Jun 18, 2026
1a9855e
Merge branch 'develop' into Issue-#2765
01es Jun 18, 2026
c303ab6
Merge pull request #2766 from fieldenms/Issue-#2765
01es Jun 18, 2026
a70df23
Update versions for release 2.4.4
01es Jun 18, 2026
0c12faf
Merge branch 'release-2.4.4' into develop
01es Jun 18, 2026
3fcca2d
Update versions to 2.4.5-SNAPSHOT
01es Jun 18, 2026
2ec887a
#2768 Update `fullcalendar` dependency from 6.1.20 to 6.1.21 (no-tree…
jhou-pro Jun 20, 2026
6f0c42f
#2768 Update `RichText` editor => `@toast-ui/editor` => `dompurify` t…
jhou-pro Jun 20, 2026
58f91a8
#2768 Patch updates for `RichText` editor => `@toast-ui/editor` => `p…
jhou-pro Jun 20, 2026
bd7ab3d
#2768 Minor / patch updates for web test infrastructure development d…
jhou-pro Jun 20, 2026
196d094
#2768 Enforce the lowest possible and safe `dompurify` dependency.
jhou-pro Jun 20, 2026
68757ba
#2768 Enforce the lowest possible and safe `dompurify` dependency.
jhou-pro Jun 20, 2026
77db6fe
Merge pull request #2769 from fieldenms/Issue-#2768
01es Jun 22, 2026
d779bd5
Program instructions: Fixed Entity Instances
homedirectory Jun 26, 2026
3a834f0
Merge pull request #2770 from fieldenms/program-instructions-fixed-en…
01es Jun 27, 2026
2dbc626
#2780 Wrapped paper icon button in egi cell into dom-if to increased …
oleh-maikovych Jul 3, 2026
f779dd2
#2780 Deferred tg-fullcalendar event source rebuild while hidden; bat…
01es Jul 5, 2026
57381f4
#2780 EGI rendering optimisations: O(1) entity index lookups, on-dema…
01es Jul 5, 2026
986ceaf
#2780 EGI improvements: extracted HTML comments to JS to avoid repeti…
01es Jul 7, 2026
592d0b7
#2780 Latched navigate-to-first-event intent for tg-fullcalendar rebu…
01es Jul 7, 2026
ab9addf
Merge pull request #2783 from fieldenms/Issue-#2780
01es Jul 8, 2026
4ac6be3
#2777 Updated Jackson to 2.22.0.
01es Jul 8, 2026
6917a83
#2777 Opportunistic updated to Guava and POI.
01es Jul 8, 2026
db8c097
#2777 Addressed Guava-related deprecations.
01es Jul 8, 2026
9ce1d6c
Merge pull request #2785 from fieldenms/Issue-#2777
01es Jul 8, 2026
ad681fb
#2777 Updated Jackson to 2.22.1.
01es Jul 8, 2026
a04c20c
Merge pull request #2786 from fieldenms/Issue-#2777
01es Jul 8, 2026
0c4444f
Merge branch 'develop' into Issue-#2755
01es Jul 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion platform-annotation-processors-test/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>fielden</groupId>
<artifactId>platform-parent</artifactId>
<version>2.4.2-SNAPSHOT</version>
<version>2.4.5-SNAPSHOT</version>
</parent>

<artifactId>platform-annotation-processors-test</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion platform-annotation-processors/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>fielden</groupId>
<artifactId>platform-parent</artifactId>
<version>2.4.2-SNAPSHOT</version>
<version>2.4.5-SNAPSHOT</version>
</parent>

<artifactId>platform-annotation-processors</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion platform-annotations/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<parent>
<groupId>fielden</groupId>
<artifactId>platform-parent</artifactId>
<version>2.4.2-SNAPSHOT</version>
<version>2.4.5-SNAPSHOT</version>
</parent>

<artifactId>platform-annotations</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion platform-benchmark/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>fielden</groupId>
<artifactId>platform-parent</artifactId>
<version>2.4.2-SNAPSHOT</version>
<version>2.4.5-SNAPSHOT</version>
</parent>

<name>Trident Genesis Platform Microbenckmarks</name>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
import ua.com.fielden.platform.serialisation.api.impl.IdOnlyProxiedEntityTypeCacheForTests;
import ua.com.fielden.platform.web.annotations.AppUri;

import java.time.Duration;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

import static java.lang.String.format;

Expand Down Expand Up @@ -59,7 +59,7 @@ protected void configure() {
@Provides
@Singleton
@SessionCache Cache<String, UserSession> provideSessionCache() {
return CacheBuilder.newBuilder().expireAfterWrite(2, TimeUnit.MINUTES).build();
return CacheBuilder.newBuilder().expireAfterWrite(Duration.ofMinutes(2)).build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
import ua.com.fielden.platform.serialisation.api.impl.IdOnlyProxiedEntityTypeCacheForTests;
import ua.com.fielden.platform.web.annotations.AppUri;

import java.time.Duration;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

import static java.lang.String.format;

Expand Down Expand Up @@ -59,7 +59,7 @@ protected void configure() {
@Provides
@Singleton
@SessionCache Cache<String, UserSession> provideSessionCache() {
return CacheBuilder.newBuilder().expireAfterWrite(2, TimeUnit.MINUTES).build();
return CacheBuilder.newBuilder().expireAfterWrite(Duration.ofMinutes(2)).build();
}

}
2 changes: 1 addition & 1 deletion platform-dao/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<parent>
<groupId>fielden</groupId>
<artifactId>platform-parent</artifactId>
<version>2.4.2-SNAPSHOT</version>
<version>2.4.5-SNAPSHOT</version>
</parent>

<artifactId>platform-dao</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
import java.sql.Types;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static org.apache.commons.lang3.StringUtils.substringBefore;
import static ua.com.fielden.platform.utils.Pair.pair;
Expand Down Expand Up @@ -40,11 +38,8 @@ public final class HibernateToJdbcSqlTypeCorrespondence {
*/
// funnily enough Hibernate itself performs such conversion in certain Dialect implementations
public static String genericSqlTypeName(final int sqlType, final Dialect dialect) {
final var map = GENERIC_TYPE_NAMES.computeIfAbsent(dialect, $ -> new ConcurrentHashMap<>());
return map.computeIfAbsent(sqlType, $ -> substringBefore(dialect.getTypeName(sqlType), '('));
return substringBefore(dialect.getTypeName(sqlType), '(');
}
// where
private static final Map<Dialect, Map<Integer, String>> GENERIC_TYPE_NAMES = new ConcurrentHashMap<>(1); // expect at most 1 dialect

/**
* Infers the name of a Hibernate type to use in a {@code CAST} SQL expression.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,14 @@ public TgEntityWithTimeZoneDatesDao(final IFilter filter) {

@Override
protected IFetchProvider<TgEntityWithTimeZoneDates> createFetchProvider() {
return super.createFetchProvider().with("key", "dateProp", "datePropUtc", "datePropDependent");
return super.createFetchProvider().with(
"key",
"dateProp",
"datePropUtc",
"datePropDependent",
"dateOnlyProp",
"dateOnlyPropUtc"
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import ua.com.fielden.platform.entity.query.DbVersion;
import ua.com.fielden.platform.entity.query.fluent.EntityQueryProgressiveInterfaces.ICompleted;
import ua.com.fielden.platform.entity.query.fluent.EntityQueryProgressiveInterfaces.IJoin;
import ua.com.fielden.platform.entity.query.model.ConditionModel;
import ua.com.fielden.platform.entity.query.model.EntityResultQueryModel;
import ua.com.fielden.platform.entity_centre.mnemonics.DateMnemonicUtils;
import ua.com.fielden.platform.entity_centre.mnemonics.DateRangePrefixEnum;
import ua.com.fielden.platform.entity_centre.mnemonics.DateRangeSelectorEnum;
Expand All @@ -23,11 +25,12 @@
import ua.com.fielden.platform.eql.dbschema.HibernateMappingsGenerator;
import ua.com.fielden.platform.eql.dbschema.PropertyInlinerImpl;
import ua.com.fielden.platform.eql.meta.EqlTables;
import ua.com.fielden.platform.error.Result;
import ua.com.fielden.platform.meta.DomainMetadataBuilder;
import ua.com.fielden.platform.meta.DomainMetadataUtils;
import ua.com.fielden.platform.persistence.types.PlatformHibernateTypeMappings;
import ua.com.fielden.platform.reflection.PropertyTypeDeterminator;
import ua.com.fielden.platform.sample.domain.TgBogie;
import ua.com.fielden.platform.sample.domain.*;
import ua.com.fielden.platform.security.ISecurityToken;
import ua.com.fielden.platform.security.interception.MasterEntity_CanRead_unauthorisedProp_Token;
import ua.com.fielden.platform.security.user.SecurityRoleAssociation;
Expand All @@ -43,7 +46,7 @@
import static java.util.Optional.empty;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.junit.Assert.assertEquals;
import static ua.com.fielden.platform.entity.AbstractEntity.DESC;
import static org.junit.Assert.assertThrows;
import static ua.com.fielden.platform.entity.AbstractEntity.KEY;
import static ua.com.fielden.platform.entity.query.IDbVersionProvider.constantDbVersion;
import static ua.com.fielden.platform.entity.query.fluent.EntityQueryUtils.cond;
Expand Down Expand Up @@ -576,60 +579,90 @@ public void query_composition_for_property_of_type_string_with_and_without_wildc
assertEquals("Incorrect query model has been built.", expected.model(), actual.model());
}


@Test
public void query_composition_for_properties_of_entity_type_with_wildcard_selection_crit_value_uses_iLike_operator() {
final var property = queryProperties.get("entityProp");
final String propertyName = "entityProp";

set_up();
final QueryProperty property = queryProperties.get(propertyName);
final var values = List.of("some val 1*", "some val 2*");
property.setValue(values);

final var expected = iJoin.where()
.condition(cond()
.condition(cond().prop(createConditionProperty("entityProp")).isNotNull()
.and().condition(cond().prop(createConditionProperty("entityProp") + "." + KEY).iLike().anyOfValues(prepCritValuesForEntityTypedProp(values)).model())
.model())
.model());
final var actual = createQuery(masterKlass, new ArrayList<>(queryProperties.values()), dates);
final String cbn = property.getConditionBuildingName();
final var cbnNoKey = getPropertyNameWithoutKeyPart(cbn);

final ICompleted<? extends AbstractEntity<?>> expected = //
/**/iJoin.where().condition(cond() //
/* */.condition(cond().prop(cbnNoKey).isNotNull().and() //
/* */.condition(cond().prop(cbnNoKey).in().model(select(SlaveEntity.class).where().prop(KEY).iLike().anyOfValues(prepCritValuesForEntityTypedProp(values)).model()).model())
/* */.model()) //
/**/.model()); //
final ICompleted<? extends AbstractEntity<?>> actual = createQuery(masterKlass, new ArrayList<>(queryProperties.values()), dates);

assertEquals("Incorrect query model has been built.", expected.model(), actual.model());
}

@Test
public void query_composition_for_properties_of_entity_type_without_wildcard_selection_crit_value() {
final var property = queryProperties.get("entityProp");
property.setValue(List.of("some val 1", "some val 2"));

final var expected = iJoin.where()
.condition(cond()
.condition(cond().prop(createConditionProperty("entityProp")).isNotNull()
.and().condition(cond().prop(createConditionProperty("entityProp") + "." + KEY).in().values("some val 1", "some val 2").model())
.model())
.model());
final var actual = createQuery(masterKlass, new ArrayList<>(queryProperties.values()), dates);
public void query_composition_for_properties_of_entity_type_without_wildcard_selection_crit_value_uses_in_operator_with_subselect() {
final String propertyName = "entityProp";

set_up();
final QueryProperty property = queryProperties.get(propertyName);
final String[] critValues = new String[] {"some val 1", "some val 2"};
property.setValue(Arrays.asList(critValues));


final String cbn = property.getConditionBuildingName();
final String cbnNoKey = cbn.substring(0, cbn.length() - 4); // cut off ".key" from the name

final ICompleted<? extends AbstractEntity<?>> expected = //
/**/iJoin.where().condition(cond() //
/* */.condition(cond().prop(getPropertyNameWithoutKeyPart(cbn)).isNotNull().and() //
/* */.condition(cond().prop(cbnNoKey).in().model(select(SlaveEntity.class).where().prop("key").in().values("some val 1", "some val 2").model()).model()) //
/* */.model()) //
/**/.model()); //
final ICompleted<? extends AbstractEntity<?>> actual = createQuery(masterKlass, new ArrayList<>(queryProperties.values()), dates);

assertEquals("Incorrect query model has been built.", expected.model(), actual.model());
}

@Test
public void query_composition_for_properties_of_entity_type_with_and_without_wildcard_selection_crit_value() {
final var property = queryProperties.get("entityProp");
property.setValue(List.of("some val 1", "some val 2*", "some val 3*", "some val 4"));

final var expected = iJoin.where()
.condition(cond()
.condition(cond()
.prop(createConditionProperty("entityProp")).isNotNull()
.and().condition(cond().prop(path(createConditionProperty("entityProp"), KEY)).in().values("some val 1", "some val 4")
.or()
.prop(path(createConditionProperty("entityProp"), KEY)).iLike().anyOfValues(prepCritValuesForEntityTypedProp(List.of("some val 2*", "some val 3*")))
.model())
.model())
.model());

final var actual = createQuery(masterKlass, new ArrayList<>(queryProperties.values()), dates);
public void query_composition_for_properties_of_entity_type_with_and_without_wildcard_selection_crit_value_uses_combination_of_in_operator_with_subselect_and_iLike_operator() {
final String propertyName = "entityProp";

set_up();
final QueryProperty property = queryProperties.get(propertyName);
final String[] critValues = new String[] {"some val 1", "some val 2*", "some val 3*", "some val 4",};
property.setValue(Arrays.asList(critValues));

final String[] critValuesWithWildcard = new String[] {"some val 2*", "some val 3*"};

final String cbn = property.getConditionBuildingName();
final String cbnNoKey = cbn.substring(0, cbn.length() - 4); // cut off ".key" from the name


final EntityResultQueryModel<SlaveEntity> subSelect = select(SlaveEntity.class).where().prop("key").in().values("some val 1", "some val 4").model();
final ConditionModel whereCondition = cond()
.condition(
cond().prop(getPropertyNameWithoutKeyPart(cbn)).isNotNull()
.and()
.condition(
cond().prop(cbnNoKey).in().model(subSelect)
.or().prop(cbnNoKey).in().model(select(SlaveEntity.class).where().prop(KEY).iLike().anyOfValues(prepCritValuesForEntityTypedProp(Arrays.asList(critValuesWithWildcard))).model())
.model())
.model())
.model();

final ICompleted<? extends AbstractEntity<?>> expected = //
/**/iJoin.where().condition(whereCondition);

final ICompleted<? extends AbstractEntity<?>> actual = createQuery(masterKlass, new ArrayList<>(queryProperties.values()), dates);

assertEquals("Incorrect query model has been built.", expected.model(), actual.model());
}


//---------------------------------------------------------------------------------------//
//------------------------------ 2. Property level (Negation / Null) --------------------//
//---------------------------------------------------------------------------------------//
Expand Down Expand Up @@ -1364,35 +1397,35 @@ public void conditions_for_union_members_are_combined_with_logical_AND() {
property.setValue(3);
property.setValue2(7);

final var expected = select(select(TgBogie.class).model().setShouldMaterialiseCalcPropsAsColumnsInSqlQuery(true)).as(alias).where()
.condition(cond()
.condition(cond().prop(alias).isNotNull().and()
.condition(cond().prop(path(alias, KEY)).iLike().anyOfValues("some val 1%", "some val 2%").model())
.model()).and()
.condition(cond().prop(path(alias, DESC)).isNotNull().and()
.condition(cond().prop(path(alias, DESC)).iLike().anyOfValues("%Some string value%").model())
.model()).and()
.condition(cond().prop(path(alias, "location")).isNotNull().and()
.condition(cond().prop(path(alias, "location.key")).iLike().anyOfValues("some val 1%", "some val 2%").model())
.model()).and()
.condition(cond().prop(path(alias, "location.workshop")).isNotNull().and()
.condition(cond().prop(path(alias, "location.workshop.key")).iLike().anyOfValues("some val 1%", "some val 2%").model())
.model()).and()
.condition(cond().prop(path(alias, "location.workshop.desc")).isNotNull().and()
.condition(cond().prop(path(alias, "location.workshop.desc")).iLike().anyOfValues("%Some string value%").model())
.model())
.and()
.condition(cond().prop(path(alias, "location.wagonSlot")).isNotNull().and()
.condition(cond().prop(path(alias, "location.wagonSlot.key")).iLike().anyOfValues("some val 1%", "some val 2%").model())
.model()).and()
.condition(cond().prop(path(alias, "location.wagonSlot.wagon")).isNotNull().and()
.condition(cond().prop(path(alias, "location.wagonSlot.wagon.key")).iLike().anyOfValues("some val 1%", "some val 2%").model())
.model()).and()
.condition(cond().prop(path(alias, "location.wagonSlot.position")).isNotNull().and()
.condition(cond().prop(path(alias, "location.wagonSlot.position")).ge().iVal(3).and().prop(path(alias, "location.wagonSlot.position")).le().iVal(7).model())
.model())
.model());
final var actual = createQuery(TgBogie.class, new ArrayList<>(unionProps.values()), dates);
final ICompleted<? extends AbstractEntity<?>> expected =
/**/select(select(TgBogie.class).model().setShouldMaterialiseCalcPropsAsColumnsInSqlQuery(true)).as(alias).where().condition(cond() //
/* */.condition(cond().prop(alias).isNotNull().and() //
/* */.condition(cond().prop(alias).in().model(select(TgBogie.class).where().prop(KEY).iLike().anyOfValues("some val 1%", "some val 2%").model()).model())//
/* */.model()).and()//
/* */.condition(cond().prop(alias + ".desc").isNotNull().and() //
/* */.condition(cond().prop(alias + ".desc").iLike().anyOfValues("%Some string value%").model()) //
/* */.model()).and()//
/* */.condition(cond().prop(alias + ".location").isNotNull().and() //
/* */.condition(cond().prop(alias + ".location").in().model(select(TgBogieLocation.class).where().prop(KEY).iLike().anyOfValues("some val 1%", "some val 2%").model()).model())//
/* */.model()).and()//
/* */.condition(cond().prop(alias + ".location.workshop").isNotNull().and()//
/* */.condition(cond().prop(alias + ".location.workshop").in().model(select(TgWorkshop.class).where().prop(KEY).iLike().anyOfValues("some val 1%", "some val 2%").model()).model())//
/* */.model()).and()//
/* */.condition(cond().prop(alias + ".location.workshop.desc").isNotNull().and()//
/* */.condition(cond().prop(alias + ".location.workshop.desc").iLike().anyOfValues("%Some string value%").model())
/* */.model())//
/* */.and() // this used to be OR
/* */.condition(cond().prop(alias + ".location.wagonSlot").isNotNull().and()//
/* */.condition(cond().prop(alias + ".location.wagonSlot").in().model(select(TgWagonSlot.class).where().prop(KEY).iLike().anyOfValues("some val 1%", "some val 2%").model()).model())//
/* */.model()).and()//
/* */.condition(cond().prop(alias + ".location.wagonSlot.wagon").isNotNull().and()//
/* */.condition(cond().prop(alias + ".location.wagonSlot.wagon").in().model(select(TgWagon.class).where().prop(KEY).iLike().anyOfValues("some val 1%", "some val 2%").model()).model())//
/* */.model()).and()//
/* */.condition(cond().prop(alias + ".location.wagonSlot.position").isNotNull().and()//
/* */.condition(cond().prop(alias + ".location.wagonSlot.position").ge().iVal(3).and().prop(alias + ".location.wagonSlot.position").le().iVal(7).model())//
/* */.model())//
/**/.model()); //
final ICompleted<? extends AbstractEntity<?>> actual = createQuery(TgBogie.class, new ArrayList<>(unionProps.values()), dates);
assertEquals("Incorrect query model for union entities has been built.", expected.model(), actual.model());
}

Expand Down Expand Up @@ -1438,10 +1471,4 @@ private void removeAccessTo(final Class<? extends ISecurityToken> token) {
));
}

/// Joins property paths.
///
private static String path(final CharSequence... xs) {
return String.join(".", xs);
}

}
Loading
Loading