diff --git a/src/main/java/com/google/api/resourcenames/ResourceName.java b/src/main/java/com/google/api/resourcenames/ResourceName.java index e67227fcf..751f1fa77 100644 --- a/src/main/java/com/google/api/resourcenames/ResourceName.java +++ b/src/main/java/com/google/api/resourcenames/ResourceName.java @@ -32,7 +32,20 @@ package com.google.api.resourcenames; import com.google.api.core.BetaApi; +import java.util.Map; /** An interface that generated resource name types must implement. */ @BetaApi -public interface ResourceName {} +public interface ResourceName { + + /** + * Return the map of each field name to its value. + */ + Map getFieldValuesMap(); + + /** + * Return the String value of the field with name fieldName. Returns null if the fieldName was not + * found. + */ + String getFieldValue(String fieldName); +} diff --git a/src/main/java/com/google/api/resourcenames/ResourceNameFactory.java b/src/main/java/com/google/api/resourcenames/ResourceNameFactory.java new file mode 100644 index 000000000..13e18d0c5 --- /dev/null +++ b/src/main/java/com/google/api/resourcenames/ResourceNameFactory.java @@ -0,0 +1,40 @@ +/* + * Copyright 2018, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.google.api.resourcenames; + +import com.google.api.core.BetaApi; + +@BetaApi +public interface ResourceNameFactory { + + /* Create a new ResourceName from a formatted String representing a ResourceName. */ + T parse(String formattedString); +} diff --git a/src/main/java/com/google/api/resourcenames/UntypedResourceName.java b/src/main/java/com/google/api/resourcenames/UntypedResourceName.java index 7e7cfe75d..4e2da19c3 100644 --- a/src/main/java/com/google/api/resourcenames/UntypedResourceName.java +++ b/src/main/java/com/google/api/resourcenames/UntypedResourceName.java @@ -33,6 +33,8 @@ import com.google.api.core.BetaApi; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import java.util.Map; /** * A class to represent a {@link ResourceName} with an unknown format. This class in intended to @@ -44,6 +46,8 @@ public class UntypedResourceName implements ResourceName { private final String rawValue; + private volatile Map fieldValuesMap; + private UntypedResourceName(String rawValue) { this.rawValue = Preconditions.checkNotNull(rawValue); } @@ -57,7 +61,26 @@ public static UntypedResourceName parse(String formattedString) { } public static boolean isParsableFrom(String formattedString) { - return true; + return formattedString != null; + } + + /* Returns a map with an empty String "" as the sole key, which maps to the raw value of this ResourceName. */ + @Override + public Map getFieldValuesMap() { + if (fieldValuesMap == null) { + synchronized (this) { + if (fieldValuesMap == null) { + fieldValuesMap = ImmutableMap.of("", rawValue); + } + } + } + return fieldValuesMap; + } + + /* Returns the raw value of this ResourceName iff fieldName.equals(""), else returns null. */ + @Override + public String getFieldValue(String fieldName) { + return getFieldValuesMap().get(""); } @Override diff --git a/src/test/java/com/google/api/resourcenames/UntypedResourceNameTest.java b/src/test/java/com/google/api/resourcenames/UntypedResourceNameTest.java new file mode 100644 index 000000000..ab13287ea --- /dev/null +++ b/src/test/java/com/google/api/resourcenames/UntypedResourceNameTest.java @@ -0,0 +1,95 @@ +/* + * Copyright 2018, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.google.api.resourcenames; + +import static junit.framework.TestCase.fail; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Map; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Tests for {@link UntypedResourceNameTest}. + */ +@RunWith(JUnit4.class) +public class UntypedResourceNameTest { + private static final String NAME_STRING = "sunshine"; + private static final String EMPTY_STRING = ""; + + @Test + public void testGetFieldValues() { + assertTrue(UntypedResourceName.isParsableFrom(NAME_STRING)); + UntypedResourceName fooName = UntypedResourceName.parse(NAME_STRING); + + Map fieldValuesMap = fooName.getFieldValuesMap(); + assertTrue(fieldValuesMap.containsKey(EMPTY_STRING)); + assertEquals(NAME_STRING, fieldValuesMap.get(EMPTY_STRING)); + assertEquals(1, fieldValuesMap.size()); + assertEquals(null, fieldValuesMap.get(NAME_STRING)); + } + + @Test + public void testInsertIntoFieldValuesMap() { + UntypedResourceName fooName = UntypedResourceName.parse(NAME_STRING); + Map fieldValuesMap = fooName.getFieldValuesMap(); + + try { + fieldValuesMap.put(EMPTY_STRING, "foo"); + fail("fieldValuesMap should prevent insertion into internal map. "); + } catch (UnsupportedOperationException e) { + } + + try { + fieldValuesMap.put(null, "foo"); + fail("fieldValuesMap should prevent insertion into internal map. "); + } catch (UnsupportedOperationException e) { + } + + try { + fieldValuesMap.put(NAME_STRING, NAME_STRING); + fail("fieldValuesMap should prevent insertion into internal map. "); + } catch (UnsupportedOperationException e) { + } + } + + @Test + public void testNullName() { + assertFalse(UntypedResourceName.isParsableFrom(null)); + try { + UntypedResourceName fooName = UntypedResourceName.parse(null); + } catch (NullPointerException e) { + } + } +}