001/* 002 * GeoAPI - Java interfaces for OGC/ISO standards 003 * Copyright © 2006-2024 Open Geospatial Consortium, Inc. 004 * http://www.geoapi.org 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.opengis.util; 019 020import java.util.Map; 021import org.opengis.annotation.UML; 022 023import static org.opengis.annotation.Obligation.*; 024import static org.opengis.annotation.Specification.*; 025 026 027/** 028 * A list of logically related fields as (<var>name</var>, <var>value</var>) pairs in a dictionary. 029 * A {@code Record} is an instance of an {@link RecordType}. 030 * For example, a {@code Record} may be a row in a table described by a {@code RecordType}. 031 * 032 * <h2>Relationship with Java {@code Record} class</h2> 033 * This interface serves a purpose similar to the {@link java.lang.Record} abstract class 034 * provided by the standard Java platform, but is used in a different context. 035 * The standard Java {@code Record} class provides static records (i.e., with structure defined at compile time), 036 * while this GeoAPI {@code Record} interfaces provides dynamic records. 037 * The former is more convenient, efficient and type-safe, 038 * while the latter is the only option when the record structure is not known in advance, 039 * for example when it is determined by the content of a data file being read. 040 * If interoperability between the two models is desired, 041 * a GeoAPI {@code Record} implementation could delegate all operations 042 * to a wrapped Java {@code Record} using {@link java.lang.reflect.RecordComponent}. 043 * 044 * @author Bryce Nordgren (USDA) 045 * @author Martin Desruisseaux (IRD) 046 * @version 3.1 047 * @since 2.1 048 * 049 * @see RecordType 050 */ 051@UML(identifier="Record", specification=ISO_19103) 052public interface Record { 053 /** 054 * Returns the type definition of this record. All fields named in this record must be defined 055 * in the returned record type. In other words, the following assertion must holds: 056 * 057 * {@snippet lang="java" : 058 * Set<MemberName> members = getRecordType().getMembers(); 059 * Set<MemberName> fields = getFields().keySet(); 060 * assert members.containsAll(fields); 061 * } 062 * 063 * This association is optional according ISO 19103. 064 * But implementers are encouraged to provide a value in all cases. 065 * 066 * @return the type definition of this record. May be {@code null}. 067 */ 068 @UML(identifier="type", obligation=OPTIONAL, specification=ISO_19103) 069 RecordType getRecordType(); 070 071 /** 072 * Returns the dictionary of all (<var>name</var>, <var>value</var>) pairs in this record. 073 * The returned map should not allows entry addition or removal. 074 * It may allows the replacement of values for existing keys only. 075 * 076 * @return the dictionary of all (<var>name</var>, <var>value</var>) pairs in this record. 077 * 078 * @see RecordType#getFieldTypes() 079 * 080 * @since 3.1 081 */ 082 @UML(identifier="field", obligation=MANDATORY, specification=ISO_19103) 083 Map<MemberName, Object> getFields(); 084 085 /** 086 * Returns the dictionary of all (<var>name</var>, <var>value</var>) pairs in this record. 087 * The returned map should not allows key addition or removal. 088 * It may allows the replacement of values for existing keys only. 089 * 090 * @return the dictionary of all (<var>name</var>, <var>value</var>) pairs in this record. 091 * 092 * @see RecordType#getMemberTypes() 093 * 094 * @deprecated Renamed {@link #getFields()} in the 2015 revision of ISO 19103. 095 */ 096 @Deprecated(since="3.1") 097 @UML(identifier="memberValue", obligation=MANDATORY, specification=ISO_19103, version=2005) 098 default Map<MemberName, Object> getAttributes() { 099 return getFields(); 100 } 101 102 /** 103 * Returns the value for a field of the specified name. 104 * 105 * @param name the name of the field to lookup. 106 * @return the value of the field for the given name. 107 * 108 * @deprecated This method has been removed from the ISO 19103:2015 standard. It has been kept in GeoAPI 109 * for convenience, but renamed {@link #get(MemberName)} for consistency with common practice. 110 */ 111 @Deprecated(since="3.1") 112 default Object locate(MemberName name) { 113 return get(name); 114 } 115 116 /** 117 * Returns the value for a field of the specified name. 118 * This is functionally equivalent to the following code: 119 * 120 * {@snippet lang="java" : 121 * return getFields().get(name); 122 * } 123 * 124 * The type of the returned object is given by 125 * <code>{@linkplain #getRecordType()}.{@linkplain RecordType#locate locate}(name)</code>. 126 * 127 * @param name the name of the field to lookup. 128 * @return the value of the field for the given name. 129 * 130 * @see RecordType#locate(MemberName) 131 * 132 * @departure historic 133 * This method was named {@code locate} in ISO 19103:2005 and removed in ISO 19103:2015. 134 * It has been kept in GeoAPI as a convenience shortcut for a frequently used operation. 135 * 136 * @since 3.1 137 */ 138 @UML(identifier="locate", obligation=MANDATORY, specification=ISO_19103, version=2005) 139 default Object get(MemberName name) { 140 return getFields().get(name); 141 } 142 143 /** 144 * Sets the value for the field of the specified name. 145 * This is functionally equivalent to the following code: 146 * 147 * {@snippet lang="java" : 148 * getFields().put(name, value); 149 * } 150 * 151 * Remind that {@code name} keys are constrained to 152 * {@linkplain RecordType#getMembers() record type members} only. 153 * 154 * @param name the name of the field to modify. 155 * @param value the new value for the field. 156 * @throws UnsupportedOperationException if this record is not modifiable. 157 * 158 * @departure easeOfUse 159 * This is a convenience shortcut for a frequently used operation. 160 */ 161 default void set(MemberName name, Object value) throws UnsupportedOperationException { 162 getFields().put(name, value); 163 } 164}