private void checkImmutableFieldsCorrespond(FieldType userFieldType, FieldType latestFieldType) throws FieldTypeUpdateException { if (!userFieldType.getValueType().equals(latestFieldType.getValueType())) { throw new FieldTypeUpdateException("Changing the valueType of a fieldType '" + latestFieldType.getId() + "' (current name: " + latestFieldType.getName() + ") is not allowed; old '" + latestFieldType.getValueType() + "' new '" + userFieldType.getValueType() + "'"); } if (!userFieldType.getScope().equals(latestFieldType.getScope())) { throw new FieldTypeUpdateException("Changing the scope of a fieldType '" + latestFieldType.getId() + "' (current name: " + latestFieldType.getName() + ") is not allowed; old '" + latestFieldType.getScope() + "' new '" + userFieldType.getScope() + "'"); } }
@Override public FieldType createOrUpdateFieldType(FieldType fieldType) throws RepositoryException, InterruptedException { if (fieldType.getId() == null) { fieldType.setId(new SchemaIdImpl(UUID.randomUUID())); } fieldTypesByName.put(fieldType.getName(), fieldType); fieldTypes.put(fieldType.getId(), fieldType); return fieldType; }
@Override public List<FieldType> getFieldTypes() throws InterruptedException { List<FieldType> fieldTypes = new ArrayList<FieldType>(); for (FieldType fieldType : getNameCache().values()) { fieldTypes.add(fieldType.clone()); } return fieldTypes; }
private void copyUnspecifiedFields(FieldType userFieldType, FieldType latestFieldType) throws FieldTypeUpdateException { if (userFieldType.getScope() == null) { userFieldType.setScope(latestFieldType.getScope()); } if (userFieldType.getValueType() == null) { userFieldType.setValueType(latestFieldType.getValueType()); } }
/** * Version of #decodeRecord() which returns an {@link IdRecord} instance rather than a {@link Record} instance. */ public IdRecord decodeRecordWithIds(RecordId recordId, Long requestedVersion, Result result, FieldTypes fieldTypes) throws InterruptedException, RepositoryException { final ReadContext readContext = new ReadContext(); final Record record = decodeRecord(recordId, requestedVersion, readContext, result, fieldTypes); Map<SchemaId, QName> idToQNameMapping = new HashMap<SchemaId, QName>(); for (FieldType fieldType : readContext.getFieldTypes().values()) { idToQNameMapping.put(fieldType.getId(), fieldType.getName()); } Map<Scope, SchemaId> recordTypeIds = new EnumMap<Scope, SchemaId>(Scope.class); for (Map.Entry<Scope, SchemaId> entry : readContext.getRecordTypes().entrySet()) { recordTypeIds.put(entry.getKey(), entry.getValue()); } return new IdRecordImpl(record, idToQNameMapping, recordTypeIds); }
/** * Returns true if the given FieldType is a version tag. */ public static boolean isVersionTag(FieldType fieldType) { String namespace = fieldType.getName().getNamespace(); return (fieldType.getScope() == Scope.NON_VERSIONED && fieldType.getValueType().getBaseName().equals("LONG") && namespace != null && namespace.equals(NAMESPACE) /* namespace is typically the longest string, therefore compare it last */ && !fieldType.getName().getName().equals("last")); /* filter out 'last' vtag, it should not be custom assigned */ }
@Override public FieldEntryBuilder use(FieldType fieldType) { this.id = fieldType.getId(); return this; }
@Override public FieldType createFieldType(FieldType fieldType) throws RepositoryException { ArgumentValidator.notNull(fieldType, "fieldType"); ArgumentValidator.notNull(fieldType.getName(), "fieldType.name"); ArgumentValidator.notNull(fieldType.getValueType(), "fieldType.valueType"); ArgumentValidator.notNull(fieldType.getScope(), "fieldType.scope"); SchemaId id = getValidId(); byte[] rowId = id.getBytes(); byte[] nameBytes = encodeName(fieldType.getName()); put.add(TypeCf.DATA.bytes, TypeColumn.FIELDTYPE_VALUETYPE.bytes, encodeValueType(fieldType.getValueType())); put.add(TypeCf.DATA.bytes, TypeColumn.FIELDTYPE_SCOPE.bytes, Bytes .toBytes(fieldType.getScope().name())); put.add(TypeCf.DATA.bytes, TypeColumn.FIELDTYPE_NAME.bytes, nameBytes); newFieldType = fieldType.clone(); newFieldType.setId(id); if (schemaCache.fieldTypeExists(fieldType.getName())) { throw new FieldTypeExistsException(fieldType); checkConcurrency(fieldType.getName(), nameBytes, now); throw new TypeException("Exception occurred while creating fieldType '" + fieldType.getName() + "' version: '" + version + "' on HBase", e); } catch (InterruptedException e) { throw new TypeException("Exception occurred while creating fieldType '" + fieldType.getName() + "' version: '" + version + "' on HBase", e);
private static void printFieldType(Pair<FieldTypeEntry, FieldType> pair, PrintStream out, int indent) { FieldTypeEntry fieldTypeEntry = pair.getV1(); FieldType fieldType = pair.getV2(); println(out, indent, "Name = " + fieldType.getName()); println(out, indent, "ID = " + fieldType.getId()); println(out, indent, "Mandatory = " + fieldTypeEntry.isMandatory()); try { println(out, indent, "ValueType = " + fieldType.getValueType().getName()); } catch (Throwable t) { // value type failed to load } }
public Set<QName> getFieldDependencies() { return fieldType != null ? Collections.singleton(fieldType.getName()) : Collections.<QName>emptySet(); }
@Override public boolean accept(FieldType fieldtype) { return fieldtype.getValueType().getDeepestValueType().getBaseName().equals("LINK"); } };
/** * Extracts the given field value from the record and transforms it into a flat (java) list, * regardless of the valueType of the field. * @param record * @param fieldType * @return */ public static List flatList(Record record, FieldType fieldType) { if (record != null && record.hasField(fieldType.getName())) { return flatList(record.getField(fieldType.getName()), fieldType.getValueType()); } else { return Collections.emptyList(); } }
if (fieldType.getId() == null || fieldType.getName() == null) { FieldType newFieldType = fieldType.clone(); byte[] rowId = fieldType.getId().getBytes(); byte[] nameBytes = null; Long now = null; throw new FieldTypeNotFoundException(fieldType.getId()); nameBytes = encodeName(fieldType.getName()); checkConcurrency(fieldType.getName(), nameBytes, now); FieldType latestFieldType = getFieldTypeByIdWithoutCache(fieldType.getId()); copyUnspecifiedFields(newFieldType, latestFieldType); checkImmutableFieldsCorrespond(newFieldType, latestFieldType); if (!newFieldType.getName().equals(latestFieldType.getName())) { try { getFieldTypeByName(newFieldType.getName()); throw new FieldTypeUpdateException("Changing the name '" + newFieldType.getName() + "' of a fieldType '" + newFieldType.getId() + "' to a name that already exists is not allowed; old '" + latestFieldType.getName() + "' new '" + newFieldType.getName() + "'"); } catch (FieldTypeNotFoundException allowed) { updateFieldTypeCache(newFieldType.clone()); } catch (IOException e) {
if (fieldType.getName() == null) { throw new ImportException("Missing name property on field type."); FieldType ftToCreate = fieldType.clone(); ftToCreate.setName(new QName(fieldType.getName().getNamespace(), fieldType.getName().getName() + i)); ImportResult<FieldType> result = FieldTypeImport.importFieldType(ftToCreate, ImportMode.CREATE_OR_UPDATE, IdentificationMode.NAME, ftToCreate.getName(), repository.getTypeManager()); FieldType newFieldType = result.getEntity(); importListener.created(EntityType.FIELD_TYPE, newFieldType.getName().toString(), newFieldType.getId() .toString()); break; case UP_TO_DATE: importListener.existsAndEqual(EntityType.FIELD_TYPE, newFieldType.getName().toString(), null); break; case CONFLICT: importListener.conflict(EntityType.FIELD_TYPE, ftToCreate.getName().toString(), result.getConflictingProperty(), result.getConflictingOldValue(), result.getConflictingNewValue());
private void addField(FieldType type, Object oldValue, Object newValue, RecordEvent.IndexRecordFilterData idxSel) throws RepositoryException, InterruptedException { if (oldValue == null && newValue == null) { return; } if (oldValue != null) { oldValue = type.getValueType().toBytes(oldValue, new IdentityRecordStack()); } if (newValue != null) { newValue = type.getValueType().toBytes(newValue, new IdentityRecordStack()); } idxSel.addChangedField(type.getId(), (byte[])oldValue, (byte[])newValue); }
/** * Extracts field types declared inline in a record type. An inline definition is recognized by the * presence of a valueType attribute on the field. Found field types are added to the passed map after * checking for conflicting definitions. */ private void extractFieldTypesFromRecordType(JsonNode node, Map<QName, FieldType> fieldTypes) throws RepositoryException, InterruptedException, JsonFormatException, ImportException { if (node.has("fields")) { ArrayNode fields = getArray(node, "fields"); for (int i = 0; i < fields.size(); i++) { JsonNode field = fields.get(i); if (field.has("valueType")) { FieldType fieldType = parseFieldType(field); if (fieldTypes.containsKey(fieldType.getName())) { FieldType prevFieldType = fieldTypes.get(fieldType.getName()); if (!fieldType.equals(prevFieldType)) { throw new ImportException("Found conflicting definitions of a field type in two record" + " types, field types: " + fieldType + " and " + prevFieldType); } } else { fieldTypes.put(fieldType.getName(), fieldType); } } } } }
/** * Update the cache to contain the new fieldType * * @param fieldType */ public void update(FieldType fieldType) { // Clone the FieldType to avoid changes to it while it is in the cache FieldType ftToCache = fieldType.clone(); SchemaId id = ftToCache.getId(); String bucketId = AbstractSchemaCache.encodeHex(id.getBytes()); // First increment the number of buckets that are being updated incCount(); // Get a lock on the bucket to be updated synchronized (getBucketMonitor(bucketId)) { Map<SchemaId, FieldType> bucket = buckets.get(bucketId); // If the bucket does not exist yet, create it if (bucket == null) { bucket = new ConcurrentHashMap<SchemaId, FieldType>(8, .75f, 1); buckets.put(bucketId, bucket); } bucket.put(id, ftToCache); // Mark that this fieldType is updated locally // and that the next refresh can be ignored // since this refresh can contain an old fieldType addToLocalUpdateBucket(id, bucketId); } // Decrement the number of buckets that are being updated again. decCount(); }
private Map<QName, Object> filterMutableFields(Map<QName, Object> fields, FieldTypes fieldTypes) throws RecordException, TypeException, InterruptedException { Map<QName, Object> mutableFields = new HashMap<QName, Object>(); for (Entry<QName, Object> field : fields.entrySet()) { FieldType fieldType = fieldTypes.getFieldType(field.getKey()); if (Scope.VERSIONED_MUTABLE.equals(fieldType.getScope())) { mutableFields.put(field.getKey(), field.getValue()); } } return mutableFields; }
private FieldType buildFieldType() throws RepositoryException, InterruptedException { FieldType fieldType = typeManager.newFieldType(valueType, name, scope); fieldType.setId(id); return fieldType; }