Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 0 additions & 4 deletions cms-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.15.0</version>
<configuration>
<compilerArgs>
<arg>--enable-preview</arg>
Expand Down Expand Up @@ -75,7 +74,4 @@
<version>9.10.1</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.release>25</maven.compiler.release>
</properties>
</project>
14 changes: 14 additions & 0 deletions cms-api/src/main/java/com/condation/cms/api/db/ContentQuery.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,20 @@ public interface ContentQuery<T> {
ContentQuery<T> whereNotIn(final String field, final List<Object> value);

ContentQuery<T> whereExists(final String field);

ContentQuery<T> within(
final String field,
final double latitude,
final double longitude,
final double radius,
final DistanceUnit unit);

ContentQuery<T> within(
final String field,
final double latitude,
final double longitude,
final double radius,
final String unit);

ContentQuery<T> expression(final String expressions);

Expand Down
63 changes: 63 additions & 0 deletions cms-api/src/main/java/com/condation/cms/api/db/DistanceUnit.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.condation.cms.api.db;

/*-
* #%L
* CMS Api
* %%
* Copyright (C) 2023 - 2026 CondationCMS
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/

import java.util.Locale;

/**
* Distance units accepted by geo queries.
*
* @author t.marx
*/
public enum DistanceUnit {

METERS(1),
KILOMETERS(1_000),
MILES(1_609.344);

private final double meters;

DistanceUnit(double meters) {
this.meters = meters;
}

public double toMeters(double value) {
return value * meters;
}

public double fromMeters(double value) {
return value / meters;
}

public static DistanceUnit fromString(String value) {
if (value == null) {
throw new IllegalArgumentException("distance unit must not be null");
}

return switch (value.strip().toLowerCase(Locale.ROOT)) {
case "m", "meter", "meters" -> METERS;
case "km", "kilometer", "kilometers" -> KILOMETERS;
case "mi", "mile", "miles" -> MILES;
default -> throw new IllegalArgumentException("unsupported distance unit: " + value);
};
}
}
78 changes: 78 additions & 0 deletions cms-api/src/main/java/com/condation/cms/api/db/GeoDistance.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.condation.cms.api.db;

/*-
* #%L
* CMS Api
* %%
* Copyright (C) 2023 - 2026 CondationCMS
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/

import java.util.Objects;

public final class GeoDistance {

private static final double EARTH_RADIUS_METERS = 6_371_008.7714;

private GeoDistance() {
}

public static double between(
double originLatitude,
double originLongitude,
double latitude,
double longitude,
DistanceUnit unit) {
Objects.requireNonNull(unit, "distance unit must not be null");
validateCoordinate(originLatitude, originLongitude);
validateCoordinate(latitude, longitude);

double latitudeDelta = Math.toRadians(latitude - originLatitude);
double longitudeDelta = Math.toRadians(longitude - originLongitude);
double originLatitudeRadians = Math.toRadians(originLatitude);
double latitudeRadians = Math.toRadians(latitude);
double haversine = Math.pow(Math.sin(latitudeDelta / 2), 2)
+ Math.cos(originLatitudeRadians)
* Math.cos(latitudeRadians)
* Math.pow(Math.sin(longitudeDelta / 2), 2);
haversine = Math.min(1, haversine);
double centralAngle = 2 * Math.atan2(Math.sqrt(haversine), Math.sqrt(1 - haversine));
return unit.fromMeters(EARTH_RADIUS_METERS * centralAngle);
}

public static double between(
double originLatitude,
double originLongitude,
double latitude,
double longitude,
String unit) {
return between(
originLatitude,
originLongitude,
latitude,
longitude,
DistanceUnit.fromString(unit));
}

private static void validateCoordinate(double latitude, double longitude) {
if (!Double.isFinite(latitude) || latitude < -90 || latitude > 90) {
throw new IllegalArgumentException("latitude must be between -90 and 90");
}
if (!Double.isFinite(longitude) || longitude < -180 || longitude > 180) {
throw new IllegalArgumentException("longitude must be between -180 and 180");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,9 @@
* #L%
*/

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.experimental.Accessors;

/**
*
* @author t.marx
*/
@AllArgsConstructor
@Data
@Accessors(fluent = true)
public class FilterContext<T> implements HookContext {
private T value;
}
public record FilterContext<T> (T value) implements HookContext {
}
30 changes: 11 additions & 19 deletions cms-api/src/main/java/com/condation/cms/api/utils/DateRange.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/

import java.time.Instant;
import java.util.Date;

public class DateRange {



/**
* Checks if the current UTC time is within the range.
* @param from
* @param to
* @return
*
* @param from
* @param to
* @return
*/
public static boolean isNowWithin(Date from, Date to) {

var now = Date.from(Instant.now());

if ( from != null && !(from.before(now) || from.equals(now)) ) {
return false;
}
if (to != null
&& (to.before(now) || to.equals(now))) {
return false;
}
return true;
Date now = new Date();

if (from != null && now.before(from)) {
return false;
}

return to == null || now.before(to);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.condation.cms.api.db;

/*-
* #%L
* CMS Api
* %%
* Copyright (C) 2023 - 2026 CondationCMS
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

class DistanceUnitTest {

@Test
void parsesTemplateFriendlyUnitNames() {
Assertions.assertThat(DistanceUnit.fromString("m")).isEqualTo(DistanceUnit.METERS);
Assertions.assertThat(DistanceUnit.fromString(" meters ")).isEqualTo(DistanceUnit.METERS);
Assertions.assertThat(DistanceUnit.fromString("KM")).isEqualTo(DistanceUnit.KILOMETERS);
Assertions.assertThat(DistanceUnit.fromString("kilometers")).isEqualTo(DistanceUnit.KILOMETERS);
Assertions.assertThat(DistanceUnit.fromString("mi")).isEqualTo(DistanceUnit.MILES);
Assertions.assertThat(DistanceUnit.fromString(" MILES ")).isEqualTo(DistanceUnit.MILES);
}

@Test
void rejectsUnknownUnitNames() {
Assertions.assertThatThrownBy(() -> DistanceUnit.fromString("yards"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("yards");
}

@Test
void convertsValuesToMeters() {
Assertions.assertThat(DistanceUnit.METERS.toMeters(2.5)).isEqualTo(2.5);
Assertions.assertThat(DistanceUnit.KILOMETERS.toMeters(2.5)).isEqualTo(2_500);
Assertions.assertThat(DistanceUnit.MILES.toMeters(2.5)).isEqualTo(4_023.36);
Assertions.assertThat(DistanceUnit.MILES.fromMeters(1_609.344)).isEqualTo(1);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.condation.cms.api.db;

/*-
* #%L
* CMS Api
* %%
* Copyright (C) 2023 - 2026 CondationCMS
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

class GeoDistanceTest {

@Test
void calculatesDistanceInTheRequestedUnit() {
double kilometers = GeoDistance.between(51.4818, 7.2162, 51.4882, 7.2160, "km");
double miles = GeoDistance.between(51.4818, 7.2162, 51.4882, 7.2160, "miles");

Assertions.assertThat(kilometers).isBetween(0.70, 0.72);
Assertions.assertThat(miles).isBetween(0.43, 0.45);
}

@Test
void rejectsInvalidCoordinates() {
Assertions.assertThatThrownBy(() -> GeoDistance.between(91, 7.2162, 51.4882, 7.2160, "km"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("latitude");
}
}
3 changes: 1 addition & 2 deletions cms-content/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.15.0</version>
<configuration>
<compilerArgs>
<arg>--enable-preview</arg>
Expand Down Expand Up @@ -81,4 +80,4 @@
<scope>test</scope>
</dependency>
</dependencies>
</project>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import com.condation.cms.hooksystem.extensions.TemplateHooks;
import com.condation.cms.content.template.functions.LinkFunction;
import com.condation.cms.content.template.functions.MarkdownFunction;
import com.condation.cms.content.template.functions.geo.GeoFunction;
import com.condation.cms.content.template.functions.list.NodeListFunctionBuilder;
import com.condation.cms.content.template.functions.navigation.NavigationFunction;
import com.condation.cms.content.template.functions.query.QueryFunction;
Expand Down Expand Up @@ -170,6 +171,7 @@ public String render(final ReadOnlyFile contentFile, final RequestContext contex

QueryFunction queryFunction = createQueryFunction(contentFile, context);
namespace.add(Constants.TemplateNamespaces.CMS, "query", queryFunction);
namespace.add(Constants.TemplateNamespaces.CMS, "geo", new GeoFunction());

MarkdownFunction markdownFunction = createMarkdownFunction(context);
namespace.add(Constants.TemplateNamespaces.CMS, "markdown", markdownFunction);
Expand Down
Loading
Loading