public static void printWholeCompletionMessage(MigrationOptions options){ System.out.println("Migration complete."); if(options.isVerbose()) { System.out.println("Gathering information about migrated data. If in a hurry, you can ctrl+c now."); GraknTx tx = new Grakn(options.getUri()).session(options.getKeyspace()).transaction(GraknTxType.WRITE); QueryBuilder qb = tx.graql(); StringBuilder builder = new StringBuilder(); builder.append("Graph schema contains:\n"); builder.append("\t ").append(tx.admin().getMetaEntityType().instances().count()).append(" entity types\n"); builder.append("\t ").append(tx.admin().getMetaRelationType().instances().count()).append(" relation types\n"); builder.append("\t ").append(tx.admin().getMetaRole().subs().count()).append(" roles\n\n"); builder.append("\t ").append(tx.admin().getMetaAttributeType().instances().count()).append(" resource types\n"); builder.append("\t ").append(tx.admin().getMetaRule().subs().count()).append(" rules\n\n"); builder.append("Graph data contains:\n"); builder.append("\t ").append(qb.match(var("x").isa(label(ENTITY.getLabel()))).aggregate(count()).execute()).append(" entities\n"); builder.append("\t ").append(qb.match(var("x").isa(label(RELATIONSHIP.getLabel()))).aggregate(count()).execute()).append(" relations\n"); builder.append("\t ").append(qb.match(var("x").isa(label(ATTRIBUTE.getLabel()))).aggregate(count()).execute()).append(" resources\n"); builder.append("\t ").append(qb.match(var("x").isa(label(RULE.getLabel()))).aggregate(count()).execute()).append(" rules\n\n"); System.out.println(builder); tx.close(); } }
if(Schema.MetaSchema.isMetaLabel(superRelationType.label()) || superRelationType.isAbstract()){ //If super type is a meta type no validation needed return Collections.emptySet();
@CheckReturnValue public static boolean isMetaLabel(Label label) { return valueOf(label) != null; }
boolean allRolesMeta = explicitRoles.stream().allMatch(role -> Schema.MetaSchema.isMetaLabel(role.label())); boolean roleRecomputationViable = allRolesMeta && (!sub.isEmpty() || !Sets.intersection(varTypeMap.keySet(), getRolePlayers()).isEmpty()); if (explicitRoles.size() == getRelationPlayers().size() && !roleRecomputationViable) return this; Label roleLabel = rolePattern.getTypeLabel().orElse(null); if (roleLabel == null || !Schema.MetaSchema.isMetaLabel(roleLabel)) { inferredRelationPlayers.add(RelationPlayer.of(rolePattern, varName.admin())); allocatedRelationPlayers.add(rp);
/** * NB: assumes MATCH semantics - all types and their subs are considered * @param parentRole parent {@link Role} * @param parentType parent {@link Type} * @param entryRoles entry set of possible {@link Role}s * @return set of playable {@link Role}s defined by type-role parent combination, parent role assumed as possible */ public static Set<Role> compatibleRoles(Role parentRole, Type parentType, Set<Role> entryRoles) { Set<Role> compatibleRoles = parentRole != null? Sets.newHashSet(parentRole) : Sets.newHashSet(); if (parentRole != null && !Schema.MetaSchema.isMetaLabel(parentRole.label()) ){ compatibleRoles.addAll( Sets.intersection( new RoleConverter().toCompatibleRoles(parentRole).collect(toSet()), entryRoles )); } else { compatibleRoles.addAll(entryRoles); } if (parentType != null && !Schema.MetaSchema.isMetaLabel(parentType.label())) { Set<Role> compatibleRolesFromTypes = new TypeConverter().toCompatibleRoles(parentType).collect(toSet()); //do set intersection meta role compatibleRoles = compatibleRoles.stream() .filter(role -> Schema.MetaSchema.isMetaLabel(role.label()) || compatibleRolesFromTypes.contains(role)) .collect(toSet()); //parent role also possible if (parentRole != null) compatibleRoles.add(parentRole); } return compatibleRoles; }
/** * This is a temporary patch to prevent accidentally disconnecting implicit {@link RelationshipType}s from their * {@link RelationshipEdge}s. This Disconnection happens because {@link RelationshipType#instances()} depends on the * presence of a direct {@link Schema.EdgeLabel#PLAYS} edge between the {@link Type} and the implicit {@link RelationshipType}. * * When changing the super you may accidentally cause this disconnection. So we prevent it here. * */ //TODO: Remove this when traversing to the instances of an implicit Relationship Type is no longer done via plays edges @Override boolean changingSuperAllowed(T oldSuperType, T newSuperType){ boolean changingSuperAllowed = super.changingSuperAllowed(oldSuperType, newSuperType); if(changingSuperAllowed && oldSuperType != null && !Schema.MetaSchema.isMetaLabel(oldSuperType.label())) { //noinspection unchecked Set<Role> superPlays = oldSuperType.playing().collect(Collectors.toSet()); //Get everything that this can play bot including the supers Set<Role> plays = new HashSet<>(directPlays().keySet()); subs().flatMap(sub -> TypeImpl.from(sub).directPlays().keySet().stream()).forEach(plays::add); superPlays.removeAll(plays); //It is possible to be disconnecting from a role which is no longer in use but checking this will take too long //So we assume the role is in sure and throw if that is the case if(!superPlays.isEmpty() && instancesDirect().findAny().isPresent()){ throw GraknTxOperationException.changingSuperWillDisconnectRole(oldSuperType, newSuperType, superPlays.iterator().next()); } return true; } return changingSuperAllowed; }
/** * @return a map of relationships and corresponding roles that could be played by this atom */ private Multimap<RelationshipType, Role> inferPossibleRelationConfigurations(ConceptMap sub){ Set<Role> roles = getExplicitRoles().filter(r -> !Schema.MetaSchema.isMetaLabel(r.label())).collect(toSet()); Map<Var, Type> varTypeMap = getParentQuery().getVarTypeMap(sub); Set<Type> types = getRolePlayers().stream().filter(varTypeMap::containsKey).map(varTypeMap::get).collect(toSet()); if (roles.isEmpty() && types.isEmpty()){ RelationshipType metaRelationType = tx().admin().getMetaRelationType(); Multimap<RelationshipType, Role> compatibleTypes = HashMultimap.create(); metaRelationType.subs() .filter(rt -> !rt.equals(metaRelationType)) .forEach(rt -> compatibleTypes.putAll(rt, rt.roles().collect(toSet()))); return compatibleTypes; } //intersect relation types from roles and types Multimap<RelationshipType, Role> compatibleTypes; Multimap<RelationshipType, Role> compatibleTypesFromRoles = compatibleRelationTypesWithRoles(roles, new RoleConverter()); Multimap<RelationshipType, Role> compatibleTypesFromTypes = compatibleRelationTypesWithRoles(types, new TypeConverter()); if (roles.isEmpty()){ compatibleTypes = compatibleTypesFromTypes; } //no types from roles -> roles correspond to mutually exclusive relations else if(compatibleTypesFromRoles.isEmpty() || types.isEmpty()){ compatibleTypes = compatibleTypesFromRoles; } else { compatibleTypes = multimapIntersection(compatibleTypesFromTypes, compatibleTypesFromRoles); } return compatibleTypes; }
@SuppressWarnings("unchecked") private boolean initialiseMetaConcepts() { boolean schemaInitialised = false; if (isMetaSchemaNotInitialised()) { VertexElement type = addTypeVertex(Schema.MetaSchema.THING.getId(), Schema.MetaSchema.THING.getLabel(), Schema.BaseType.TYPE); VertexElement entityType = addTypeVertex(Schema.MetaSchema.ENTITY.getId(), Schema.MetaSchema.ENTITY.getLabel(), Schema.BaseType.ENTITY_TYPE); VertexElement relationType = addTypeVertex(Schema.MetaSchema.RELATIONSHIP.getId(), Schema.MetaSchema.RELATIONSHIP.getLabel(), Schema.BaseType.RELATIONSHIP_TYPE); VertexElement resourceType = addTypeVertex(Schema.MetaSchema.ATTRIBUTE.getId(), Schema.MetaSchema.ATTRIBUTE.getLabel(), Schema.BaseType.ATTRIBUTE_TYPE); addTypeVertex(Schema.MetaSchema.ROLE.getId(), Schema.MetaSchema.ROLE.getLabel(), Schema.BaseType.ROLE); addTypeVertex(Schema.MetaSchema.RULE.getId(), Schema.MetaSchema.RULE.getLabel(), Schema.BaseType.RULE); relationType.property(Schema.VertexProperty.IS_ABSTRACT, true); resourceType.property(Schema.VertexProperty.IS_ABSTRACT, true); entityType.property(Schema.VertexProperty.IS_ABSTRACT, true); relationType.addEdge(type, Schema.EdgeLabel.SUB); resourceType.addEdge(type, Schema.EdgeLabel.SUB); entityType.addEdge(type, Schema.EdgeLabel.SUB); schemaInitialised = true; } //Copy entire schema to the graph cache. This may be a bad idea as it will slow down graph initialisation copyToCache(getMetaConcept()); //Role and rule have to be copied separately due to not being connected to meta schema copyToCache(getMetaRole()); copyToCache(getMetaRule()); return schemaInitialised; }
@Override public Set<String> validateOntologically() { Set<String> errors = new HashSet<>(); SchemaConcept type = getSchemaConcept(); if (type != null && !type.isRelationshipType()){ errors.add(ErrorMessage.VALIDATION_RULE_INVALID_RELATION_TYPE.getMessage(type.label())); return errors; } //check role-type compatibility Map<Var, Type> varTypeMap = getParentQuery().getVarTypeMap(); for (Map.Entry<Role, Collection<Var>> e : getRoleVarMap().asMap().entrySet() ){ Role role = e.getKey(); if (!Schema.MetaSchema.isMetaLabel(role.label())) { //check whether this role can be played in this relation if (type != null && type.asRelationshipType().roles().noneMatch(r -> r.equals(role))) { errors.add(ErrorMessage.VALIDATION_RULE_ROLE_CANNOT_BE_PLAYED.getMessage(role.label(), type.label())); } //check whether the role player's type allows playing this role for (Var player : e.getValue()) { Type playerType = varTypeMap.get(player); if (playerType != null && playerType.playing().noneMatch(plays -> plays.equals(role))) { errors.add(ErrorMessage.VALIDATION_RULE_TYPE_CANNOT_PLAY_ROLE.getMessage(playerType.label(), role.label(), type == null? "" : type.label())); } } } } return errors; }
/** * @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); }
/** * Utility method used to create an instance of this type * * @param instanceBaseType The base type of the instances of this type * @param producer The factory method to produce the instance * @param checkNeeded indicates if a check is necessary before adding the instance * @return A new instance */ V addInstance(Schema.BaseType instanceBaseType, BiFunction<VertexElement, T, V> producer, boolean isInferred, boolean checkNeeded){ if(checkNeeded) preCheckForInstanceCreation(); if(isAbstract()) throw GraknTxOperationException.addingInstancesToAbstractType(this); VertexElement instanceVertex = vertex().tx().addVertexElement(instanceBaseType); if(!Schema.MetaSchema.isMetaLabel(label())) { vertex().tx().txCache().addedInstance(id()); if(isInferred) instanceVertex.property(Schema.VertexProperty.IS_INFERRED, true); } V instance = producer.apply(instanceVertex, getThis()); assert instance != null : "producer should never return null"; return instance; }
private Set<String> validateRelationPlayers(Rule rule){ Set<String> errors = new HashSet<>(); getRelationPlayers().forEach(rp -> { VarPatternAdmin role = rp.getRole().orElse(null); if (role == null){ errors.add(ErrorMessage.VALIDATION_RULE_ILLEGAL_HEAD_RELATION_WITH_AMBIGUOUS_ROLE.getMessage(rule.then(), rule.label())); } else { Label roleLabel = role.getTypeLabel().orElse(null); if (roleLabel == null){ errors.add(ErrorMessage.VALIDATION_RULE_ILLEGAL_HEAD_RELATION_WITH_AMBIGUOUS_ROLE.getMessage(rule.then(), rule.label())); } else { if (Schema.MetaSchema.isMetaLabel(roleLabel)) { errors.add(ErrorMessage.VALIDATION_RULE_ILLEGAL_HEAD_RELATION_WITH_AMBIGUOUS_ROLE.getMessage(rule.then(), rule.label())); } Role roleType = tx().getRole(roleLabel.getValue()); if (roleType != null && roleType.isImplicit()) { errors.add(ErrorMessage.VALIDATION_RULE_ILLEGAL_HEAD_RELATION_WITH_IMPLICIT_ROLE.getMessage(rule.then(), rule.label())); } } } }); return errors; }
/** * @param typedVar variable of interest * @param parentType to be checked * @return true if typing the typeVar with type is compatible with role configuration of this query */ @Override public boolean isTypeRoleCompatible(Var typedVar, Type parentType){ if (parentType == null || Schema.MetaSchema.isMetaLabel(parentType.label())) return true; Set<Type> parentTypes = parentType.subs().collect(Collectors.toSet()); return getAtoms(RelationshipAtom.class) .filter(ra -> ra.getVarNames().contains(typedVar)) .noneMatch(ra -> ra.getRoleVarMap().entries().stream() //get roles this type needs to play .filter(e -> e.getValue().equals(typedVar)) .filter(e -> !Schema.MetaSchema.isMetaLabel(e.getKey().label())) //check if it can play it .anyMatch(e -> e.getKey().players().noneMatch(parentTypes::contains))); }
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); } } /**
/** * * @param isAbstract Specifies if the concept is abstract (true) or not (false). * If the concept type is abstract it is not allowed to have any instances. * @return The Type itself. */ public T isAbstract(Boolean isAbstract) { if(!Schema.MetaSchema.isMetaLabel(label()) && isAbstract && instancesDirect().findAny().isPresent()){ throw GraknTxOperationException.addingInstancesToAbstractType(this); } property(Schema.VertexProperty.IS_ABSTRACT, isAbstract); cachedIsAbstract.set(isAbstract); if(isAbstract){ vertex().tx().txCache().removeFromValidation(this); } else { vertex().tx().txCache().trackForValidation(this); } return getThis(); }
/** * Gets and increments the current available type id. * * @return the current available Grakn id which can be used for types */ private LabelId getNextId() { TypeImpl<?, ?> metaConcept = (TypeImpl<?, ?>) getMetaConcept(); Integer currentValue = metaConcept.vertex().property(Schema.VertexProperty.CURRENT_LABEL_ID); if (currentValue == null) { currentValue = Schema.MetaSchema.values().length + 1; } else { currentValue = currentValue + 1; } //Vertex is used directly here to bypass meta type mutation check metaConcept.property(Schema.VertexProperty.CURRENT_LABEL_ID, currentValue); return LabelId.of(currentValue); }
/** * @param parent type * @param child type * @return true if child is a subtype of parent */ public static boolean typesCompatible(SchemaConcept parent, SchemaConcept child) { if (parent == null) return true; if (child == null) return false; if (Schema.MetaSchema.isMetaLabel(parent.label())) return true; SchemaConcept superType = child; while(superType != null && !Schema.MetaSchema.isMetaLabel(superType.label())){ if (superType.equals(parent)) return true; superType = superType.sup(); } return false; }
private Thing putInstance() { Type type = use(TYPE); if (type.isEntityType()) { return type.asEntityType().create(); } else if (type.isRelationshipType()) { return type.asRelationshipType().create(); } else if (type.isAttributeType()) { return type.asAttributeType().create(use(VALUE)); } else if (type.label().equals(Schema.MetaSchema.THING.getLabel())) { throw GraqlQueryException.createInstanceOfMetaConcept(var, type); } else { throw CommonUtil.unreachableStatement("Can't recognize type " + type); } }
@SuppressWarnings("unchecked") @Override public <V> AttributeType<V> putAttributeType(Label label, AttributeType.DataType<V> dataType) { @SuppressWarnings("unchecked") AttributeType<V> attributeType = putSchemaConcept(label, Schema.BaseType.ATTRIBUTE_TYPE, false, v -> factory().buildAttributeType(v, getMetaAttributeType(), dataType)); //These checks is needed here because caching will return a type by label without checking the datatype if (Schema.MetaSchema.isMetaLabel(label)) { throw GraknTxOperationException.metaTypeImmutable(label); } else if (!dataType.equals(attributeType.dataType())) { throw GraknTxOperationException.immutableProperty(attributeType.dataType(), dataType, Schema.VertexProperty.DATA_TYPE); } return attributeType; }
@Override public boolean isTinkerPopGraphClosed() { return !rootGraph.traversal().V().has(Schema.VertexProperty.SCHEMA_LABEL.name(), Schema.MetaSchema.ENTITY.getLabel().getValue()).hasNext(); }