Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2.2.2] Release #308

Merged
merged 17 commits into from
Jan 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# JOPA - Change Log

## 2.2.2 - 2025-01-18
- Fix an issue with parsing SPARQL query parameters (Enhancement #294).
- Fix an issue with passing a lazy loading proxy to `EntityManager.remove` (Bug #306).
- Refactor test metamodel setup (GH #301).
- Allow using primitive types as mapped attribute types.
- Dependency updates: RDF4J 5.1.0.

## 2.2.1 - 2024-12-12
- Rename `MultilingualString` in OntoDriver to `Translations` to prevent confusion with `MultilingualString` from JOPA (GH #288).
- Fix a SPARQL query parsing issue (Bug #294).
Expand Down
2 changes: 1 addition & 1 deletion datatype/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<artifactId>jopa-all</artifactId>
<groupId>cz.cvut.kbss.jopa</groupId>
<version>2.2.1</version>
<version>2.2.2</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ public class DatatypeTransformer {

private static final Map<Pair, Function<Object, ?>> TRANSFORMERS = initTransformers();

private static final Map<Class<?>, Class<?>> WRAPPER_TO_PRIMITIVES = Map.of(
Integer.class, int.class,
Boolean.class, boolean.class,
Byte.class, byte.class,
Short.class, short.class,
Long.class, long.class,
Float.class, float.class,
Double.class, double.class
);

private DatatypeTransformer() {
throw new AssertionError();
}
Expand Down Expand Up @@ -79,14 +89,31 @@ private DatatypeTransformer() {
return map;
}

/**
* Converts the specified wrapper class to its corresponding primitive class.
* <p>
* If the class parameter is a wrapper type, the equivalent primitive type will be returned (e.g. int.class for
* Integer.class) In all other cases, the return value is null.
*
* @param cls - the class to convert
* @return Optional containing the primitive type, or empty if the specified class is not a wrapper type
*/
public static Optional<Class<?>> wrapperTypeToPrimitiveType(Class<?> cls) {
if (cls != null && WRAPPER_TO_PRIMITIVES.containsKey(cls)) {
return Optional.of(WRAPPER_TO_PRIMITIVES.get(cls));
}
return Optional.empty();
}

/**
* Maps the specified value to the target type (if possible).
*
* @param value The value to convert
* @param targetType The type to which the specified value should be converted
* @param <T> Target type
* @return Value as the target type
* @throws UnsupportedTypeTransformationException If the specified value cannot be transformed to the specified target type
* @throws UnsupportedTypeTransformationException If the specified value cannot be transformed to the specified
* target type
*/
public static <T> T transform(Object value, Class<T> targetType) {
Objects.requireNonNull(targetType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,36 @@

import java.net.InetAddress;
import java.net.URL;
import java.util.Optional;
import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.*;

class DatatypeTransformerTest {

@Test
void wrapperTypeToPrimitiveTypeReturnsNullForNullInput() {
assertEquals(Optional.empty(), DatatypeTransformer.wrapperTypeToPrimitiveType(null));
}

@ParameterizedTest
@MethodSource("wrapperTypeToPrimitiveTypeTestValues")
void wrapperTypeToPrimitiveType(Class<?> wrapper, Class<?> primitive) {
assertEquals(Optional.of(primitive), DatatypeTransformer.wrapperTypeToPrimitiveType(wrapper));
}

private static Stream<Arguments> wrapperTypeToPrimitiveTypeTestValues() {
return Stream.of(
Arguments.arguments(Integer.class, int.class),
Arguments.arguments(Boolean.class, boolean.class),
Arguments.arguments(Byte.class, byte.class),
Arguments.arguments(Short.class, short.class),
Arguments.arguments(Long.class, long.class),
Arguments.arguments(Float.class, float.class),
Arguments.arguments(Double.class, double.class)
);
}

@Test
void transformReturnsNullForNullInput() {
assertNull(DatatypeTransformer.transform(null, String.class));
Expand Down
2 changes: 1 addition & 1 deletion jopa-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>cz.cvut.kbss.jopa</groupId>
<artifactId>jopa-all</artifactId>
<version>2.2.1</version>
<version>2.2.2</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion jopa-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>cz.cvut.kbss.jopa</groupId>
<artifactId>jopa-all</artifactId>
<version>2.2.1</version>
<version>2.2.2</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion jopa-impl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>cz.cvut.kbss.jopa</groupId>
<artifactId>jopa-all</artifactId>
<version>2.2.1</version>
<version>2.2.2</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
131 changes: 66 additions & 65 deletions jopa-impl/src/main/antlr4/cz/cvut/kbss/jopa/query/soql/Soql.g4
Original file line number Diff line number Diff line change
@@ -1,48 +1,30 @@
grammar Soql;

start: querySentence EOF ;

querySentence : selectStatement whereClauseWrapper? groupByClause? orderByClause? ;
querySentence: selectStatement ;

selectStatement: typeDef params FROM tables ;
selectStatement: selectClause fromClause whereClause? groupByClause? orderByClause? ;

typeDef: SELECT ;
singleValuedObjectPathExpression: simpleSubpath DOT singleValuedObjectField ;

params: paramComma* distinctParam ;
simpleSubpath: singleValuedObjectField (DOT simpleSubpath)* ;

paramComma: distinctParam ',' ;
singleValuedObjectField: IDENTIFICATION_VARIABLE ;

distinctParam: distinct? selectedParam ;
selectClause: SELECT (DISTINCT)? selectItem (',' selectItem)* ;

selectedParam: param | count;
selectItem: selectExpression;

count: COUNT '(' param ')' ;
selectExpression: simpleSubpath | aggregateExpression ;

param: objWithAttr | objWithOutAttr ;
aggregateExpression: COUNT '(' (DISTINCT)? simpleSubpath ')';

objWithAttr: object DOT attribute;
fromClause: FROM entityName IDENTIFICATION_VARIABLE;

objWithOutAttr: object ;
entityName: IDENTIFICATION_VARIABLE ;

distinct: DISTINCT ;

object: IDENTIFICATION_VARIABLE ;

attribute: IDENTIFICATION_VARIABLE ;

joinedParams: object DOT attribute (DOT attribute)+ ;



tables: tableWithName ;

table: IDENTIFICATION_VARIABLE ;

tableName: IDENTIFICATION_VARIABLE ;

tableWithName: table tableName ;


whereClauseWrapper
whereClause
: WHERE conditionalExpression
;

Expand All @@ -66,38 +48,44 @@ simpleConditionalExpression
;

inExpression
: whereClauseParam (NOT)? IN '('? (inItem (',' inItem)*) ')'?
: simpleSubpath (NOT)? IN '('? (inItem (',' inItem)*) ')'?
;

inItem
: literal
| whereClauseValue
| inputParameter
;

literal
:
: STRING_LITERAL
| INT_LITERAL
| FLOAT_LITERAL
| BOOLEAN_LITERAL
| IDENTIFICATION_VARIABLE
;

likeExpression
: stringExpression (NOT)? LIKE whereClauseValue
: stringExpression (NOT)? LIKE stringExpression
;

memberOfExpression
: inItem (NOT)? MEMBEROF whereClauseParam
: inItem (NOT)? MEMBER OF simpleSubpath
;

entityExpression
: IDENTIFICATION_VARIABLE
| inputParameter
;

comparisonExpression
: stringExpression COMPARISON_OPERATOR stringExpression
| simpleArithmeticExpression COMPARISON_OPERATOR simpleArithmeticExpression
| whereClauseParam COMPARISON_OPERATOR ( whereClauseParam | whereClauseValue )
: stringExpression comparisonOperator stringExpression
| simpleArithmeticExpression comparisonOperator simpleArithmeticExpression
| entityExpression op=(EQUAL | NOT_EQUAL) ( entityExpression )
;

whereClauseValue: (QMARK TEXT QMARK) | inputParameter ;

whereClauseParam: param | joinedParams ;

stringExpression
: whereClauseParam
: simpleSubpath
| STRING_LITERAL
| inputParameter
| functionsReturningStrings
;
Expand All @@ -107,7 +95,7 @@ functionsReturningStrings
| 'SUBSTRING' '(' stringExpression ',' simpleArithmeticExpression ',' simpleArithmeticExpression ')'
| 'LOWER' '(' stringExpression ')'
| 'UPPER' '(' stringExpression ')'
| 'LANG' '(' whereClauseParam ')'
| 'LANG' '(' simpleSubpath ')'
;

simpleArithmeticExpression
Expand All @@ -123,7 +111,7 @@ arithmeticFactor
;

arithmeticPrimary
: param
: simpleSubpath
| literal
| '(' simpleArithmeticExpression ')'
| inputParameter
Expand All @@ -138,22 +126,24 @@ functionsReturningNumerics
| 'FLOOR' '(' simpleArithmeticExpression ')'
;

orderByClause: ORDERBY orderByFullFormComma orderByFullFormComma* ;

orderByFullFormComma: orderByFullForm ','? ;

orderByFullForm: orderByParam ORDERING? ;

orderByParam: object DOT attribute (DOT attribute)* ;
orderByClause: ORDER BY orderByItem (',' orderByItem)* ;

groupByClause: GROUPBY groupByParamComma groupByParamComma* ;
orderByItem: singleValuedObjectPathExpression (ASC | DESC) ;

groupByParamComma: groupByParam ','? ;
groupByClause: GROUP BY groupByItem (',' groupByItem)* ;

groupByParam: object DOT attribute (DOT attribute)* ;
groupByItem: singleValuedObjectPathExpression ;

inputParameter: COLON IDENTIFICATION_VARIABLE ;

comparisonOperator
: op=EQUAL
| op='>'
| op='>='
| op='<'
| op='<='
| op=NOT_EQUAL
;

SELECT: 'SELECT' ;

Expand All @@ -169,11 +159,13 @@ AND: 'AND' ;

OR: 'OR' ;

ORDERBY: 'ORDER BY' ;
BY: 'BY' ;

OF: 'OF' ;

ORDERING: ASC | DESC ;
ORDER: 'ORDER' ;

GROUPBY: 'GROUP BY' ;
GROUP: 'GROUP' ;

ASC: 'ASC' ;

Expand All @@ -187,18 +179,31 @@ LIKE: 'LIKE' ;

IN: 'IN' ;

MEMBEROF: 'MEMBER OF' ;
MEMBER: 'MEMBER' ;

COMPARISON_OPERATOR: '>' | '<' | '>=' | '<=' | '=' | '<>' | '!=' ;
EQUAL: '=' ;
NOT_EQUAL: '<>' | '!=' ;

DOT: '.' ;

QMARK: '"' ;

COLON: ':' ;

TRUE: 'TRUE';

FALSE: 'FALSE';

IDENTIFICATION_VARIABLE: (LOWERCASE | UPPERCASE | '_') (LOWERCASE | UPPERCASE | DIGIT | '_')* ;

STRING_LITERAL: QMARK TEXT QMARK ;

INT_LITERAL: DIGIT+;

FLOAT_LITERAL: DIGIT* '.' DIGIT;

BOOLEAN_LITERAL: TRUE | FALSE;

TEXT: (LOWERCASE | UPPERCASE | DIGIT)+ ;

UPPERCASE: ('A'..'Z');
Expand All @@ -207,8 +212,4 @@ LOWERCASE: ('a'..'z');

DIGIT: ('0'..'9');

NUMBER: DIGIT+ ;

VALUE: NUMBER ;

WHITESPACE: (' ')+ -> skip;
Loading
Loading