public String toString() { String retVal = type.toString() + ": "; switch (type) { case STRUCT_FIELD: retVal += getFieldRef(); break; case ARRAY_INDEX: retVal += getLookupIndex(); break; case MAP_KEY: retVal += getLookupKey(); break; case MAP_ALL_KEYS: case MAP_ALL_VALUES: break; case VARIABLE: retVal += getVariableName(); break; } return retVal; }
/** * Creates a new field path entry that references a map or weighted set. * * @param lookupKey The value of the key in the map or weighted set to recurse into. * @param resultingDataType The datatype of values in the map or weighted set. * @return The new field path entry */ public static FieldPathEntry newMapLookupEntry(FieldValue lookupKey, DataType resultingDataType) { return new FieldPathEntry(lookupKey, resultingDataType); }
public static FieldPath buildFieldPath(String remainFieldName, DataType keyType, DataType valueType) { if (remainFieldName.length() > 0 && remainFieldName.charAt(0) == '{') { FieldPathEntry.KeyParseResult result = FieldPathEntry.parseKey(remainFieldName); String keyValue = result.parsed; FieldPath path = valueType.buildFieldPath(skipDotInString(remainFieldName, result.consumedChars - 1)); List<FieldPathEntry> tmpPath = new ArrayList<FieldPathEntry>(path.getList()); if (remainFieldName.charAt(1) == '$') { tmpPath.add(0, FieldPathEntry.newVariableLookupEntry(keyValue.substring(1), valueType)); } else { FieldValue fv = keyType.createFieldValue(); fv.assign(keyValue); tmpPath.add(0, FieldPathEntry.newMapLookupEntry(fv, valueType)); } return new FieldPath(tmpPath); } else if (remainFieldName.startsWith("key")) { FieldPath path = keyType.buildFieldPath(skipDotInString(remainFieldName, 2)); List<FieldPathEntry> tmpPath = new ArrayList<FieldPathEntry>(path.getList()); tmpPath.add(0, FieldPathEntry.newAllKeysLookupEntry(keyType)); return new FieldPath(tmpPath); } else if (remainFieldName.startsWith("value")) { FieldPath path = valueType.buildFieldPath(skipDotInString(remainFieldName, 4)); List<FieldPathEntry> tmpPath = new ArrayList<FieldPathEntry>(path.getList()); tmpPath.add(0, FieldPathEntry.newAllValuesLookupEntry(valueType)); return new FieldPath(tmpPath); } return keyType.buildFieldPath(remainFieldName); }
if (idx < updatePath.size()) { FieldPathEntry pathEntry = updatePath.get(idx); FieldPathEntry.Type type = pathEntry.getType(); if (type == FieldPathEntry.Type.STRUCT_FIELD) { if (!(value instanceof StructuredFieldValue)) { Map.Entry<Field, FieldValue> structEntry = it.next(); List<FieldPathEntry> nextPath = new ArrayList<>(path); nextPath.add(FieldPathEntry.newStructFieldEntry(structEntry.getKey())); createUpdatesAt(nextPath, structEntry.getValue(), idx + 1, out); FieldValue wsetEntry = it.next(); List<FieldPathEntry> nextPath = new ArrayList<>(path); nextPath.add(FieldPathEntry.newMapLookupEntry(wsetEntry, DataType.INT)); createUpdatesAt(nextPath, new IntegerFieldValue(wset.get(wsetEntry)), idx + 1, out); List<FieldPathEntry> nextPath = new ArrayList<>(path); FieldValue nextVal = entry.getValue(); nextPath.add(FieldPathEntry.newMapLookupEntry(entry.getKey(), nextVal.getDataType())); createUpdatesAt(nextPath, nextVal, idx + 1, out);
@Override FieldPathIteratorHandler.ModificationStatus iterateNested(FieldPath fieldPath, int pos, FieldPathIteratorHandler handler) { if (pos < fieldPath.size()) { switch (fieldPath.get(pos).getType()) { case ARRAY_INDEX: final int elemIndex = fieldPath.get(pos).getLookupIndex(); return iterateSubset(elemIndex, elemIndex, fieldPath, null, pos + 1, handler); case VARIABLE: { FieldPathIteratorHandler.IndexValue val = handler.getVariables().get(fieldPath.get(pos).getVariableName()); if (val != null) { int idx = val.getIndex(); return iterateSubset(0, values.size() - 1, fieldPath, fieldPath.get(pos).getVariableName(), pos + 1, handler);
FieldPathIteratorHandler handler) { if (pos < fieldPath.size()) { if (fieldPath.get(pos).getType() == FieldPathEntry.Type.STRUCT_FIELD) { FieldValue fieldVal = getFieldValue(fieldPath.get(pos).getFieldRef()); if (fieldVal != null) { FieldPathIteratorHandler.ModificationStatus status = fieldVal.iterateNested(fieldPath, pos + 1, handler); if (status == FieldPathIteratorHandler.ModificationStatus.REMOVED) { removeFieldValue(fieldPath.get(pos).getFieldRef()); return FieldPathIteratorHandler.ModificationStatus.MODIFIED; } else { setFieldValue(fieldPath.get(pos).getFieldRef(), fieldVal); FieldValue newVal = fieldPath.get(pos).getFieldRef().getDataType().createFieldValue(); FieldPathIteratorHandler.ModificationStatus status = newVal.iterateNested(fieldPath, pos + 1, handler); if (status == FieldPathIteratorHandler.ModificationStatus.MODIFIED) { setFieldValue(fieldPath.get(pos).getFieldRef(), newVal); return status;
switch (fieldPath.get(pos).getType()) { case MAP_KEY: FieldValue val = values.get(fieldPath.get(pos).getLookupKey()); if (val != null) { wasModified = checkAndRemove(fieldPath.get(pos).getLookupKey(), val.iterateNested(fieldPath, pos + 1, handler), wasModified, keysToRemove); } else if (handler.createMissingPath()) { val = getDataType().getValueType().createFieldValue(); FieldPathIteratorHandler.ModificationStatus status = val.iterateNested(fieldPath, pos + 1, handler); if (status == FieldPathIteratorHandler.ModificationStatus.MODIFIED) { put((K)fieldPath.get(pos).getLookupKey(), (V)val); return status; case VARIABLE: FieldPathIteratorHandler.IndexValue idx = handler.getVariables().get(fieldPath.get(pos).getVariableName()); if (idx != null) { FieldValue val = values.get(idx.getKey()); handler.getVariables().put(fieldPath.get(pos).getVariableName(), new FieldPathIteratorHandler.IndexValue(entry.getKey())); wasModified = checkAndRemove(entry.getKey(), entry.getValue().iterateNested(fieldPath, pos + 1, handler), wasModified, keysToRemove); handler.getVariables().remove(fieldPath.get(pos).getVariableName());
@Override public FieldPath buildFieldPath(String remainFieldName) { if (remainFieldName.length() == 0) { return new FieldPath(); } String currFieldName = remainFieldName; String subFieldName = ""; for (int i = 0; i < remainFieldName.length(); i++) { if (remainFieldName.charAt(i) == '.') { currFieldName = remainFieldName.substring(0, i); subFieldName = remainFieldName.substring(i + 1); break; } else if (remainFieldName.charAt(i) == '{' || remainFieldName.charAt(i) == '[') { currFieldName = remainFieldName.substring(0, i); subFieldName = remainFieldName.substring(i); break; } } Field f = getField(currFieldName); if (f != null) { FieldPath fieldPath = f.getDataType().buildFieldPath(subFieldName); List<FieldPathEntry> tmpPath = new ArrayList<FieldPathEntry>(fieldPath.getList()); tmpPath.add(0, FieldPathEntry.newStructFieldEntry(f)); return new FieldPath(tmpPath); } else { throw new IllegalArgumentException("Field '" + currFieldName + "' not found in type " + this); } }
/** * note that the returned Field may not be in this Document * directly, but may refer to a field in a struct contained in it, * in which case the returned Field is only useful for obtaining * the field type; it can't be used for get() and set(). **/ @Override public Field getField(String fieldName) { if (fieldMap != null && fieldMap.containsKey(fieldName)) { fieldName = fieldMap.get(fieldName); } FieldPath path = getFieldPath(fieldName); Field ret = path.get(path.size() - 1).getFieldRef(); checkAccess(ret); return ret; }
public static boolean isComplete(FieldPathUpdate update) { if (!(update instanceof AssignFieldPathUpdate)) { return false; } // Only consider field path updates that touch a top-level field as 'complete', // as these may be converted to regular field value updates. return ((update.getFieldPath().size() == 1) && update.getFieldPath().get(0).getType() == FieldPathEntry.Type.STRUCT_FIELD); }
/** * @return Returns the datatype we can expect this field path to return. */ public DataType getResultingDataType() { if (isEmpty()) { return null; } return get(size() - 1).getResultingDataType(); }
/** * Compares this field path with the given field path, returns true if the field path starts with the other. * * @param other The field path to compare with. * @return Returns true if this field path starts with the other field path, otherwise false */ public boolean startsWith(FieldPath other) { if (other.size() > size()) { return false; } for (int i = 0; i < other.size(); i++) { if (!other.get(i).equals(get(i))) { return false; } } return true; }
DataType prevType = null; for (FieldPathEntry entry : this) { FieldPathEntry.Type type = entry.getType(); switch (type) { case STRUCT_FIELD: out.append("."); Field field = entry.getFieldRef(); out.append(field.getName()); prevType = field.getDataType(); break; case ARRAY_INDEX: out.append("[").append(entry.getLookupIndex()).append("]"); break; case MAP_KEY: out.append("{").append(entry.getLookupKey()).append("}"); break; case MAP_ALL_KEYS: case VARIABLE: if (prevType instanceof ArrayDataType) { out.append("[$").append(entry.getVariableName()).append("]"); } else if (prevType instanceof WeightedSetDataType || prevType instanceof MapDataType) { out.append("{$").append(entry.getVariableName()).append("}"); } else { out.append("$").append(entry.getVariableName());
/** * Creates a new field path entry that digs through all the values of a map or weighted set. * * @param resultingDataType The datatype of the values in the map or weighted set. * @return The new field path entry. */ public static FieldPathEntry newAllValuesLookupEntry(DataType resultingDataType) { return new FieldPathEntry(false, true, resultingDataType); }
/** * Creates a new field path entry that references an array index. * * @param lookupIndex The index to look up * @param resultingDataType The datatype of the contents of the array * @return The new field path entry */ public static FieldPathEntry newArrayLookupEntry(int lookupIndex, DataType resultingDataType) { return new FieldPathEntry(lookupIndex, resultingDataType); }
/** * Creates a new field path entry that digs through all the keys of a map or weighted set. * * @param resultingDataType The datatype of the keys in the map or weighted set. * @return The new field path entry. */ public static FieldPathEntry newAllKeysLookupEntry(DataType resultingDataType) { return new FieldPathEntry(true, false, resultingDataType); }
/** * Creates a new field path entry that references a struct field. * For these kinds of field path entries, getFieldRef() is valid. * * @param fieldRef The field to look up in the struct. * @return The new field path entry */ public static FieldPathEntry newStructFieldEntry(Field fieldRef) { return new FieldPathEntry(fieldRef); }
/** * Creates a new field path entry that digs through all the keys in a map or weighted set, or all the indexes of an array, * an sets the given variable name as it does so (or, if the variable is set, uses the set variable to look up the * collection. * * @param variableName The name of the variable to lookup in the collection * @param resultingDataType The value type of the collection we're digging through * @return The new field path entry. */ public static FieldPathEntry newVariableLookupEntry(String variableName, DataType resultingDataType) { return new FieldPathEntry(variableName, resultingDataType); }