use of com.linkedin.data.DataMap in project rest.li by linkedin.
the class PdlSchemaParser method addPropertiesAtPath.
/**
* Adds additional properties to an existing properties map at the location identified by
* the given path.
*
* This allows for properties defined with paths such as:
*
* {@literal @}a.b = "x"
* {@literal @}a.c = "y"
*
* to be merged together into a property map like:
*
* { "a": { "b": "x", "c": "y" }}
*
* Examples:
*
* <pre>
* existing properties | path | value | result
* ---------------------------|-------|---------------|----------------------------------------
* {} | a.b.c | true | { "a": { "b": { "c": true } } }
* { "a": {} } | a.b | true | { "a": { "b": true } }
* { "a": {} } | a.b | { "z": "x" } | { "a": { "b": { "z": "x" } } }
* { "a": { "c": "x"}} } | a.b | true | { "a": { "b": true, "c": "x"} } }
* { "a": { "b": "x"}} } | a.b | "y" | ParseError "Conflicting property: a.b"
* </pre>
*
* The existing properties are traversed using the given path, adding DataMaps as needed to
* complete the traversal. If any of data elements in the existing properties along the path are
* not DataMaps, a ParseError is thrown to report the conflict.
*
* @param context provides the parsing context for error reporting purposes.
* @param existingProperties provides the properties to add to.
* @param path provides the path of the property to insert.
* @param value provides the value of the property to insert.
* @throws ParseException if the path of the properties to add conflicts with data already
* in the properties map or if a property is already exists at the path.
*/
private void addPropertiesAtPath(ParserRuleContext context, Map<String, Object> existingProperties, Iterable<String> path, Object value) throws ParseException {
Map<String, Object> current = existingProperties;
Iterator<String> iter = path.iterator();
while (iter.hasNext()) {
String pathPart = iter.next();
if (iter.hasNext()) {
if (existingProperties.containsKey(pathPart)) {
Object val = existingProperties.get(pathPart);
if (!(val instanceof DataMap)) {
throw new ParseException(new ParseError(new ParseErrorLocation(context), "Conflicting property: " + path.toString()));
}
current = (DataMap) val;
} else {
DataMap next = new DataMap();
current.put(pathPart, next);
current = next;
}
} else {
if (current.containsKey(pathPart)) {
throw new ParseException(new ParseError(new ParseErrorLocation(context), "Property already defined: " + path.toString()));
} else {
current.put(pathPart, value);
}
}
}
}
use of com.linkedin.data.DataMap in project rest.li by linkedin.
the class PdlSchemaParser method parseEnum.
private EnumDataSchema parseEnum(NamedTypeDeclarationContext context, EnumDeclarationContext enumDecl) throws ParseException {
Name name = toName(enumDecl.name);
EnumDataSchema schema = new EnumDataSchema(name);
bindNameToSchema(name, schema);
List<EnumSymbolDeclarationContext> symbolDecls = enumDecl.enumDecl.symbolDecls;
List<String> symbols = new ArrayList<>(symbolDecls.size());
Map<String, Object> props = setProperties(context, schema);
Map<String, Object> symbolDocs = new HashMap<>();
DataMap deprecatedSymbols = new DataMap();
DataMap symbolProperties = new DataMap();
for (EnumSymbolDeclarationContext symbolDecl : symbolDecls) {
symbols.add(symbolDecl.symbol.value);
if (symbolDecl.doc != null) {
symbolDocs.put(symbolDecl.symbol.value, symbolDecl.doc.value);
}
for (PropDeclarationContext prop : symbolDecl.props) {
String symbol = symbolDecl.symbol.value;
Object value = parsePropValue(prop);
if (prop.name.equals("deprecated")) {
deprecatedSymbols.put(symbol, value);
} else {
List<String> path = new ArrayList<>(prop.path);
path.add(0, symbol);
addPropertiesAtPath(prop, symbolProperties, path, value);
}
}
}
schema.setSymbols(symbols, errorMessageBuilder());
if (symbolDocs.size() > 0) {
schema.setSymbolDocs(symbolDocs, errorMessageBuilder());
}
if (deprecatedSymbols.size() > 0) {
props.put("deprecatedSymbols", deprecatedSymbols);
}
if (symbolProperties.size() > 0) {
props.put("symbolProperties", symbolProperties);
}
schema.setProperties(props);
return schema;
}
use of com.linkedin.data.DataMap in project rest.li by linkedin.
the class AbstractDataElement method getChild.
@Override
public Object getChild(Object childName) {
Object value = getValue();
Class<?> valueClass = value.getClass();
if (valueClass == DataList.class && childName.getClass() == Integer.class) {
int index = ((Integer) childName);
DataList list = (DataList) value;
if (index >= 0 && index < list.size()) {
return list.get(index);
}
} else if (valueClass == DataMap.class && childName.getClass() == String.class) {
String name = ((String) childName);
DataMap map = (DataMap) value;
return map.get(name);
}
return null;
}
use of com.linkedin.data.DataMap in project rest.li by linkedin.
the class SchemaSampleDataGenerator method buildRecordData.
private static DataMap buildRecordData(ParentSchemas parentSchemas, NamedDataSchema schema, DataGenerationOptions spec) {
spec = preventRecursionIntoAlreadyTraversedSchemas(parentSchemas, spec, schema);
parentSchemas.incrementReferences(schema);
final DataMap data = new DataMap();
if (schema instanceof RecordDataSchema) {
for (RecordDataSchema.Field field : ((RecordDataSchema) schema).getFields()) {
if (!(spec.isRequiredFieldsOnly() && field.getOptional())) {
final Object value;
if (spec.isUseDefaults() && field.getDefault() != null) {
value = field.getDefault();
} else {
value = buildData(parentSchemas, field.getType(), field.getName(), spec);
}
// null is returned for NULL Pegasus type (used in unions, primarily)
if (value == null) {
data.remove(field.getName());
} else {
data.put(field.getName(), value);
}
}
}
} else if (schema instanceof TyperefDataSchema) {
data.put("ref", buildData(parentSchemas, schema.getDereferencedDataSchema(), spec));
} else {
data.put("value", buildData(parentSchemas, schema, spec));
}
parentSchemas.decrementReferences(schema);
return data;
}
use of com.linkedin.data.DataMap in project rest.li by linkedin.
the class DynamicRecordTemplate method putArray.
/**
* Puts an array field value by doing the necessary unwrapping at the items level.
* @param field specifies the field to put the value for.
* @param fieldDef specifies the field definition to put the value for.
* @param value provides the value to put for the specified field.
* @param <T> provides the type of the value.
*/
@SuppressWarnings({ "unchecked" })
private <T> void putArray(RecordDataSchema.Field field, FieldDef<T> fieldDef, T value) {
DataList data = new DataList();
Class<?> itemType = null;
ArrayDataSchema arrayDataSchema = null;
if (fieldDef.getDataSchema() instanceof ArrayDataSchema) {
arrayDataSchema = (ArrayDataSchema) fieldDef.getDataSchema();
DataSchema itemSchema = arrayDataSchema.getItems();
if (itemSchema instanceof TyperefDataSchema) {
itemType = DataSchemaUtil.dataSchemaTypeToPrimitiveDataSchemaClass(itemSchema.getDereferencedType());
} else {
itemType = fieldDef.getType().getComponentType();
}
} else {
throw new IllegalArgumentException("Field " + fieldDef.getName() + " does not have an array schema; although the data is an array.");
}
boolean isDataTemplate = DataTemplate.class.isAssignableFrom(itemType);
List<Object> items;
if (value instanceof DataList) {
items = (List<Object>) value;
} else {
items = Arrays.asList((Object[]) value);
}
for (Object item : items) {
if (isDataTemplate) {
Object itemData;
if (item instanceof DataMap) {
itemData = item;
} else {
itemData = ((DataTemplate) item).data();
}
data.add(itemData);
} else {
data.add(DataTemplateUtil.coerceInput(item, (Class<Object>) item.getClass(), itemType.isEnum() ? String.class : itemType));
}
}
putDirect(field, DataList.class, data, SetMode.DISALLOW_NULL);
}
Aggregations