diff --git a/reasoner/catalog/openspg-catalog/pom.xml b/reasoner/catalog/openspg-catalog/pom.xml new file mode 100644 index 00000000..ded8793d --- /dev/null +++ b/reasoner/catalog/openspg-catalog/pom.xml @@ -0,0 +1,74 @@ + + + + 4.0.0 + + com.antgroup.openspg.reasoner + reasoner-parent + 0.0.1-SNAPSHOT + ../../pom.xml + + + reasoner-openspg-catalog + + + 8 + 8 + + + + + com.antgroup.openspg.reasoner + reasoner-common + + + com.antgroup.openspg.reasoner + reasoner-lube-api + + + com.antgroup.openspg.reasoner + reasoner-kgdsl-parser + + + junit + junit + + + org.apache.commons + commons-collections4 + + + org.projectlombok + lombok + + + org.apache.httpcomponents + httpclient + + + org.apache.hadoop + hadoop-common + + + com.antgroup.openspg.server + api-http-client + + + com.antgroup.openspg.server + core-schema-model + + + + diff --git a/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/ConceptRule.java b/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/ConceptRule.java new file mode 100644 index 00000000..79de1cff --- /dev/null +++ b/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/ConceptRule.java @@ -0,0 +1,104 @@ +/* + * Copyright 2023 Ant Group CO., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. + */ + +package com.antgroup.openspg.reasoner.catalog.impl.struct; + +import com.alibaba.fastjson.annotation.JSONField; +import lombok.Data; + +@Data +public class ConceptRule { + @JSONField(name = "relation") + private String relation; + + @JSONField(name = "objectMetaType") + private String objectMetaType; + + @JSONField(name = "objectConcept") + private String objectConcept; + + @JSONField(name = "dsl") + private String dsl; + + /** + * Getter method for property relation. + * + * @return property value of relation + */ + public String getRelation() { + return relation; + } + + /** + * Setter method for property relation. + * + * @param relation value to be assigned to property relation + */ + public void setRelation(String relation) { + this.relation = relation; + } + + /** + * Getter method for property objectMetaType. + * + * @return property value of objectMetaType + */ + public String getObjectMetaType() { + return objectMetaType; + } + + /** + * Setter method for property objectMetaType. + * + * @param objectMetaType value to be assigned to property objectMetaType + */ + public void setObjectMetaType(String objectMetaType) { + this.objectMetaType = objectMetaType; + } + + /** + * Getter method for property objectConcept. + * + * @return property value of objectConcept + */ + public String getObjectConcept() { + return objectConcept; + } + + /** + * Setter method for property objectConcept. + * + * @param objectConcept value to be assigned to property objectConcept + */ + public void setObjectConcept(String objectConcept) { + this.objectConcept = objectConcept; + } + + /** + * Getter method for property dsl. + * + * @return property value of dsl + */ + public String getDsl() { + return dsl; + } + + /** + * Setter method for property dsl. + * + * @param dsl value to be assigned to property dsl + */ + public void setDsl(String dsl) { + this.dsl = dsl; + } +} diff --git a/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/PropertyMeta.java b/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/PropertyMeta.java new file mode 100644 index 00000000..27304e30 --- /dev/null +++ b/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/PropertyMeta.java @@ -0,0 +1,144 @@ +/* + * Copyright 2023 Ant Group CO., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. + */ + +package com.antgroup.openspg.reasoner.catalog.impl.struct; + +import com.alibaba.fastjson.annotation.JSONField; +import lombok.Data; + +@Data +public class PropertyMeta { + @JSONField(name = "id") + private Long id; + + @JSONField(name = "name") + private String name; + + @JSONField(name = "attrRangeDetail") + private PropertyRangeDetail propRange; + + @JSONField(name = "propertyCategoryEnum") + private String category; + + @JSONField(name = "spreadable") + private boolean spreadable; + + @JSONField(name = "transformerDetail") + private TransformerDetail transformerDetail; + + @JSONField(name = "logicRule") + private Rule logicRule; + + /** + * Getter method for property logicalRule. + * + * @return property value of logicalRule + */ + public Rule getLogicRule() { + return logicRule; + } + + /** + * Setter method for property logicalRule. + * + * @param logicRule value to be assigned to property logicalRule + */ + public void setLogicRule(Rule logicRule) { + this.logicRule = logicRule; + } + + /** + * Getter method for property name. + * + * @return property value of name + */ + public String getName() { + return name; + } + + /** + * Setter method for property name. + * + * @param name value to be assigned to property name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Getter method for property propRange. + * + * @return property value of propRange + */ + public PropertyRangeDetail getPropRange() { + return propRange; + } + + /** + * Setter method for property propRange. + * + * @param propRange value to be assigned to property propRange + */ + public void setPropRange(PropertyRangeDetail propRange) { + this.propRange = propRange; + } + + /** + * Getter method for property category. + * + * @return property value of category + */ + public String getCategory() { + return category; + } + + /** + * Setter method for property category. + * + * @param category value to be assigned to property category + */ + public void setCategory(String category) { + this.category = category; + } + + public boolean isSpreadable() { + return spreadable; + } + + /** + * Setter method for property spreadable. + * + * @param spreadable value to be assigned to property spreadable + */ + public void setSpreadable(boolean spreadable) { + this.spreadable = spreadable; + } + + /** + * Getter method for property transformerDetail. + * + * @return property value of transformerDetail + */ + public TransformerDetail getTransformerDetail() { + return transformerDetail; + } + + /** + * Setter method for property transformerDetail. + * + * @param transformerDetail value to be assigned to property transformerDetail + */ + public void setTransformerDetail(TransformerDetail transformerDetail) { + this.transformerDetail = transformerDetail; + } +} diff --git a/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/PropertyRangeDetail.java b/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/PropertyRangeDetail.java new file mode 100644 index 00000000..fc2137f9 --- /dev/null +++ b/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/PropertyRangeDetail.java @@ -0,0 +1,56 @@ +/* + * Copyright 2023 Ant Group CO., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. + */ + +package com.antgroup.openspg.reasoner.catalog.impl.struct; + +import com.alibaba.fastjson.annotation.JSONField; +import lombok.Data; + +@Data +public class PropertyRangeDetail { + @JSONField(name = "id") + private long id; + + @JSONField(name = "rangeEntityName") + private String rangeEntityName; + + @JSONField(name = "attrRangeTypeEnumCode") + private String attrRangeTypeEnum; + + /** + * Getter method for property rangeEntityName. + * + * @return property value of rangeEntityName + */ + public String getRangeEntityName() { + return rangeEntityName; + } + + /** + * Getter method for property attrRangeTypeEnum. + * + * @return property value of attrRangeTypeEnum + */ + public String getAttrRangeTypeEnum() { + return attrRangeTypeEnum; + } + + /** + * Setter method for property attrRangeTypeEnum. + * + * @param attrRangeTypeEnum value to be assigned to property attrRangeTypeEnum + */ + public void setAttrRangeTypeEnum(String attrRangeTypeEnum) { + this.attrRangeTypeEnum = attrRangeTypeEnum; + } +} diff --git a/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/RelationTypeDetail.java b/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/RelationTypeDetail.java new file mode 100644 index 00000000..83beae10 --- /dev/null +++ b/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/RelationTypeDetail.java @@ -0,0 +1,159 @@ +/* + * Copyright 2023 Ant Group CO., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. + */ + +package com.antgroup.openspg.reasoner.catalog.impl.struct; + +import com.alibaba.fastjson.annotation.JSONField; +import java.util.List; +import lombok.Data; + +@Data +public class RelationTypeDetail { + @JSONField(name = "id") + private Long id; + + @JSONField(name = "name") + private String name; + + @JSONField(name = "startEntityTypeDetail") + private VertexMeta startEntityType; + + @JSONField(name = "endEntityTypeDetail") + private VertexMeta endEntityType; + + @JSONField(name = "attributeTypeDetailList") + private List attributeTypeDetailList; + + @JSONField(name = "relationDirectionEnumCode") + private String relationDirectionEnum; + + @JSONField(name = "logicRule") + private Rule logicRule; + + /** + * Getter method for property logicalRule. + * + * @return property value of logicalRule + */ + public Rule getLogicRule() { + return logicRule; + } + + /** + * Setter method for property logicalRule. + * + * @param logicRule value to be assigned to property logicalRule + */ + public void setLogicRule(Rule logicRule) { + this.logicRule = logicRule; + } + + /** + * Getter method for property name. + * + * @return property value of name + */ + public Long getId() { + return id; + } + + /** + * Getter method for property name. + * + * @return property value of name + */ + public String getName() { + return name; + } + + /** + * Setter method for property name. + * + * @param name value to be assigned to property name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Getter method for property startEntityType. + * + * @return property value of startEntityType + */ + public VertexMeta getStartEntityType() { + return startEntityType; + } + + /** + * Setter method for property startEntityType. + * + * @param startEntityType value to be assigned to property startEntityType + */ + public void setStartEntityType(VertexMeta startEntityType) { + this.startEntityType = startEntityType; + } + + /** + * Getter method for property endEntityType. + * + * @return property value of endEntityType + */ + public VertexMeta getEndEntityType() { + return endEntityType; + } + + /** + * Setter method for property endEntityType. + * + * @param endEntityType value to be assigned to property endEntityType + */ + public void setEndEntityType(VertexMeta endEntityType) { + this.endEntityType = endEntityType; + } + + /** + * Getter method for property attributeTypeDetailList. + * + * @return property value of attributeTypeDetailList + */ + public List getAttributeTypeDetailList() { + return attributeTypeDetailList; + } + + /** + * Setter method for property attributeTypeDetailList. + * + * @param attributeTypeDetailList value to be assigned to property attributeTypeDetailList + */ + public void setAttributeTypeDetailList(List attributeTypeDetailList) { + this.attributeTypeDetailList = attributeTypeDetailList; + } + + /** + * Getter method for property relationDirectionEnum. + * + * @return property value of relationDirectionEnum + */ + public String getRelationDirectionEnum() { + return relationDirectionEnum; + } + + /** + * Setter method for property relationDirectionEnum. + * + * @param relationDirectionEnum value to be assigned to property relationDirectionEnum + */ + public void setRelationDirectionEnum(String relationDirectionEnum) { + this.relationDirectionEnum = relationDirectionEnum; + } +} diff --git a/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/Rule.java b/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/Rule.java new file mode 100644 index 00000000..c72b8d59 --- /dev/null +++ b/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/Rule.java @@ -0,0 +1,62 @@ +/* + * Copyright 2023 Ant Group CO., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. + */ + +package com.antgroup.openspg.reasoner.catalog.impl.struct; + +import com.alibaba.fastjson.annotation.JSONField; +import lombok.Data; + +@Data +public class Rule { + @JSONField(name = "ruleId") + private String ruleId; + + @JSONField(name = "ruleContent") + private String ruleContent; + + /** + * Getter method for property ruleId. + * + * @return property value of ruleId + */ + public String getRuleId() { + return ruleId; + } + + /** + * Setter method for property ruleId. + * + * @param ruleId value to be assigned to property ruleId + */ + public void setRuleId(String ruleId) { + this.ruleId = ruleId; + } + + /** + * Getter method for property ruleContent. + * + * @return property value of ruleContent + */ + public String getRuleContent() { + return ruleContent; + } + + /** + * Setter method for property ruleContent. + * + * @param ruleContent value to be assigned to property ruleContent + */ + public void setRuleContent(String ruleContent) { + this.ruleContent = ruleContent; + } +} diff --git a/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/TransformerDetail.java b/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/TransformerDetail.java new file mode 100644 index 00000000..302e80bc --- /dev/null +++ b/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/TransformerDetail.java @@ -0,0 +1,42 @@ +/* + * Copyright 2023 Ant Group CO., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. + */ + +package com.antgroup.openspg.reasoner.catalog.impl.struct; + +import com.alibaba.fastjson.annotation.JSONField; +import lombok.Data; + +@Data +public class TransformerDetail { + + @JSONField(name = "transformerCategoryEnum") + private String transformerCategoryEnum; + + /** + * Getter method for property transformerCategoryEnum. + * + * @return property value of transformerCategoryEnum + */ + public String getTransformerCategoryEnum() { + return transformerCategoryEnum; + } + + /** + * Setter method for property transformerCategoryEnum. + * + * @param transformerCategoryEnum value to be assigned to property transformerCategoryEnum + */ + public void setTransformerCategoryEnum(String transformerCategoryEnum) { + this.transformerCategoryEnum = transformerCategoryEnum; + } +} diff --git a/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/VertexMeta.java b/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/VertexMeta.java new file mode 100644 index 00000000..29b2d5cb --- /dev/null +++ b/reasoner/catalog/openspg-catalog/src/main/java/com/antgroup/openspg/reasoner/catalog/impl/struct/VertexMeta.java @@ -0,0 +1,129 @@ +/* + * Copyright 2023 Ant Group CO., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. + */ + +package com.antgroup.openspg.reasoner.catalog.impl.struct; + +import com.alibaba.fastjson.annotation.JSONField; +import java.util.List; +import lombok.Data; + +@Data +public class VertexMeta { + @JSONField(name = "id") + private Long id; + + @JSONField(name = "name") + private String name; + + @JSONField(name = "attributeTypeDetailList") + private List attributeTypeDetailList; + + @JSONField(name = "relationTypeDetailList") + private List relationTypeDetailList; + + @JSONField(name = "inheritAttributeTypeDetailList") + private List inheritAttributeTypeDetailList; + + @JSONField(name = "entityCategory") + private String entityCategory; + + /** + * Getter method for property entityCategory. + * + * @return property value of entityCategory + */ + public String getEntityCategory() { + return entityCategory; + } + + /** + * Setter method for property entityCategory. + * + * @param entityCategory value to be assigned to property entityCategory + */ + public void setEntityCategory(String entityCategory) { + this.entityCategory = entityCategory; + } + + /** + * Getter method for property name. + * + * @return property value of name + */ + public Long getId() { + return id; + } + + /** + * Getter method for property name. + * + * @return property value of name + */ + public String getName() { + return name; + } + + /** + * Setter method for property name. + * + * @param name value to be assigned to property name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Getter method for property attributeTypeDetailList. + * + * @return property value of attributeTypeDetailList + */ + public List getAttributeTypeDetailList() { + return attributeTypeDetailList; + } + + /** + * Setter method for property attributeTypeDetailList. + * + * @param attributeTypeDetailList value to be assigned to property attributeTypeDetailList + */ + public void setAttributeTypeDetailList(List attributeTypeDetailList) { + this.attributeTypeDetailList = attributeTypeDetailList; + } + + /** + * Getter method for property relationTypeDetailList. + * + * @return property value of relationTypeDetailList + */ + public List getRelationTypeDetailList() { + return relationTypeDetailList; + } + + /** + * Getter method for property relationTypeDetailList. + * + * @return property value of relationTypeDetailList + */ + public List getInheritAttributeTypeDetailList() { + return inheritAttributeTypeDetailList; + } + + /** + * Setter method for property relationTypeDetailList. + * + * @param relationTypeDetailList value to be assigned to property relationTypeDetailList + */ + public void setRelationTypeDetailList(List relationTypeDetailList) { + this.relationTypeDetailList = relationTypeDetailList; + } +} diff --git a/reasoner/catalog/openspg-catalog/src/main/scala/com/antgroup/openspg/reasoner/catalog/impl/KgSchemaConnectionInfo.scala b/reasoner/catalog/openspg-catalog/src/main/scala/com/antgroup/openspg/reasoner/catalog/impl/KgSchemaConnectionInfo.scala new file mode 100644 index 00000000..a326ab6f --- /dev/null +++ b/reasoner/catalog/openspg-catalog/src/main/scala/com/antgroup/openspg/reasoner/catalog/impl/KgSchemaConnectionInfo.scala @@ -0,0 +1,16 @@ +/* + * Copyright 2023 Ant Group CO., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. + */ + +package com.antgroup.openspg.reasoner.catalog.impl + +case class KgSchemaConnectionInfo(uri: String, token: String) diff --git a/reasoner/catalog/openspg-catalog/src/main/scala/com/antgroup/openspg/reasoner/catalog/impl/OpenSPGCatalog.scala b/reasoner/catalog/openspg-catalog/src/main/scala/com/antgroup/openspg/reasoner/catalog/impl/OpenSPGCatalog.scala new file mode 100644 index 00000000..b107ffd6 --- /dev/null +++ b/reasoner/catalog/openspg-catalog/src/main/scala/com/antgroup/openspg/reasoner/catalog/impl/OpenSPGCatalog.scala @@ -0,0 +1,252 @@ +/* + * Copyright 2023 Ant Group CO., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. + */ + +package com.antgroup.openspg.reasoner.catalog.impl + +import scala.collection.JavaConverters._ +import scala.collection.mutable +import scala.collection.mutable.ListBuffer + +import com.antgroup.openspg.core.schema.model.`type`.{BaseAdvancedType, BaseSPGType, BasicType, ProjectSchema} +import com.antgroup.openspg.core.schema.model.predicate.{Property, Relation} +import com.antgroup.openspg.core.schema.model.semantic.DynamicTaxonomySemantic +import com.antgroup.openspg.reasoner.common.constants.Constants +import com.antgroup.openspg.reasoner.common.exception.SchemaException +import com.antgroup.openspg.reasoner.common.graph.edge.SPO +import com.antgroup.openspg.reasoner.common.types.KTString +import com.antgroup.openspg.reasoner.lube.catalog.{AbstractConnection, Catalog, GeneralSemanticRule, PropertyGraphSchema, SemanticPropertyGraph, SemanticRule} +import com.antgroup.openspg.reasoner.lube.catalog.struct.{Edge, Field, Node} +import com.antgroup.openspg.server.api.facade.ApiResponse +import com.antgroup.openspg.server.api.facade.client.{ConceptFacade, SchemaFacade} +import com.antgroup.openspg.server.api.facade.dto.schema.request.{ConceptRequest, ProjectSchemaRequest} +import com.antgroup.openspg.server.api.http.client.{HttpConceptFacade, HttpSchemaFacade} +import com.antgroup.openspg.server.api.http.client.util.{ConnectionInfo, HttpClientBootstrap} +import org.apache.commons.collections4.CollectionUtils +import org.apache.commons.lang3.StringUtils + + +class OpenSPGCatalog(val projectId: Long, + val connInfo: KgSchemaConnectionInfo, + val projectSchema: ProjectSchema = null) extends Catalog { + + if (projectSchema == null) { + HttpClientBootstrap.init(new ConnectionInfo(connInfo.uri)) + } + + private val spgSchemaFacade: SchemaFacade = new HttpSchemaFacade() + private val spgConceptFacade: ConceptFacade = new HttpConceptFacade() + + private val defineRules = new mutable.HashMap[String, SemanticRule]() + + /** + * Get schema from knowledge graph + */ + override def getKnowledgeGraph(): SemanticPropertyGraph = { + val realProjectSchema: ProjectSchema = + if (projectSchema == null) { + val request = new ProjectSchemaRequest() + request.setProjectId(projectId) + resultOf(spgSchemaFacade.queryProjectSchema(request)) + } else { + projectSchema + } + + val nodes: mutable.Map[String, Node] = new mutable.HashMap[String, Node]() + val edges: mutable.Map[SPO, Edge] = new mutable.HashMap[SPO, Edge] + realProjectSchema.getSpgTypes.asScala.foreach(spgType => { + val node = toNode(realProjectSchema, spgType) + if (node != null) { + nodes.put(spgType.getName, node) + + val vertexEdges = toEdges(realProjectSchema, spgType) + for (e <- vertexEdges) { + if (edges.contains(e._1)) { + val edgeInfo = edges(e._1) + val mergeSet = edgeInfo.properties ++ e._2.properties + edges += (e._1 -> Edge( + edgeInfo.startNode, + edgeInfo.typeName, + edgeInfo.endNode, + mergeSet, + edgeInfo.resolved)) + } else { + edges += e + } + } + } + }) + + new SemanticPropertyGraph( + Catalog.defaultGraphName, + new PropertyGraphSchema(nodes, edges), + defineRules, + null) + } + + private def toNode(projectSchema: ProjectSchema, spgType: BaseSPGType): Node = { + val attrList = new ListBuffer[Field]() + attrList.+=(defaultTypeField) + spgType match { + case _: BasicType => + null + case advancedType: BaseAdvancedType => + attrList.++=(advancedType.getProperties.asScala.map(spgProperty => { + toField(projectSchema, spgType, spgProperty) + })) + attrList.++=(getDefaultNodeProperties()) + Node( + advancedType.getName, + PropertySchemaOps.toNodeType(spgType.getSpgTypeEnum), + attrList.toSet, + true) + } + } + + private def toField(projectSchema: ProjectSchema, + spgType: BaseSPGType, + spgProperty: Property): Field = { + val propertyType = PropertySchemaOps + .stringToKgType2(projectSchema.getByRef(spgProperty.getObjectTypeRef)) + val rule = spgProperty.getLogicalRule + val predicateName = spgProperty.getName + if (rule != null && StringUtils.isNotBlank(rule.getContent)) { + defineRules.put(s"${spgType.getName}.${predicateName}", GeneralSemanticRule(rule.getContent)) + new Field(predicateName, propertyType, false) + } else { + new Field(predicateName, propertyType, true) + } + } + + private def defaultTypeField: Field = { + new Field(Constants.CONTEXT_LABEL, KTString, true) + } + + private def toEdges(projectSchema: ProjectSchema, spgType: BaseSPGType): Map[SPO, Edge] = { + if (CollectionUtils.isEmpty(spgType.getRelations)) { + Map.empty + } else { + spgType.getRelations.asScala + .flatMap(relation => toEdge(projectSchema, spgType, relation)) + .map(e => (new SPO(e.startNode, e.typeName, e.endNode), e)) + .toMap + } + } + + private def toEdge(projectSchema: ProjectSchema, + spgType: BaseSPGType, + rel: Relation): List[Edge] = { + val attrList = rel.getSubProperties.asScala.toList + val fields = new ListBuffer[Field]() + val s = spgType.getName + val p = rel.getName + val o = rel.getObjectTypeRef.getName + val spo = new SPO(s, p, o).toString + + fields.++=(attrList.map(att => { + val relationType = PropertySchemaOps + .stringToKgType2(projectSchema.getByRef(att.getObjectTypeRef)) + new Field(att.getName, relationType, true) + })) + fields.+=(defaultTypeField) + fields.++=(getDefaultEdgeProperties()) + + val rule = rel.getLogicalRule + if (rule != null && StringUtils.isNotBlank(rule.getContent)) { + defineRules.put(spo, GeneralSemanticRule(rule.getContent)) + List.apply(Edge(s, p, o, fields.toSet, false)) + } else if (p.equals("belongTo")) { + val request = new ConceptRequest() + request.setConceptTypeName(o) + + val concept = resultOf(spgConceptFacade.queryConcept(request)) + if (CollectionUtils.isNotEmpty(concept.getConcepts)) { + concept.getConcepts.asScala + .map(r => { + r.getSemantics.asScala.foreach { + case belong: DynamicTaxonomySemantic => + if (belong.getLogicalRule != null) { + defineRules.put(spo + "/" + r.getName, + GeneralSemanticRule(belong.getLogicalRule.getContent)) + } + case _ => + } + Edge(s, p, o + "/" + r.getName, fields.toSet, false) + }) + .toList + } else { + List.apply(Edge(s, p, o, fields.toSet, true)) + } + } else { + List.apply(Edge(s, p, o, fields.toSet, true)) + } + } + + /** + * Get connections of knowledge graph + * + * @return + */ + override def getConnections(): Map[AbstractConnection, Set[String]] = { + val connections = new mutable.HashMap[AbstractConnection, Set[String]]() + graphRepository + .get("KG") + .map(graph => { + val graphSchema = graph.graphSchema + + val types = new mutable.HashSet[String]() + types.++=(graphSchema.nodes.keySet) + types.++=(graphSchema.edges.map(x => x._1.toString).toSet) + + connections.put(new AbstractConnection {}, types.toSet) + }) + connections.toMap + } + + private def resultOf[T](apiResponse: ApiResponse[T]): T = { + if (apiResponse.isSuccess) { + apiResponse.getData + } else { + throw SchemaException("Get Schema failed") + } + } + + /** + * get default node properties + * + * @return + */ + override def getDefaultNodeProperties() + : Set[Field] = { + Set.apply( + new Field(Constants.NODE_ID_KEY, KTString, true), + new Field(Constants.VERTEX_INTERNAL_ID_KEY, KTString, true), + new Field(Constants.CONTEXT_LABEL, KTString, true)) + } + + /** + * get default edge properties + */ + override def getDefaultEdgeProperties() + : Set[Field] = { + Set.apply( + new Field(Constants.CONTEXT_LABEL, KTString, true), + new Field(Constants.EDGE_FROM_ID_KEY, KTString, true), + new Field(Constants.EDGE_TO_ID_KEY, KTString, true), + new Field(Constants.EDGE_FROM_INTERNAL_ID_KEY, KTString, true), + new Field(Constants.EDGE_TO_INTERNAL_ID_KEY, KTString, true), + new Field(Constants.EDGE_FROM_ID_TYPE_KEY, KTString, true), + new Field(Constants.EDGE_TO_ID_TYPE_KEY, KTString, true) + ) + } + +} diff --git a/reasoner/catalog/openspg-catalog/src/main/scala/com/antgroup/openspg/reasoner/catalog/impl/PropertySchemaOps.scala b/reasoner/catalog/openspg-catalog/src/main/scala/com/antgroup/openspg/reasoner/catalog/impl/PropertySchemaOps.scala new file mode 100644 index 00000000..b51616cc --- /dev/null +++ b/reasoner/catalog/openspg-catalog/src/main/scala/com/antgroup/openspg/reasoner/catalog/impl/PropertySchemaOps.scala @@ -0,0 +1,91 @@ +/* + * Copyright 2023 Ant Group CO., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. + */ + +package com.antgroup.openspg.reasoner.catalog.impl + +import scala.language.implicitConversions + +import com.antgroup.openspg.core.schema.model.`type`.{BaseSPGType, BasicType, ConceptType, EntityType, EventType, SPGTypeEnum, StandardType} +import com.antgroup.openspg.reasoner.catalog.impl.struct.PropertyMeta +import com.antgroup.openspg.reasoner.common.exception.KGValueException +import com.antgroup.openspg.reasoner.common.types._ +import com.antgroup.openspg.reasoner.lube.catalog.struct.NodeType + +object PropertySchemaOps { + + implicit def stringToKgType(propertySchema: PropertyMeta): KgType = { + propertySchema.getCategory match { + case "BASIC" => + toKgType(propertySchema.getPropRange.getAttrRangeTypeEnum) + case "CONCEPT" => + KTConcept(propertySchema.getPropRange.getRangeEntityName) + case "STANDARD" => + KTStd(propertySchema.getPropRange.getRangeEntityName, propertySchema.isSpreadable) + case "PROPERTY" => + KTStd(propertySchema.getPropRange.getRangeEntityName, propertySchema.isSpreadable) + case "ENTITY" => + KTAdvanced(propertySchema.getPropRange.getRangeEntityName) + case _ => throw KGValueException(s"unsupported type: ${propertySchema.getCategory}") + } + } + + def stringToKgType2(spgType: BaseSPGType): KgType = { + spgType match { + case entityType: EntityType => + KTAdvanced(entityType.getName) + case conceptType: ConceptType => + KTConcept(conceptType.getName) + case eventType: EventType => + // todo + KTAdvanced(eventType.getName) + case standardType: StandardType => + KTStd(spgType.getName, standardType.getSpreadable) + case basicType: BasicType => + toKgType(basicType.getBasicType.name()) + case _ => + throw KGValueException(s"unsupported type: ${spgType}") + } + } + + private def toKgType(basicType: String): KgType = { + basicType.toUpperCase() match { + case "INTEGER" => KTLong + case "LONG" => KTLong + case "TEXT" => KTString + case "FLOAT" => KTDouble + case "DOUBLE" => KTDouble + case "BOOLEAN" => KTString + case "DATE" => KTString + case "TIME" => KTString + case "URL" => KTString + case "DATETIME" => KTString + case "TIMESTAMP" => KTString + case _ => throw KGValueException(s"unsupported type: $basicType") + } + } + + def toNodeType(spgType: SPGTypeEnum): NodeType.Value = { + spgType match { + case SPGTypeEnum.ENTITY_TYPE => + NodeType.ADVANCED + case SPGTypeEnum.CONCEPT_TYPE => + NodeType.CONCEPT + case SPGTypeEnum.STANDARD_TYPE => + NodeType.STANDARD + case SPGTypeEnum.EVENT_TYPE => + NodeType.EVENT + case _ => throw KGValueException(s"unsupported type: $spgType") + } + } + +} diff --git a/reasoner/catalog/openspg-catalog/src/test/java/com/antgroup/openspg/reasoner/catalog/impl/OpenSPGCatalogTest.java b/reasoner/catalog/openspg-catalog/src/test/java/com/antgroup/openspg/reasoner/catalog/impl/OpenSPGCatalogTest.java new file mode 100644 index 00000000..7acbddd5 --- /dev/null +++ b/reasoner/catalog/openspg-catalog/src/test/java/com/antgroup/openspg/reasoner/catalog/impl/OpenSPGCatalogTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2023 Ant Group CO., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. + */ + +package com.antgroup.openspg.reasoner.catalog.impl; + +import com.antgroup.openspg.reasoner.lube.catalog.SemanticPropertyGraph; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +@Ignore +public class OpenSPGCatalogTest { + + public static final KgSchemaConnectionInfo connInfo = + new KgSchemaConnectionInfo("http://127.0.0.1:8887", "a8bB6398B6Da9170"); + + @Test + public void testGet() { + long projectId = 2L; + + OpenSPGCatalog catalog = new OpenSPGCatalog(projectId, connInfo, null); + catalog.init(); + SemanticPropertyGraph graph = catalog.getKnowledgeGraph(); + + Assert.assertNotNull(graph); + } +} diff --git a/reasoner/lube-api/src/main/scala/com/antgroup/openspg/reasoner/lube/catalog/Catalog.scala b/reasoner/lube-api/src/main/scala/com/antgroup/openspg/reasoner/lube/catalog/Catalog.scala index 77c8c4da..76c72ef9 100644 --- a/reasoner/lube-api/src/main/scala/com/antgroup/openspg/reasoner/lube/catalog/Catalog.scala +++ b/reasoner/lube-api/src/main/scala/com/antgroup/openspg/reasoner/lube/catalog/Catalog.scala @@ -32,7 +32,7 @@ import com.antgroup.openspg.reasoner.lube.common.graph.IRGraph * and the property graph at runtime */ abstract class Catalog() extends Serializable { - private val graphRepository = new mutable.HashMap[String, SemanticPropertyGraph]() + protected val graphRepository = new mutable.HashMap[String, SemanticPropertyGraph]() private val connections = new mutable.HashMap[String, AbstractConnection]() /** diff --git a/reasoner/pom.xml b/reasoner/pom.xml index c1cd9177..ed791a52 100644 --- a/reasoner/pom.xml +++ b/reasoner/pom.xml @@ -29,6 +29,7 @@ udf lube-api kgdsl-parser + catalog/openspg-catalog