diff --git a/klab.cli/src/main/java/org/integratedmodelling/cli/views/CLIReasonerView.java b/klab.cli/src/main/java/org/integratedmodelling/cli/views/CLIReasonerView.java index 20bb956d..eb0c5651 100644 --- a/klab.cli/src/main/java/org/integratedmodelling/cli/views/CLIReasonerView.java +++ b/klab.cli/src/main/java/org/integratedmodelling/cli/views/CLIReasonerView.java @@ -595,14 +595,6 @@ public void run() { public static class Info implements Runnable { @Spec CommandSpec commandSpec; - - @Option( - names = {"-a", "--alternative"}, - defaultValue = "false", - description = {"Include inherited " + "traits"}, - required = false) - boolean alternative = false; - @Parameters List arguments; @Override @@ -631,13 +623,7 @@ public void run() { for (var urn : tokens.stream().map(l -> Utils.Strings.join(l, " ")).toList()) { - Concept concept = null; - - if (alternative && reasoner instanceof ReasonerClient reasonerClient) { - concept = reasonerClient.resolveConceptAlternative(urn); - } else { - concept = reasoner.resolveConcept(urn); - } + Concept concept = reasoner.resolveConcept(urn); if (concept != null) { out.println(AUTO.string("Normalized URN: @|blue " + concept.getUrn() + "|@")); @@ -763,7 +749,7 @@ private static String describe(Concept concept, Reasoner reasoner) { ret.append("\nTraits:\n"); for (var trait : allTraits) { ret.append(" ") - .append(trait.getUrn()) + .append(decl(trait)) .append(dirTraits.contains(trait) ? " [direct]" : " [indirect]") .append(" ") .append(trait.getType()) @@ -777,7 +763,7 @@ private static String describe(Concept concept, Reasoner reasoner) { ret.append("\nRoles:\n"); for (var trait : allRoles) { ret.append(" ") - .append(trait.getUrn()) + .append(decl(trait)) .append(dirRoles.contains(trait) ? " [direct]" : " [indirect]") .append("\n"); } @@ -787,7 +773,7 @@ private static String describe(Concept concept, Reasoner reasoner) { if (!affected.isEmpty()) { ret.append("\nAffects:\n"); for (var quality : affected) { - ret.append(" ").append(quality.getUrn()).append("\n"); + ret.append(" ").append(decl(quality)).append("\n"); } } diff --git a/klab.core.common/src/main/java/org/integratedmodelling/common/lang/kim/KimConceptImpl.java b/klab.core.common/src/main/java/org/integratedmodelling/common/lang/kim/KimConceptImpl.java index 5f7cdbc9..3caa3ee7 100644 --- a/klab.core.common/src/main/java/org/integratedmodelling/common/lang/kim/KimConceptImpl.java +++ b/klab.core.common/src/main/java/org/integratedmodelling/common/lang/kim/KimConceptImpl.java @@ -458,12 +458,16 @@ private static List copyWithout( public void addTraits( List traits, BiPredicate checkForConflict) { - addPredicates(traits, this.traits, checkForConflict); + if (!traits.isEmpty()) { + addPredicates(traits, this.traits, checkForConflict); + } } public void addRoles( List roles, BiPredicate checkForConflict) { - addPredicates(roles, this.roles, checkForConflict); + if (!roles.isEmpty()) { + addPredicates(roles, this.roles, checkForConflict); + } } private void addPredicates( @@ -550,10 +554,21 @@ public String finalizeDefinition() { collective = true; } + String main = ""; StringBuilder ret = new StringBuilder(isCollective() ? "each" : ""); if (semanticModifier != null) { ret.append(ret.isEmpty() ? "" : " ").append(semanticModifier.declaration[0]); + ret.append((ret.isEmpty()) ? "" : " ") + .append(name == null ? ((KimConceptImpl) observable).finalizeDefinition() : name); + if (comparisonConcept != null) { + ret.append(" ") + .append(semanticModifier.declaration[1]) + .append(" ") + .append(((KimConceptImpl) comparisonConcept).finalizeDefinition()); + } + main = ret.toString(); + ret = new StringBuilder(); } if (negated) { @@ -581,14 +596,11 @@ public String finalizeDefinition() { .append(((KimConceptImpl) role).computeUrnAndParenthesize()); } - ret.append((ret.isEmpty()) ? "" : " ") - .append(name == null ? ((KimConceptImpl) observable).finalizeDefinition() : name); - - if (comparisonConcept != null) { - ret.append(" ") - .append(semanticModifier.declaration[1]) - .append(" ") - .append(((KimConceptImpl) comparisonConcept).finalizeDefinition()); + if (semanticModifier == null) { + ret.append((ret.isEmpty()) ? "" : " ") + .append(name == null ? ((KimConceptImpl) observable).finalizeDefinition() : name); + } else { + ret.append((ret.isEmpty()) ? "" : " ").append(main); } if (inherent != null) { diff --git a/klab.core.common/src/main/java/org/integratedmodelling/common/services/client/reasoner/ReasonerClient.java b/klab.core.common/src/main/java/org/integratedmodelling/common/services/client/reasoner/ReasonerClient.java index aa2be787..7e8d8a28 100644 --- a/klab.core.common/src/main/java/org/integratedmodelling/common/services/client/reasoner/ReasonerClient.java +++ b/klab.core.common/src/main/java/org/integratedmodelling/common/services/client/reasoner/ReasonerClient.java @@ -96,11 +96,6 @@ public Capabilities capabilities(Scope scope) { return client.get(ServicesAPI.CAPABILITIES, ReasonerCapabilitiesImpl.class); } - // TODO remove when the new semantic builder is in place - public Concept resolveConceptAlternative(String urn) { - return client.post("/resolve/dioporco", urn, Concept.class); - } - @Override public Concept resolveConcept(String definition) { if (!useCaches) { diff --git a/klab.services.reasoner.server/src/main/java/org/integratedmodelling/klab/services/reasoner/controllers/ReasonerController.java b/klab.services.reasoner.server/src/main/java/org/integratedmodelling/klab/services/reasoner/controllers/ReasonerController.java index 8ff3cc51..22c3dfef 100644 --- a/klab.services.reasoner.server/src/main/java/org/integratedmodelling/klab/services/reasoner/controllers/ReasonerController.java +++ b/klab.services.reasoner.server/src/main/java/org/integratedmodelling/klab/services/reasoner/controllers/ReasonerController.java @@ -24,27 +24,23 @@ public class ReasonerController { @Autowired private ReasonerServer reasoner; - // FIXME REMOVE - @PostMapping("/resolve/dioporco") - public @ResponseBody Concept resolveConcept(@RequestBody String definition) { - var syntax = reasoner.klabService().serviceScope().getService(ResourcesService.class).resolveConcept(definition); - if (syntax != null) { - return SemanticsBuilder.create(syntax, reasoner.klabService()).buildConcept(); - } - return null; - } - - /** - * GET /resolve/concept + * POST /resolve/concept from URN * * @param definition * @return */ @PostMapping(ServicesAPI.REASONER.RESOLVE_CONCEPT) - public @ResponseBody Concept resolveConcept(@RequestBody String definition, @RequestParam(name = "alt", required = false) boolean alternative) { + public @ResponseBody Concept resolveConcept( + @RequestBody String definition, + @RequestParam(name = "alt", required = false) boolean alternative) { if (alternative) { - var syntax = reasoner.klabService().serviceScope().getService(ResourcesService.class).resolveConcept(definition); + var syntax = + reasoner + .klabService() + .serviceScope() + .getService(ResourcesService.class) + .resolveConcept(definition); if (syntax != null) { return SemanticsBuilder.create(syntax, reasoner.klabService()).buildConcept(); } @@ -79,23 +75,24 @@ public class ReasonerController { return reasoner.klabService().resolveObservable(definition); } -// @PostMapping(ServicesAPI.REASONER.DECLARE_OBSERVABLE) -// public @ResponseBody Observable declareObservable(@RequestBody DeclarationRequest request) { -// return request.getObservableDeclaration().getPattern() == null -// ? reasoner.klabService().declareObservable(request.getObservableDeclaration()) -// : reasoner -// .klabService() -// .declareObservable(request.getObservableDeclaration(), request.getPatternVariables()); -// } -// -// @PostMapping(ServicesAPI.REASONER.DECLARE_CONCEPT) -// public @ResponseBody Concept declareConcept(@RequestBody DeclarationRequest request) { -// return request.getConceptDeclaration().isPattern() -// ? reasoner.klabService().declareConcept(request.getConceptDeclaration()) -// : reasoner -// .klabService() -// .declareConcept(request.getConceptDeclaration(), request.getPatternVariables()); -// } + // @PostMapping(ServicesAPI.REASONER.DECLARE_OBSERVABLE) + // public @ResponseBody Observable declareObservable(@RequestBody DeclarationRequest request) { + // return request.getObservableDeclaration().getPattern() == null + // ? reasoner.klabService().declareObservable(request.getObservableDeclaration()) + // : reasoner + // .klabService() + // .declareObservable(request.getObservableDeclaration(), + // request.getPatternVariables()); + // } + // + // @PostMapping(ServicesAPI.REASONER.DECLARE_CONCEPT) + // public @ResponseBody Concept declareConcept(@RequestBody DeclarationRequest request) { + // return request.getConceptDeclaration().isPattern() + // ? reasoner.klabService().declareConcept(request.getConceptDeclaration()) + // : reasoner + // .klabService() + // .declareConcept(request.getConceptDeclaration(), request.getPatternVariables()); + // } /** * POST /subsumes diff --git a/klab.services.resources/src/main/java/org/integratedmodelling/klab/services/resources/lang/LanguageAdapter.java b/klab.services.resources/src/main/java/org/integratedmodelling/klab/services/resources/lang/LanguageAdapter.java index 56b8609a..28430c11 100644 --- a/klab.services.resources/src/main/java/org/integratedmodelling/klab/services/resources/lang/LanguageAdapter.java +++ b/klab.services.resources/src/main/java/org/integratedmodelling/klab/services/resources/lang/LanguageAdapter.java @@ -76,23 +76,45 @@ public KimObservable adaptObservable( return ret; } - public KimConceptImpl adaptSemantics( - SemanticSyntax semantics, + private List asTokens( + SemanticSyntax semanticSyntax, String namespace, String projectName, KlabAsset.KnowledgeClass documentClass) { - List tokens = new ArrayList<>(); - - for (var token : semantics) { + for (var token : semanticSyntax) { tokens.add(adaptSemanticToken(token, namespace, projectName, documentClass)); } + return tokens; + } - if (tokens.isEmpty()) { - return null; - } else if (tokens.size() > 1) { - System.out.println("DIO PANDA MUST WRITE adaptSemanticSequence()"); + private List asTokens( + List second, + String namespace, + String projectName, + KlabAsset.KnowledgeClass documentClass) { + var ret = new ArrayList(); + for (var token : second) { + ret.addAll(asTokens(token, namespace, projectName, documentClass)); } + return ret; + } + + public KimConceptImpl adaptSemantics( + SemanticSyntax semantics, + String namespace, + String projectName, + KlabAsset.KnowledgeClass documentClass) { + return adaptSemanticSequence(asTokens(semantics, namespace, projectName, documentClass)); + } + + /** + * FIXME this will not work right: e.g. data:Normalized change rate of geography:Elevation will be + * interpreted as change rate of data:Normalized geography:Elevation. Needs to tokenize + * intelligently from the last, apply traits where they belong and bring the first "each" or + * distribution operator to the final concept + */ + private KimConceptImpl adaptSemanticSequence(List tokens) { // TODO first thing check if there are AND or OR restrictions and behave accordingly @@ -101,53 +123,43 @@ public KimConceptImpl adaptSemantics( List roles = new ArrayList<>(); List traits = new ArrayList<>(); + var isNothing = false; + var observableIsCollective = false; for (var token : tokens) { - if (token.getType().contains(SemanticType.OBSERVABLE)) { ret = token; + observableIsCollective = token.isCollective(); + if (observableIsCollective) { + token.setCollective(false); + token.resetDefinition(); + } } else if (token.getType().contains(SemanticType.ROLE)) { roles.add(token); } else if (token.getType().contains(SemanticType.PREDICATE)) { traits.add(token); + } else if (token.getType().contains(SemanticType.NOTHING)) { + isNothing = true; } } if (ret == null) { // no observable - ret = tokens.getFirst(); + ret = tokens.getLast(); traits.remove(ret); roles.remove(ret); } - roles.sort( - new Comparator() { - @Override - public int compare(KimConcept o1, KimConcept o2) { - return o1.getUrn().compareTo(o2.getUrn()); - } - }); - traits.sort( - new Comparator() { - @Override - public int compare(KimConcept o1, KimConcept o2) { - return o1.getUrn().compareTo(o2.getUrn()); - } - }); + ret.addTraits(traits, null); + ret.addRoles(roles, null); - // rebuild urn - StringBuilder urn = new StringBuilder(); - - for (var role : roles) { - urn.append(urn.isEmpty() ? "" : " ").append(role.getUrn()); - } - for (var trait : traits) { - urn.append(urn.isEmpty() ? "" : " ").append(trait.getUrn()); + if (observableIsCollective) { + ret.setCollective(true); + ret.resetDefinition(); } - urn.append(urn.isEmpty() ? "" : " ").append(ret.getUrn()); - ret.setUrn(urn.toString()); - ret.getTraits().addAll(traits); - ret.getRoles().addAll(roles); + if (isNothing) { + ret.setType(EnumSet.of(SemanticType.NOTHING)); + } return ret; } @@ -198,30 +210,23 @@ public KimConceptImpl adaptSemanticToken( UnarySemanticOperator.valueOf(semantics.getUnaryOperator().getFirst().name())); if (semantics.getUnaryOperator().getSecond() != null && !semantics.getUnaryOperator().getSecond().isEmpty()) { - // TODO not sure we have any situation when there is more than one secondary concept - if (semantics.getUnaryOperator().getSecond().size() > 1) { - System.out.println("DIO POLLO MUST WRITE adaptSemanticSequence()"); - } ret.setComparisonConcept( - adaptSemantics( - semantics.getUnaryOperator().getSecond().getFirst(), - namespace, - projectName, - documentClass)); + adaptSemanticSequence( + asTokens( + semantics.getUnaryOperator().getSecond().getFirst(), + namespace, + projectName, + documentClass))); } } for (var restriction : semantics.getRestrictions()) { - // TODO not sure this happens - if (restriction.getSecond().size() > 1) { - System.out.println("DIO BUFFO MUST WRITE adaptSemanticSequence()"); - } - boolean collective = restriction.getThird(); var operand = - adaptSemantics(restriction.getSecond().get(0), namespace, projectName, documentClass); + adaptSemanticSequence( + asTokens(restriction.getSecond(), namespace, projectName, documentClass)); if (operand != null && collective) { operand.setCollective(true); operand.resetDefinition(); @@ -268,6 +273,7 @@ public KimConceptImpl adaptSemanticToken( return ret; } + public KimNamespace adaptNamespace( NamespaceSyntax namespace, String projectName, Collection notifications) {