/** * Check if the given {@link Attribute} conforms to the has syntax and structural requirements * @param attribute {@link Attribute} to check * @return true if the {@link Attribute} is target of has relation */ private static boolean isHasResourceResource(Attribute attribute){ AttributeType attributeType = attribute.type(); // TODO: Make sure this is tested boolean plays = attributeType.playing().map(Role::label) .allMatch(c -> c.equals(HAS_VALUE.getLabel(attributeType.label()))); return attribute.owners().findAny().isPresent() && plays; } }
/** * Thrown when creating a label which starts with a reserved character {@link Schema.ImplicitType#RESERVED} */ public static GraknTxOperationException invalidLabelStart(Label label){ return create(String.format("Cannot create a label {%s} starting with character {%s} as it is a reserved starting character", label, Schema.ImplicitType.RESERVED.getValue())); }
/** * * @param thing The thing to be validated * @return An error message if the thing does not have all the required resources */ static Optional<String> validateInstancePlaysAllRequiredRoles(Thing thing) { TypeImpl<?, ?> currentConcept = (TypeImpl) thing.type(); while(currentConcept != null){ Map<Role, Boolean> plays = currentConcept.directPlays(); for (Map.Entry<Role, Boolean> playsEntry : plays.entrySet()) { if(playsEntry.getValue()){ Role role = playsEntry.getKey(); // Assert there is a relationship for this type Stream<Relationship> relationships = thing.relationships(role); if(!CommonUtil.containsOnly(relationships, 1)){ Label resourceTypeLabel = Schema.ImplicitType.explicitLabel(role.label()); return Optional.of(VALIDATION_NOT_EXACTLY_ONE_KEY.getMessage(thing.id(), resourceTypeLabel)); } } } currentConcept = (TypeImpl) currentConcept.sup(); } return Optional.empty(); }
cluster.has(name); tx.getType(Schema.ImplicitType.HAS.getLabel("title")).has(provenance);
if (!isImplicit && label.getValue().startsWith(Schema.ImplicitType.RESERVED.getValue())) { throw GraknTxOperationException.invalidLabelStart(label);
/** * Creates a relation type which allows this type and a {@link ai.grakn.concept.Attribute} type to be linked. * @param attributeType The {@link AttributeType} which instances of this type should be allowed to play. * @param has the implicit relation type to build * @param hasValue the implicit role type to build for the {@link AttributeType} * @param hasOwner the implicit role type to build for the type * @param required Indicates if the {@link ai.grakn.concept.Attribute} is required on the entity * @return The {@link Type} itself */ private T has(AttributeType attributeType, Schema.ImplicitType has, Schema.ImplicitType hasValue, Schema.ImplicitType hasOwner, boolean required){ Label attributeLabel = attributeType.label(); Role ownerRole = vertex().tx().putRoleTypeImplicit(hasOwner.getLabel(attributeLabel)); Role valueRole = vertex().tx().putRoleTypeImplicit(hasValue.getLabel(attributeLabel)); RelationshipType relationshipType = vertex().tx().putRelationTypeImplicit(has.getLabel(attributeLabel)). relates(ownerRole). relates(valueRole); //this plays ownerRole; this.play(ownerRole, required); //TODO: Use explicit cardinality of 0-1 rather than just false //attributeType plays valueRole; ((AttributeTypeImpl) attributeType).play(valueRole, false); updateAttributeRelationHierarchy(attributeType, has, hasValue, hasOwner, ownerRole, valueRole, relationshipType); return getThis(); }
/** * @throws GraqlQueryException if no label is specified on {@code resourceType} */ public static HasAttributeTypeProperty of(VarPatternAdmin resourceType, boolean required) { Label resourceLabel = resourceType.getTypeLabel().orElseThrow(() -> GraqlQueryException.noLabelSpecifiedForHas(resourceType) ); VarPattern role = Graql.label(Schema.MetaSchema.ROLE.getLabel()); VarPatternAdmin ownerRole = var().sub(role).admin(); VarPatternAdmin valueRole = var().sub(role).admin(); VarPattern relationType = var().sub(Graql.label(Schema.MetaSchema.RELATIONSHIP.getLabel())); // If a key, limit only to the implicit key type if(required){ ownerRole = ownerRole.label(KEY_OWNER.getLabel(resourceLabel)).admin(); valueRole = valueRole.label(KEY_VALUE.getLabel(resourceLabel)).admin(); relationType = relationType.label(KEY.getLabel(resourceLabel)); } VarPatternAdmin relationOwner = relationType.relates(ownerRole).admin(); VarPatternAdmin relationValue = relationType.admin().var().relates(valueRole).admin(); return new AutoValue_HasAttributeTypeProperty( resourceType, ownerRole, valueRole, relationOwner, relationValue, required); }
private void updateAttributeRelationHierarchy(AttributeType attributeType, Schema.ImplicitType has, Schema.ImplicitType hasValue, Schema.ImplicitType hasOwner, Role ownerRole, Role valueRole, RelationshipType relationshipType){ AttributeType attributeTypeSuper = attributeType.sup(); Label superLabel = attributeTypeSuper.label(); Role ownerRoleSuper = vertex().tx().putRoleTypeImplicit(hasOwner.getLabel(superLabel)); Role valueRoleSuper = vertex().tx().putRoleTypeImplicit(hasValue.getLabel(superLabel)); RelationshipType relationshipTypeSuper = vertex().tx().putRelationTypeImplicit(has.getLabel(superLabel)). relates(ownerRoleSuper).relates(valueRoleSuper); //Create the super type edges from sub role/relations to super roles/relation ownerRole.sup(ownerRoleSuper); valueRole.sup(valueRoleSuper); relationshipType.sup(relationshipTypeSuper); if (!Schema.MetaSchema.ATTRIBUTE.getLabel().equals(superLabel)) { //Make sure the supertype attribute is linked with the role as well ((AttributeTypeImpl) attributeTypeSuper).plays(valueRoleSuper); updateAttributeRelationHierarchy(attributeTypeSuper, has, hasValue, hasOwner, ownerRoleSuper, valueRoleSuper, relationshipTypeSuper); } } /**
@Override public Collection<EquivalentFragmentSet> match(Var start) { Label type = type(); Label has = Schema.ImplicitType.HAS.getLabel(type); Label key = Schema.ImplicitType.KEY.getLabel(type); Label hasOwnerRole = Schema.ImplicitType.HAS_OWNER.getLabel(type); Label keyOwnerRole = Schema.ImplicitType.KEY_OWNER.getLabel(type); Label hasValueRole= Schema.ImplicitType.HAS_VALUE.getLabel(type); Label keyValueRole = Schema.ImplicitType.KEY_VALUE.getLabel(type); Var edge1 = Graql.var(); Var edge2 = Graql.var(); return ImmutableSet.of( //owner rolePlayer edge rolePlayer(this, relationship().var(), edge1, start, null, ImmutableSet.of(hasOwnerRole, keyOwnerRole), ImmutableSet.of(has, key)), //value rolePlayer edge rolePlayer(this, relationship().var(), edge2, attribute().var(), null, ImmutableSet.of(hasValueRole, keyValueRole), ImmutableSet.of(has, key)), neq(this, edge1, edge2) ); }
private Relationship attributeRelationship(Attribute attribute, boolean isInferred) { Schema.ImplicitType has = Schema.ImplicitType.HAS; Schema.ImplicitType hasValue = Schema.ImplicitType.HAS_VALUE; Schema.ImplicitType hasOwner = Schema.ImplicitType.HAS_OWNER; //Is this attribute a key to me? if(type().keys().anyMatch(rt -> rt.equals(attribute.type()))){ has = Schema.ImplicitType.KEY; hasValue = Schema.ImplicitType.KEY_VALUE; hasOwner = Schema.ImplicitType.KEY_OWNER; } Label label = attribute.type().label(); RelationshipType hasAttribute = vertex().tx().getSchemaConcept(has.getLabel(label)); Role hasAttributeOwner = vertex().tx().getSchemaConcept(hasOwner.getLabel(label)); Role hasAttributeValue = vertex().tx().getSchemaConcept(hasValue.getLabel(label)); if(hasAttribute == null || hasAttributeOwner == null || hasAttributeValue == null || type().playing().noneMatch(play -> play.equals(hasAttributeOwner))){ throw GraknTxOperationException.hasNotAllowed(this, attribute); } EdgeElement attributeEdge = addEdge(AttributeImpl.from(attribute), Schema.EdgeLabel.ATTRIBUTE); if(isInferred) attributeEdge.property(Schema.EdgeProperty.IS_INFERRED, true); return vertex().tx().factory().buildRelation(attributeEdge, hasAttribute, hasAttributeOwner, hasAttributeValue); }
/** * Helper method to delete a {@link AttributeType} which is possible linked to this {@link Type}. * The link to {@link AttributeType} is removed if <code>attributeToRemove</code> is in the candidate list * <code>attributeTypes</code> * * @param implicitType the {@link Schema.ImplicitType} which specifies which implicit {@link Role} should be removed * @param attributeTypes The list of candidate which potentially contains the {@link AttributeType} to remove * @param attributeToRemove the {@link AttributeType} to remove * @return the {@link Type} itself */ private T deleteAttribute(Schema.ImplicitType implicitType, Stream<AttributeType> attributeTypes, AttributeType attributeToRemove){ if(attributeTypes.anyMatch(a -> a.equals(attributeToRemove))){ Label label = implicitType.getLabel(attributeToRemove.label()); Role role = vertex().tx().getSchemaConcept(label); if(role != null) unplay(role); } return getThis(); }
@Override public RelationshipAtom toRelationshipAtom(){ SchemaConcept type = getSchemaConcept(); if (type == null) throw GraqlQueryException.illegalAtomConversion(this, RelationshipAtom.class); GraknTx tx = getParentQuery().tx(); Label typeLabel = Schema.ImplicitType.HAS.getLabel(type.label()); return RelationshipAtom.create( Graql.var() .rel(Schema.ImplicitType.HAS_OWNER.getLabel(type.label()).getValue(), getVarName()) .rel(Schema.ImplicitType.HAS_VALUE.getLabel(type.label()).getValue(), getPredicateVariable()) .isa(typeLabel.getValue()) .admin(), getPredicateVariable(), tx.getSchemaConcept(typeLabel).id(), getParentQuery() ); }
/** * Helper method to get implicit relationship types of attributes * * @param types * @return a set of type Labels */ private static Set<Label> getAttributeImplicitRelationTypeLabes(Set<Type> types) { // If the sub graph contains attributes, we may need to add implicit relations to the path return types.stream() .filter(Concept::isAttributeType) .map(attributeType -> Schema.ImplicitType.HAS.getLabel(attributeType.label())) .collect(Collectors.toSet()); }
private Stream<AttributeType> attributes(Schema.ImplicitType implicitType){ //TODO: Make this less convoluted String [] implicitIdentifiers = implicitType.getLabel("").getValue().split("--"); String prefix = implicitIdentifiers[0] + "-"; String suffix = "-" + implicitIdentifiers[1]; //A traversal is not used in this so that caching can be taken advantage of. return playing().map(role -> role.label().getValue()). filter(roleLabel -> roleLabel.startsWith(prefix) && roleLabel.endsWith(suffix)). map(roleLabel -> { String attributeTypeLabel = roleLabel.replace(prefix, "").replace(suffix, ""); return vertex().tx().getAttributeType(attributeTypeLabel); }); }
@Override public T unhas(Attribute attribute){ Role roleHasOwner = vertex().tx().getSchemaConcept(Schema.ImplicitType.HAS_OWNER.getLabel(attribute.type().label())); Role roleKeyOwner = vertex().tx().getSchemaConcept(Schema.ImplicitType.KEY_OWNER.getLabel(attribute.type().label())); Role roleHasValue = vertex().tx().getSchemaConcept(Schema.ImplicitType.HAS_VALUE.getLabel(attribute.type().label())); Role roleKeyValue = vertex().tx().getSchemaConcept(Schema.ImplicitType.KEY_VALUE.getLabel(attribute.type().label())); Stream<Relationship> relationships = relationships(filterNulls(roleHasOwner, roleKeyOwner)); relationships.filter(relationship -> { Stream<Thing> rolePlayers = relationship.rolePlayers(filterNulls(roleHasValue, roleKeyValue)); return rolePlayers.anyMatch(rolePlayer -> rolePlayer.equals(attribute)); }).forEach(Concept::delete); return getThis(); }
private Set<Integer> implicitLabelsToIds(Set<Label> labels, Set<Schema.ImplicitType> implicitTypes){ return labels.stream() .flatMap(label -> implicitTypes.stream().map(it -> it.getLabel(label))) .map(label -> vertex().tx().convertToId(label)) .filter(id -> !id.equals(LabelId.invalid())) .map(LabelId::getValue) .collect(toSet()); }
private Set<SchemaConcept> getTypes(SchemaConcept type, boolean direct) { Set<SchemaConcept> types = direct ? Sets.newHashSet(type) : type.subs().collect(Collectors.toSet()); return type.isImplicit()? types.stream().flatMap(t -> Stream.of(t, tx.getSchemaConcept(Schema.ImplicitType.explicitLabel(t.label())))).collect(Collectors.toSet()): types; }
/** * Make a name for a resource role player representing the value of an OWL data property. */ default Label resourceRole(Label resourceLabel) { return Schema.ImplicitType.HAS_VALUE.getLabel(resourceLabel); } }
/** * Make a name for a resource relation type representing the value of an OWL data property. */ default Label resourceRelation(Label resourceLabel) { return Schema.ImplicitType.HAS.getLabel(resourceLabel); } /**
/** * The name of the entity role type in an entity-role relation representing an OWL data property */ default Label entityRole(Label resourceLabel) { return Schema.ImplicitType.HAS_OWNER.getLabel(resourceLabel); } /**