44import com .google .common .collect .ImmutableSet ;
55import edu .stanford .protege .gateway .EntityIsMissingException ;
66import edu .stanford .protege .gateway .SecurityContextHelper ;
7+ import edu .stanford .protege .gateway .ValidationException ;
78import edu .stanford .protege .gateway .dto .BaseExclusionTerm ;
9+ import edu .stanford .protege .gateway .dto .BaseIndexTerm ;
810import edu .stanford .protege .gateway .dto .CreateEntityDto ;
11+ import edu .stanford .protege .gateway .dto .EntityLanguageTermsDto ;
12+ import edu .stanford .protege .gateway .dto .LanguageTerm ;
913import edu .stanford .protege .gateway .dto .OWLEntityDto ;
14+ import edu .stanford .protege .gateway .linearization .EntityLinearizationService ;
15+ import edu .stanford .protege .gateway .linearization .commands .LinearizationDefinition ;
1016import edu .stanford .protege .gateway .ontology .OntologyService ;
1117import edu .stanford .protege .gateway .ontology .commands .*;
18+ import edu .stanford .protege .gateway .postcoordination .CustomScalesMapper ;
19+ import edu .stanford .protege .gateway .postcoordination .SpecificationMapper ;
20+ import edu .stanford .protege .gateway .postcoordination .commands .*;
1221import edu .stanford .protege .webprotege .common .*;
1322import edu .stanford .protege .webprotege .criteria .EntityTypeIsOneOfCriteria ;
1423import edu .stanford .protege .webprotege .ipc .CommandExecutor ;
24+ import edu .stanford .protege .webprotege .ipc .ExecutionContext ;
1525import edu .stanford .protege .webprotege .search .DeprecatedEntitiesTreatment ;
16- import edu .stanford .protege .webprotege .search .EntitySearchResult ;
17- import edu .stanford .protege .webprotege .search .PerformEntitySearchAction ;
18- import edu .stanford .protege .webprotege .search .PerformEntitySearchResult ;
1926import org .semanticweb .owlapi .model .EntityType ;
2027import org .semanticweb .owlapi .model .IRI ;
2128import org .slf4j .Logger ;
@@ -40,14 +47,29 @@ public class ValidatorService {
4047 private final CommandExecutor <FilterExistingEntitiesRequest , FilterExistingEntitiesResponse > filterExistingEntitiesExecutor ;
4148
4249 private final CommandExecutor <GetExistingClassesForApiRequest , GetExistingClassesForApiResponse > getEntitySearchExecutor ;
50+ private final CommandExecutor <ValidateEntityUpdateRequest , ValidateEntityUpdateResponse > validateEntityUpdateExecutor ;
51+ private final CommandExecutor <GetTablePostCoordinationAxisRequest , GetTablePostCoordinationAxisResponse > tableConfigurationExecutor ;
52+ private final CommandExecutor <GetIcatxEntityTypeRequest , GetIcatxEntityTypeResponse > entityTypesExecutor ;
53+ private final CommandExecutor <CheckNonExistentIrisRequest , CheckNonExistentIrisResponse > checkNonExistentIrisExecutor ;
54+ private final EntityLinearizationService linearizationService ;
4355
4456
4557 public ValidatorService (CommandExecutor <GetIsExistingProjectRequest , GetIsExistingProjectResponse > isExistingProjectExecutor ,
4658 CommandExecutor <FilterExistingEntitiesRequest , FilterExistingEntitiesResponse > filterExistingEntitiesExecutor ,
47- CommandExecutor <GetExistingClassesForApiRequest , GetExistingClassesForApiResponse > getEntitySearchExecutor ) {
59+ CommandExecutor <GetExistingClassesForApiRequest , GetExistingClassesForApiResponse > getEntitySearchExecutor ,
60+ CommandExecutor <ValidateEntityUpdateRequest , ValidateEntityUpdateResponse > validateEntityUpdateExecutor ,
61+ CommandExecutor <GetTablePostCoordinationAxisRequest , GetTablePostCoordinationAxisResponse > tableConfigurationExecutor ,
62+ CommandExecutor <GetIcatxEntityTypeRequest , GetIcatxEntityTypeResponse > entityTypesExecutor ,
63+ CommandExecutor <CheckNonExistentIrisRequest , CheckNonExistentIrisResponse > checkNonExistentIrisExecutor ,
64+ EntityLinearizationService linearizationService ) {
4865 this .isExistingProjectExecutor = isExistingProjectExecutor ;
4966 this .filterExistingEntitiesExecutor = filterExistingEntitiesExecutor ;
5067 this .getEntitySearchExecutor = getEntitySearchExecutor ;
68+ this .validateEntityUpdateExecutor = validateEntityUpdateExecutor ;
69+ this .tableConfigurationExecutor = tableConfigurationExecutor ;
70+ this .entityTypesExecutor = entityTypesExecutor ;
71+ this .checkNonExistentIrisExecutor = checkNonExistentIrisExecutor ;
72+ this .linearizationService = linearizationService ;
5173 }
5274
5375
@@ -172,14 +194,200 @@ private void validateBaseExclusionTerm(BaseExclusionTerm term) {
172194 }
173195 }
174196
175- public void validateOWLEntityDto (OWLEntityDto owlEntityDto ) {
197+ public void validateOWLEntityDto (OWLEntityDto owlEntityDto , String projectId ) {
176198 if (owlEntityDto == null ) {
177199 throw new IllegalArgumentException ("OWLEntityDto cannot be null" );
178200 }
179201
180202 if (owlEntityDto .languageTerms () != null && owlEntityDto .languageTerms ().baseExclusionTerms () != null ) {
181203 validateBaseExclusionTerms (owlEntityDto .languageTerms ().baseExclusionTerms ());
182204 }
205+
206+ validateTermIdsExistence (owlEntityDto , projectId );
207+ validateParentsExistence (owlEntityDto , projectId );
208+
209+ if (owlEntityDto .postcoordination () != null ) {
210+ validatePostcoordination (owlEntityDto , projectId );
211+ }
212+ }
213+
214+ private void validateParentsExistence (OWLEntityDto owlEntityDto , String projectId ) {
215+ if (owlEntityDto .parents () == null || owlEntityDto .parents ().isEmpty ()) {
216+ return ;
217+ }
218+
219+ try {
220+ Set <IRI > parentIris = owlEntityDto .parents ().stream ()
221+ .filter (parent -> parent != null && !parent .trim ().isEmpty ())
222+ .map (IRI ::create )
223+ .collect (Collectors .toSet ());
224+
225+ if (parentIris .isEmpty ()) {
226+ return ;
227+ }
228+
229+ Set <IRI > nonExistentIris = checkNonExistentIrisExecutor .execute (
230+ new CheckNonExistentIrisRequest (ProjectId .valueOf (projectId ), ImmutableSet .copyOf (parentIris )),
231+ SecurityContextHelper .getExecutionContext ()
232+ ).get ().nonExistentIris ();
233+
234+ if (!nonExistentIris .isEmpty ()) {
235+ List <String > missingParents = nonExistentIris .stream ()
236+ .map (IRI ::toString )
237+ .collect (Collectors .toList ());
238+ throw new IllegalArgumentException ("The following parent entities do not exist: " + String .join (", " , missingParents ));
239+ }
240+ } catch (InterruptedException | ExecutionException e ) {
241+ LOGGER .error ("Could not verify if parents are valid!" , e );
242+ throw new RuntimeException ("Error validating parents existence" , e );
243+ }
244+ }
245+
246+ private void validateTermIdsExistence (OWLEntityDto owlEntityDto , String projectId ) {
247+ List <String > termIds = collectTermIds (owlEntityDto );
248+
249+ if (termIds .isEmpty ()) {
250+ return ;
251+ }
252+
253+ try {
254+ Set <IRI > termIdIris = termIds .stream ()
255+ .map (IRI ::create )
256+ .collect (Collectors .toSet ());
257+
258+ Set <IRI > nonExistentIris = checkNonExistentIrisExecutor .execute (
259+ new CheckNonExistentIrisRequest (ProjectId .valueOf (projectId ), ImmutableSet .copyOf (termIdIris )),
260+ SecurityContextHelper .getExecutionContext ()
261+ ).get ().nonExistentIris ();
262+
263+ if (!nonExistentIris .isEmpty ()) {
264+ List <String > missingTermIds = nonExistentIris .stream ()
265+ .map (IRI ::toString )
266+ .collect (Collectors .toList ());
267+ throw new IllegalArgumentException ("The following term IDs do not exist: " + String .join (", " , missingTermIds ));
268+ }
269+ } catch (InterruptedException | ExecutionException e ) {
270+ LOGGER .error ("Could not verify if term IDs are valid!" , e );
271+ throw new RuntimeException ("Error validating term IDs existence" , e );
272+ }
273+ }
274+
275+ private List <String > collectTermIds (OWLEntityDto owlEntityDto ) {
276+ List <String > termIds = new ArrayList <>();
277+
278+ // Colectare din languageTerms
279+ if (owlEntityDto .languageTerms () != null ) {
280+ EntityLanguageTermsDto languageTerms = owlEntityDto .languageTerms ();
281+
282+ // Title termId
283+ if (languageTerms .title () != null && languageTerms .title ().termId () != null && !languageTerms .title ().termId ().trim ().isEmpty ()) {
284+ termIds .add (languageTerms .title ().termId ());
285+ }
286+
287+ // Definition termId
288+ if (languageTerms .definition () != null && languageTerms .definition ().termId () != null && !languageTerms .definition ().termId ().trim ().isEmpty ()) {
289+ termIds .add (languageTerms .definition ().termId ());
290+ }
291+
292+ // LongDefinition termId
293+ if (languageTerms .longDefinition () != null && languageTerms .longDefinition ().termId () != null && !languageTerms .longDefinition ().termId ().trim ().isEmpty ()) {
294+ termIds .add (languageTerms .longDefinition ().termId ());
295+ }
296+
297+ // FullySpecifiedName termId
298+ if (languageTerms .fullySpecifiedName () != null && languageTerms .fullySpecifiedName ().termId () != null && !languageTerms .fullySpecifiedName ().termId ().trim ().isEmpty ()) {
299+ termIds .add (languageTerms .fullySpecifiedName ().termId ());
300+ }
301+
302+ // BaseIndexTerms termIds
303+ if (languageTerms .baseIndexTerms () != null ) {
304+ languageTerms .baseIndexTerms ().stream ()
305+ .filter (term -> term != null && term .termId () != null && !term .termId ().trim ().isEmpty ())
306+ .forEach (term -> termIds .add (term .termId ()));
307+ }
308+
309+ // BaseExclusionTerms termIds și foundationReferences
310+ if (languageTerms .baseExclusionTerms () != null ) {
311+ languageTerms .baseExclusionTerms ().stream ()
312+ .filter (term -> term != null )
313+ .forEach (term -> {
314+ if (term .termId () != null && !term .termId ().trim ().isEmpty ()) {
315+ termIds .add (term .termId ());
316+ }
317+ if (term .foundationReference () != null && !term .foundationReference ().trim ().isEmpty ()) {
318+ termIds .add (term .foundationReference ());
319+ }
320+ });
321+ }
322+ }
323+
324+ // Colectare din diagnosticCriteria
325+ if (owlEntityDto .diagnosticCriteria () != null && owlEntityDto .diagnosticCriteria ().termId () != null && !owlEntityDto .diagnosticCriteria ().termId ().trim ().isEmpty ()) {
326+ termIds .add (owlEntityDto .diagnosticCriteria ().termId ());
327+ }
328+
329+ // Colectare din relatedImpairments
330+ if (owlEntityDto .relatedImpairments () != null ) {
331+ owlEntityDto .relatedImpairments ().stream ()
332+ .filter (term -> term != null && term .termId () != null && !term .termId ().trim ().isEmpty ())
333+ .forEach (term -> termIds .add (term .termId ()));
334+ }
335+
336+ return termIds ;
337+ }
338+
339+ private void validatePostcoordination (OWLEntityDto owlEntityDto , String projectId ) {
340+ try {
341+ ExecutionContext executionContext = SecurityContextHelper .getExecutionContext ();
342+ ProjectId projectIdObj = ProjectId .valueOf (projectId );
343+ String entityIri = owlEntityDto .entityIRI ();
344+
345+ // Mapare custom scales values
346+ WhoficCustomScalesValues customScalesValues = CustomScalesMapper .mapFromDtoList (
347+ entityIri ,
348+ owlEntityDto .postcoordination ().scaleCustomizations ()
349+ );
350+
351+ // Obținere table configuration
352+ TableConfiguration tableConfiguration = tableConfigurationExecutor .execute (
353+ new GetTablePostCoordinationAxisRequest (IRI .create (entityIri ), projectIdObj ),
354+ executionContext
355+ ).get ().tableConfiguration ();
356+
357+ // Obținere entity types
358+ List <String > entityTypes = entityTypesExecutor .execute (
359+ GetIcatxEntityTypeRequest .create (IRI .create (entityIri ), projectIdObj ),
360+ executionContext
361+ ).get ().icatxEntityTypes ();
362+
363+ // Obținere definitions
364+ List <LinearizationDefinition > definitions = linearizationService .getDefinitionList (executionContext );
365+
366+ // Mapare specification
367+ WhoficEntityPostCoordinationSpecification specification = SpecificationMapper .mapFromDtoList (
368+ entityIri ,
369+ entityTypes .isEmpty () ? "ICD" : entityTypes .get (0 ),
370+ owlEntityDto .postcoordination ().postcoordinationSpecifications (),
371+ definitions ,
372+ tableConfiguration
373+ );
374+
375+ // Validare
376+ ValidateEntityUpdateResponse validationResponse = validateEntityUpdateExecutor .execute (
377+ new ValidateEntityUpdateRequest (projectIdObj , customScalesValues , specification ),
378+ executionContext
379+ ).get ();
380+
381+ if (validationResponse .getErrorMessages () != null && !validationResponse .getErrorMessages ().isEmpty ()) {
382+ String errorMessage = String .join ("; " , validationResponse .getErrorMessages ());
383+ throw new ValidationException (errorMessage );
384+ }
385+ } catch (ValidationException e ) {
386+ throw e ;
387+ } catch (Exception e ) {
388+ LOGGER .error ("Error validating postcoordination for entity " + owlEntityDto .entityIRI (), e );
389+ throw new RuntimeException ("Error validating postcoordination for entity " + owlEntityDto .entityIRI (), e );
390+ }
183391 }
184392
185393 public static boolean hasEscapeCharacters (String input ) {
0 commit comments