Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions sdk/src/main/java/io/opentdf/platform/sdk/Resources.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package io.opentdf.platform.sdk;

import io.opentdf.platform.authorization.v2.Resource;

import java.util.Arrays;
import java.util.Objects;

/**
* Convenience constructors for {@link Resource}, analogous to the
* {@link EntityIdentifiers} helpers for {@link io.opentdf.platform.authorization.v2.EntityIdentifier}.
*
* <p>Each method builds the full {@code Resource} proto so callers avoid
* deeply nested builder chains.
*
* <pre>{@code
* // Before
* Resource.newBuilder()
* .setAttributeValues(
* Resource.AttributeValues.newBuilder()
* .addFqns("https://example.com/attr/department/value/finance"))
* .build();
*
* // After
* Resources.forAttributeValues("https://example.com/attr/department/value/finance");
* }</pre>
*/
public final class Resources {

private Resources() {}

/**
* Returns a Resource containing the given attribute value FQNs.
* This is the most common Resource variant, used when authorizing against
* attribute values attached to data (e.g. those on a TDF).
*
* @param fqns one or more fully qualified attribute value names
* @return a fully built {@link Resource} with the {@code attribute_values} oneof set
* @throws NullPointerException if {@code fqns} or any element is null
* @throws IllegalArgumentException if {@code fqns} is empty
*/
public static Resource forAttributeValues(String... fqns) {
Objects.requireNonNull(fqns, "fqns must not be null");
if (fqns.length == 0) {
throw new IllegalArgumentException("fqns must not be empty");
}
for (String fqn : fqns) {
Objects.requireNonNull(fqn, "individual fqn must not be null");
}
return Resource.newBuilder()
.setAttributeValues(
Resource.AttributeValues.newBuilder()
.addAllFqns(Arrays.asList(fqns))
.build())
.build();
}

/**
* Returns a Resource that references a single registered resource value
* by its fully qualified name, as stored in platform policy.
*
* @param fqn the fully qualified name of the registered resource value
* @return a fully built {@link Resource} with the {@code registered_resource_value_fqn} oneof set
* @throws NullPointerException if {@code fqn} is null
*/
public static Resource forRegisteredResourceValueFqn(String fqn) {
Objects.requireNonNull(fqn, "fqn must not be null");
return Resource.newBuilder()
.setRegisteredResourceValueFqn(fqn)
.build();
}
}
63 changes: 63 additions & 0 deletions sdk/src/test/java/io/opentdf/platform/sdk/ResourcesTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package io.opentdf.platform.sdk;

import static org.junit.jupiter.api.Assertions.*;

import io.opentdf.platform.authorization.v2.Resource;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

class ResourcesTest {

@Test
void forAttributeValues_single() {
String fqn = "https://example.com/attr/department/value/finance";
Resource r = Resources.forAttributeValues(fqn);

assertEquals(Resource.ResourceCase.ATTRIBUTE_VALUES, r.getResourceCase());
assertEquals(1, r.getAttributeValues().getFqnsCount());
assertEquals(fqn, r.getAttributeValues().getFqns(0));
}

@Test
void forAttributeValues_multiple() {
String fqn1 = "https://example.com/attr/department/value/finance";
String fqn2 = "https://example.com/attr/level/value/public";
Resource r = Resources.forAttributeValues(fqn1, fqn2);

assertEquals(Resource.ResourceCase.ATTRIBUTE_VALUES, r.getResourceCase());
assertEquals(2, r.getAttributeValues().getFqnsCount());
assertEquals(fqn1, r.getAttributeValues().getFqns(0));
assertEquals(fqn2, r.getAttributeValues().getFqns(1));
}

@Test
void forAttributeValues_emptyStringFqn() {
Resource r = Resources.forAttributeValues("");

assertEquals(Resource.ResourceCase.ATTRIBUTE_VALUES, r.getResourceCase());
assertEquals(1, r.getAttributeValues().getFqnsCount());
assertEquals("", r.getAttributeValues().getFqns(0));
}

@Test
void forAttributeValues_emptyArrayThrows() {
assertThrows(IllegalArgumentException.class, () -> Resources.forAttributeValues());

Check warning on line 45 in sdk/src/test/java/io/opentdf/platform/sdk/ResourcesTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this lambda with method reference 'Resources::forAttributeValues'.

See more on https://sonarcloud.io/project/issues?id=opentdf_java-sdk&issues=AZ2tZCiwvn5gzXa57btR&open=AZ2tZCiwvn5gzXa57btR&pullRequest=354
}

@ParameterizedTest
@ValueSource(strings = {"https://example.com/attr/department/value/finance", ""})
void forRegisteredResourceValueFqn(String fqn) {
Resource r = Resources.forRegisteredResourceValueFqn(fqn);

assertEquals(Resource.ResourceCase.REGISTERED_RESOURCE_VALUE_FQN, r.getResourceCase());
assertEquals(fqn, r.getRegisteredResourceValueFqn());
}

@Test
void nullInputsThrow() {
assertThrows(NullPointerException.class, () -> Resources.forAttributeValues((String[]) null));
assertThrows(NullPointerException.class, () -> Resources.forAttributeValues("valid", null));
assertThrows(NullPointerException.class, () -> Resources.forRegisteredResourceValueFqn(null));
}
}
Loading