001package ezvcard.property;
002
003import java.util.LinkedHashMap;
004import java.util.List;
005import java.util.Map;
006
007import ezvcard.SupportedVersions;
008import ezvcard.VCard;
009import ezvcard.VCardVersion;
010import ezvcard.ValidationWarning;
011
012/*
013 Copyright (c) 2012-2023, Michael Angstadt
014 All rights reserved.
015
016 Redistribution and use in source and binary forms, with or without
017 modification, are permitted provided that the following conditions are met: 
018
019 1. Redistributions of source code must retain the above copyright notice, this
020 list of conditions and the following disclaimer. 
021 2. Redistributions in binary form must reproduce the above copyright notice,
022 this list of conditions and the following disclaimer in the documentation
023 and/or other materials provided with the distribution. 
024
025 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
026 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
027 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
028 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
029 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
030 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
031 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
032 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
033 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
034 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
035
036 The views and conclusions contained in the software and documentation are those
037 of the authors and should not be interpreted as representing official policies, 
038 either expressed or implied, of the FreeBSD Project.
039 */
040
041/**
042 * <p>
043 * Defines the person's sex.
044 * </p>
045 * 
046 * <p>
047 * <b>Code sample (creating)</b>
048 * </p>
049 * 
050 * <pre class="brush:java">
051 * VCard vcard = new VCard();
052 * 
053 * Gender gender = Gender.male();
054 * vcard.setGender(gender);
055 * </pre>
056 * 
057 * <p>
058 * <b>Code sample (retrieving)</b>
059 * </p>
060 * 
061 * <pre class="brush:java">
062 * VCard vcard = ...
063 * Gender gender = vcard.getGender();
064 * if (gender.isMale()) {
065 *   //gender is male
066 * } else if (gender.isFemale()) {
067 *   //gender is female
068 * }
069 * //etc
070 * </pre>
071 * 
072 * <p>
073 * <b>Property name:</b> {@code GENDER}
074 * </p>
075 * <p>
076 * <b>Supported versions:</b> {@code 4.0}
077 * </p>
078 * @author Michael Angstadt
079 * @see <a href="http://tools.ietf.org/html/rfc6350#page-32">RFC 6350 p.32</a>
080 */
081@SupportedVersions(VCardVersion.V4_0)
082public class Gender extends VCardProperty {
083        public static final String MALE = "M";
084        public static final String FEMALE = "F";
085        public static final String OTHER = "O";
086        public static final String NONE = "N";
087        public static final String UNKNOWN = "U";
088
089        private String gender;
090        private String text;
091
092        /**
093         * Creates a gender property. Use of this constructor is discouraged. Please
094         * use one of the static factory methods to create a new GENDER property.
095         * @param gender the gender value (e.g. "F")
096         */
097        public Gender(String gender) {
098                this.gender = gender;
099        }
100
101        /**
102         * Copy constructor.
103         * @param original the property to make a copy of
104         */
105        public Gender(Gender original) {
106                super(original);
107                gender = original.gender;
108                text = original.text;
109        }
110
111        /**
112         * Gets the additional text associated with this property.
113         * @return the additional text or null if there is no text
114         */
115        public String getText() {
116                return text;
117        }
118
119        /**
120         * Sets the additional text associated with this property.
121         * @param text additional text or null to remove
122         */
123        public void setText(String text) {
124                this.text = text;
125        }
126
127        /**
128         * Gets the gender value.
129         * @return the gender value (see static strings for the possible values)
130         */
131        public String getGender() {
132                return gender;
133        }
134
135        /**
136         * Sets the gender value.
137         * @param gender the gender value (see static strings for the possible
138         * values)
139         */
140        public void setGender(String gender) {
141                this.gender = gender;
142        }
143
144        /**
145         * Determines if the gender is "male" or not.
146         * @return true if the gender is "male", false if not
147         */
148        public boolean isMale() {
149                return MALE.equals(gender);
150        }
151
152        /**
153         * Determines if the gender is "female" or not.
154         * @return true if the gender is "female", false if not
155         */
156        public boolean isFemale() {
157                return FEMALE.equals(gender);
158        }
159
160        /**
161         * Determines if the gender is "other" or not.
162         * @return true if the gender is "other", false if not
163         */
164        public boolean isOther() {
165                return OTHER.equals(gender);
166        }
167
168        /**
169         * Determines if the gender is "none" or not. A group, organization, or
170         * location may have this gender property.
171         * @return true if the gender is "none", false if not
172         */
173        public boolean isNone() {
174                return NONE.equals(gender);
175        }
176
177        /**
178         * Determines if the gender is "unknown" or not.
179         * @return true if the gender is "unknown", false if not
180         */
181        public boolean isUnknown() {
182                return UNKNOWN.equals(gender);
183        }
184
185        /**
186         * Creates a gender property whose value is set to "male".
187         * @return a "male" gender property
188         */
189        public static Gender male() {
190                return new Gender(MALE);
191        }
192
193        /**
194         * Creates a gender property whose value is set to "female".
195         * @return a "female" gender property
196         */
197        public static Gender female() {
198                return new Gender(FEMALE);
199        }
200
201        /**
202         * Creates a gender property whose value is set to "other".
203         * @return an "other" gender property
204         */
205        public static Gender other() {
206                return new Gender(OTHER);
207        }
208
209        /**
210         * Creates a gender property whose value is set to "none". Groups,
211         * organizations, and locations should be given this gender property.
212         * @return a "none" gender property
213         */
214        public static Gender none() {
215                return new Gender(NONE);
216        }
217
218        /**
219         * Creates a gender property whose value is set to "unknown".
220         * @return a "unknown" gender property
221         */
222        public static Gender unknown() {
223                return new Gender(UNKNOWN);
224        }
225
226        @Override
227        protected void _validate(List<ValidationWarning> warnings, VCardVersion version, VCard vcard) {
228                if (gender == null) {
229                        warnings.add(new ValidationWarning(8));
230                }
231        }
232
233        @Override
234        protected Map<String, Object> toStringValues() {
235                Map<String, Object> values = new LinkedHashMap<>();
236                values.put("gender", gender);
237                values.put("text", text);
238                return values;
239        }
240
241        @Override
242        public Gender copy() {
243                return new Gender(this);
244        }
245
246        @Override
247        public int hashCode() {
248                final int prime = 31;
249                int result = super.hashCode();
250                result = prime * result + ((gender == null) ? 0 : gender.hashCode());
251                result = prime * result + ((text == null) ? 0 : text.hashCode());
252                return result;
253        }
254
255        @Override
256        public boolean equals(Object obj) {
257                if (this == obj) return true;
258                if (!super.equals(obj)) return false;
259                Gender other = (Gender) obj;
260                if (gender == null) {
261                        if (other.gender != null) return false;
262                } else if (!gender.equals(other.gender)) return false;
263                if (text == null) {
264                        if (other.text != null) return false;
265                } else if (!text.equals(other.text)) return false;
266                return true;
267        }
268}