Flex Gateway新着情報
Governance新着情報
Monitoring API Manager入力メタデータとは、コンポーネントのパラメーター型の解決を意味します。 各パラメーターは、同じコンポーネントの他のパラメーターが公開している種類のメタデータとは分離された静的または動的メタデータを提供します。 動的メタデータのパラメーターは操作でのみ使用できます。ソース、設定、および接続のパラメーターは常に静的メタデータとなります。
InputTypeResolver
実装は、MetadataContext
が提供する情報に基づいて、また、最も重要な点として MetadataKey
を使用してアプリケーション開発者が必要とする MetadataType
を特定することによって、MetadataType
の解決要求を処理します。MetadataType
の詳細は、「コンポーネントのメタデータとは?」を参照してください。
public class InputEntityResolver implements InputTypeResolver<String> {
@Override
public String getCategoryName() {
return "DocEntities";
}
@Override
public MetadataType getInputMetadata(MetadataContext context, String key)
throws MetadataResolvingException, ConnectionException {
final ObjectTypeBuilder objectBuilder = context.getTypeBuilder().objectType();
switch (key) {
case "Author_id":
objectBuilder.addField().key("name").value().numberType();
objectBuilder.addField().key("lastName").value().stringType();
break;
case "BookList_id":
objectBuilder.addField().key("genre").value().stringType();
objectBuilder.addField().key("bookIds").value().arrayType().of().stringType();
break;
case "Book_id":
objectBuilder.addField().key("title").value().stringType();
objectBuilder.addField().key("ISBN").value().numberType();
break;
default:
throw new MetadataResolvingException("Unknown key:" + key, INVALID_METADATA_KEY);
}
return objectBuilder.build();
}
}
上述の例では、typeBuilder
を取得するために MetadataContext
のみを使用していますが、提供されている設定要素や接続要素を使用することもできます。
たとえば、接続要素を使用して外部サービスからメタデータをフェッチしたり、スキーマのような設定要素に含まれる静的リソースにアクセスしたりできます。
TypesKeysResolver
と InputTypeResolver
を使用することで、操作とソースに入力 DataSense サポートを追加できます。
InputTypeResolver
と特定の TypesKeysResolver
を一緒に使用する場合の主な制限は、TypesKeysResolver
で提供される MetadataKey
が InputTypeResolver
によって MetadataType
に解決できるようにするため、どちらも同じ category
に属している必要があるという点です。
public class DemoOperation {
public void create(@Connection MyConnection connection,
@MetadataKeyId(EntityKeysResolver.class) String type,
@TypeResolver(InputEntityResolver.class) Map<String, Object> entity){
// Code that handles the creation based on the "type" of the "entity"
if ("Account_id".equals(type)){
//...
} else {
//...
}
}
}
各パラメーターは専用の TypeResolver
を持ち、それぞれが任意の InputEntityResolver
を使用します。つまり、両方が同じリゾルバーを使用することもでき、結果として 2 つのパラメーターで同じ MetadataType を記述したり、同じ MetadataKeyId
を使用して 2 つの異なる MetadataType
(各パラメーターに 1 つずつ) を記述したりすることができます。
たとえば、2 つのパラメーターで同じリゾルバーを使用することで、エンティティをマージできます。
public void merge(@MetadataKeyId(EntityKeysResolver.class) String type,
@TypeResolver(InputEntityResolver.class) Map<String, Object> first,
@TypeResolver(InputEntityResolver.class) Map<String, Object> second){
// Code that handles the merge based on the "type" of the "entity"
if ("BookList_id".equals(type)){
((List)first.get("bookIds")).addAll((List) second.get("bookIds"));
} else {
//...
}
}
あるいは、各エンティティ用に 2 つの異なる MetadataType
を定義する必要があっても、常に同じ (1 回だけ解決される) MetadataKeyId
にバインドされるため、すべて同じ category
に属するようになります。
public void crete(@MetadataKeyId(EntityKeysResolver.class) String type,
@TypeResolver(ItemTypeResolver.class) Map<String, Object> item,
@TypeResolver(ContainerTypeResolver.class) Map<String, Object> container){
// Code that handles the item based on the "type" of the "entity"
if ("developer".equals(type)){
createDeveloperInTeam(item, container);
} else {
//...
}
}
前のセクションでは、MetadataKeyId
パラメーターが TypeKeysResolver
を宣言していない場合に、アプリケーション開発者が操作の設定時に任意のキーを定義できることを示しました。
このセクションでは、MetadataKeyId
を TypeKeysResolver
なしで使用して、パラメーターで設定されている値を使用して Database Connector で queryParameters
の入力 MetadataType を解決する簡単な例を示します。
public List<Map<String, Object>> select(@MetadataKeyId String sql,
@TypeResolver(DbInputMetadataResolver.class) Map<String, Object> queryParameters,
@Config DbConnector connector){
//...
}
public class DbInputMetadataResolver implements InputTypeResolver<String> {
@Override
public String getCategoryName() {
return "DbCategory";
}
@Override
public MetadataType getInputMetadata(MetadataContext context, String query)
throws MetadataResolvingException, ConnectionException {
// The MetadataKey is the `query` parameter, we have to parse it to resolve
// all the Metadata of its parameters
QueryTemplate queryTemplate = parseQuery(query);
List<InputQueryParam> inputParams = queryTemplate.getInputParams();
if (inputParams.size() == 0) {
// No input metadata when no input parameters
return context.getTypeBuilder().nullType().build();
}
PreparedStatement statement = getStatement(context, queryTemplate);
return getInputMetadataUsingStatementMetadata(statement, inputParams);
}
}
未知の構造を持つエンティティが複数存在することは希で、通常は、たとえばアプリケーション開発者が Sandbox に接続するために使用しているログイン情報に依存するような、動的 MetadataType が 1 つだけ存在します。この場合は、同じ Organization
エンティティでも、アカウントによって異なるプロパティとなる場合があります。
KeyLess
InputMetadata の解決を宣言するには、MetadataKeyId
パラメーターを省略して、MetadataKey
に依存せずに TypeResolver
を使用します。
public void createOrg(@TypeResolver(OrganizationTypeResolver.class) Map<String, Object> organization){
//...
}
public class OrganizationTypeResolver implements InputTypeResolver {
@Override
public String getCategoryName() {
return "Organization";
}
@Override
public MetadataType getInputMetadata(MetadataContext context, Object key)
throws MetadataResolvingException, ConnectionException {
// The `key` parameter will be `null` if the fetch is performed
// as a `KeyLess` Metadata resolution. We'll just ignore it.
DemoConnection connection = context.<DemoConnection>getConnection()
.orElseThrow(() -> new MetadataResolvingException("A connection is required to resolve Metadata but none was provided",
FailureCode.INVALID_CONFIGURATION));
String schema = connection.getClient().describeOrganization();
return new JsonTypeLoader(schema).load("http://demo.org")
.orElseThrow(() -> new MetadataResolvingException("No Metadata is available for the Organization",
FailureCode.NO_DYNAMIC_TYPE_AVAILABLE));
}
}