1515 */
1616package org .springframework .data .neo4j .core ;
1717
18+ import java .util .List ;
1819import java .util .function .Consumer ;
1920import java .util .function .Predicate ;
2021import java .util .regex .Pattern ;
2324
2425import org .apache .commons .logging .LogFactory ;
2526import org .jspecify .annotations .Nullable ;
26- import org .neo4j .driver .NotificationCategory ;
27+ import org .neo4j .driver .NotificationClassification ;
2728import org .neo4j .driver .NotificationSeverity ;
28- import org .neo4j .driver .summary .InputPosition ;
29- import org .neo4j .driver .summary .Notification ;
29+ import org .neo4j .driver .summary .GqlNotification ;
3030import org .neo4j .driver .summary .Plan ;
3131import org .neo4j .driver .summary .ResultSummary ;
3232
@@ -66,8 +66,15 @@ final class ResultSummaries {
6666 private static final LogAccessor cypherTopologyNotificationLog = new LogAccessor (
6767 LogFactory .getLog ("org.springframework.data.neo4j.cypher.topology" ));
6868
69- private static final Pattern DEPRECATED_ID_PATTERN = Pattern
70- .compile ("(?im)The query used a deprecated function[.:] \\ (?[`']id.+" );
69+ private static final LogAccessor cypherSchemaNotificationLog = new LogAccessor (
70+ LogFactory .getLog ("org.springframework.data.neo4j.cypher.schema" ));
71+
72+ private static final List <Pattern > STUFF_THAT_MIGHT_INFORM_THAT_THE_ID_FUNCTION_IS_PROBLEMATIC = Stream .of (
73+ "(?im)The query used a deprecated function[.:] \\ (?[`']id.+" ,
74+ "(?im).*id is deprecated and will be removed without a replacement\\ ." ,
75+ "(?im).*feature deprecated with replacement\\ . id is deprecated\\ . It is replaced by elementId or consider using an application-generated id\\ ." )
76+ .map (Pattern ::compile )
77+ .toList ();
7178
7279 private ResultSummaries () {
7380 }
@@ -86,29 +93,33 @@ static ResultSummary process(ResultSummary resultSummary) {
8693
8794 private static void logNotifications (ResultSummary resultSummary ) {
8895
89- if (resultSummary .notifications ().isEmpty () || !Neo4jClient .cypherLog .isWarnEnabled ()) {
96+ if (resultSummary .gqlStatusObjects ().isEmpty () || !Neo4jClient .cypherLog .isWarnEnabled ()) {
9097 return ;
9198 }
9299
93100 boolean supressIdDeprecations = Neo4jClient .SUPPRESS_ID_DEPRECATIONS .getAcquire ();
94- Predicate <Notification > isDeprecationWarningForId ;
101+ Predicate <GqlNotification > isDeprecationWarningForId ;
95102 try {
96103 isDeprecationWarningForId = notification -> supressIdDeprecations
97- && notification .category ()
98- .orElse (NotificationCategory .UNRECOGNIZED )
99- .equals (NotificationCategory .DEPRECATION )
100- && DEPRECATED_ID_PATTERN .matcher (notification .description ()).matches ();
104+ && notification .classification ()
105+ .filter (cat -> cat == NotificationClassification .UNRECOGNIZED
106+ || cat == NotificationClassification .DEPRECATION )
107+ .isPresent ()
108+ && STUFF_THAT_MIGHT_INFORM_THAT_THE_ID_FUNCTION_IS_PROBLEMATIC .stream ()
109+ .anyMatch (p -> p .matcher (notification .statusDescription ()).matches ());
101110 }
102111 finally {
103112 Neo4jClient .SUPPRESS_ID_DEPRECATIONS .setRelease (supressIdDeprecations );
104113 }
105114
106115 String query = resultSummary .query ().text ();
107- resultSummary .notifications ()
116+ resultSummary .gqlStatusObjects ()
108117 .stream ()
118+ .filter (GqlNotification .class ::isInstance )
119+ .map (GqlNotification .class ::cast )
109120 .filter (Predicate .not (isDeprecationWarningForId ))
110- .forEach (notification -> notification .severityLevel ().ifPresent (severityLevel -> {
111- var category = notification .category ().orElse (null );
121+ .forEach (notification -> notification .severity ().ifPresent (severityLevel -> {
122+ var category = notification .classification ().orElse (null );
112123
113124 var logger = getLogAccessor (category );
114125 Consumer <String > logFunction ;
@@ -130,35 +141,22 @@ else if (severityLevel == NotificationSeverity.OFF) {
130141 }));
131142 }
132143
133- private static LogAccessor getLogAccessor (@ Nullable NotificationCategory category ) {
134- if (category == null ) {
144+ private static LogAccessor getLogAccessor (@ Nullable NotificationClassification classification ) {
145+ if (classification == null ) {
135146 return Neo4jClient .cypherLog ;
136147 }
137- if (category .equals (NotificationCategory .HINT )) {
138- return cypherHintNotificationLog ;
139- }
140- else if (category .equals (NotificationCategory .DEPRECATION )) {
141- return cypherDeprecationNotificationLog ;
142- }
143- else if (category .equals (NotificationCategory .PERFORMANCE )) {
144- return cypherPerformanceNotificationLog ;
145- }
146- else if (category .equals (NotificationCategory .GENERIC )) {
147- return cypherGenericNotificationLog ;
148- }
149- else if (category .equals (NotificationCategory .UNSUPPORTED )) {
150- return cypherUnsupportedNotificationLog ;
151- }
152- else if (category .equals (NotificationCategory .UNRECOGNIZED )) {
153- return cypherUnrecognizedNotificationLog ;
154- }
155- else if (category .equals (NotificationCategory .SECURITY )) {
156- return cypherSecurityNotificationLog ;
157- }
158- else if (category .equals (NotificationCategory .TOPOLOGY )) {
159- return cypherTopologyNotificationLog ;
160- }
161- return Neo4jClient .cypherLog ;
148+
149+ return switch (classification ) {
150+ case HINT -> cypherHintNotificationLog ;
151+ case UNRECOGNIZED -> cypherUnrecognizedNotificationLog ;
152+ case UNSUPPORTED -> cypherUnsupportedNotificationLog ;
153+ case PERFORMANCE -> cypherPerformanceNotificationLog ;
154+ case DEPRECATION -> cypherDeprecationNotificationLog ;
155+ case SECURITY -> cypherSecurityNotificationLog ;
156+ case TOPOLOGY -> cypherTopologyNotificationLog ;
157+ case GENERIC -> cypherGenericNotificationLog ;
158+ case SCHEMA -> cypherSchemaNotificationLog ;
159+ };
162160 }
163161
164162 /**
@@ -167,25 +165,23 @@ else if (category.equals(NotificationCategory.TOPOLOGY)) {
167165 * @param forQuery the query that caused the notification
168166 * @return a formatted string
169167 */
170- static String format (Notification notification , String forQuery ) {
168+ static String format (GqlNotification notification , String forQuery ) {
171169
172- InputPosition position = notification .position ();
173- boolean hasPosition = position != null ;
170+ var position = notification .position ().orElse (null );
174171
175172 StringBuilder queryHint = new StringBuilder ();
176173 String [] lines = forQuery .split ("(\r \n |\n )" );
177174 for (int i = 0 ; i < lines .length ; i ++) {
178175 String line = lines [i ];
179176 queryHint .append ("\t " ).append (line ).append (LINE_SEPARATOR );
180- if (hasPosition && i + 1 == position .line ()) {
177+ if (position != null && i + 1 == position .line ()) {
181178 queryHint .append ("\t " )
182179 .append (Stream .generate (() -> " " ).limit (position .column () - 1 ).collect (Collectors .joining ()))
183180 .append ("^" )
184181 .append (System .lineSeparator ());
185182 }
186183 }
187- return String .format ("%s: %s%n%s%s" , notification .code (), notification .title (), queryHint ,
188- notification .description ());
184+ return String .format ("%s (%s):%n%s" , notification .statusDescription (), notification .gqlStatus (), queryHint );
189185 }
190186
191187 /**
0 commit comments