001package ezvcard.property;
002
003import java.util.LinkedHashMap;
004import java.util.List;
005import java.util.Map;
006
007import com.github.mangstadt.vinnie.SyntaxStyle;
008import com.github.mangstadt.vinnie.validate.AllowedCharacters;
009import com.github.mangstadt.vinnie.validate.VObjectValidator;
010
011import ezvcard.VCard;
012import ezvcard.VCardDataType;
013import ezvcard.VCardVersion;
014import ezvcard.ValidationWarning;
015
016/*
017 Copyright (c) 2012-2023, Michael Angstadt
018 All rights reserved.
019
020 Redistribution and use in source and binary forms, with or without
021 modification, are permitted provided that the following conditions are met: 
022
023 1. Redistributions of source code must retain the above copyright notice, this
024 list of conditions and the following disclaimer. 
025 2. Redistributions in binary form must reproduce the above copyright notice,
026 this list of conditions and the following disclaimer in the documentation
027 and/or other materials provided with the distribution. 
028
029 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
030 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
031 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
032 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
033 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
034 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
035 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
036 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
037 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
038 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
039
040 The views and conclusions contained in the software and documentation are those
041 of the authors and should not be interpreted as representing official policies, 
042 either expressed or implied, of the FreeBSD Project.
043 */
044
045/**
046 * Holds the property value as-is. No escaping or unescaping is done on the
047 * value.
048 * @author Michael Angstadt
049 */
050public class RawProperty extends TextProperty {
051        private String propertyName;
052        private VCardDataType dataType;
053
054        /**
055         * Creates a raw property.
056         * @param propertyName the property name (e.g. "X-GENDER")
057         * @param value the property value
058         */
059        public RawProperty(String propertyName, String value) {
060                this(propertyName, value, null);
061        }
062
063        /**
064         * Creates a raw property.
065         * @param propertyName the property name (e.g. "X-GENDER")
066         * @param value the property value
067         * @param dataType the value's data type
068         */
069        public RawProperty(String propertyName, String value, VCardDataType dataType) {
070                super(value);
071                this.propertyName = propertyName;
072                this.dataType = dataType;
073        }
074
075        /**
076         * Copy constructor.
077         * @param original the property to make a copy of
078         */
079        public RawProperty(RawProperty original) {
080                super(original);
081                propertyName = original.propertyName;
082                dataType = original.dataType;
083        }
084
085        /**
086         * Gets the name of the property.
087         * @return the property name
088         */
089        public String getPropertyName() {
090                return propertyName;
091        }
092
093        /**
094         * Sets the name of the property.
095         * @param propertyName the property name
096         */
097        public void setPropertyName(String propertyName) {
098                this.propertyName = propertyName;
099        }
100
101        /**
102         * Gets the data type of the property's value.
103         * @return the data type or null if unknown
104         */
105        public VCardDataType getDataType() {
106                return dataType;
107        }
108
109        /**
110         * Sets the data type of the property's value.
111         * @param dataType the data type or null if unknown
112         */
113        public void setDataType(VCardDataType dataType) {
114                this.dataType = dataType;
115        }
116
117        @Override
118        protected void _validate(List<ValidationWarning> warnings, VCardVersion version, VCard vcard) {
119                SyntaxStyle syntax = version.getSyntaxStyle();
120                AllowedCharacters allowed = VObjectValidator.allowedCharactersParameterName(syntax, true);
121                if (!allowed.check(propertyName)) {
122                        if (syntax == SyntaxStyle.OLD) {
123                                AllowedCharacters notAllowed = allowed.flip();
124                                warnings.add(new ValidationWarning(33, propertyName, notAllowed.toString(true)));
125                        } else {
126                                warnings.add(new ValidationWarning(24, propertyName));
127                        }
128                }
129        }
130
131        @Override
132        protected Map<String, Object> toStringValues() {
133                Map<String, Object> values = new LinkedHashMap<>();
134                values.put("propertyName", propertyName);
135                values.put("dataType", dataType);
136                values.put("value", value);
137                return values;
138        }
139
140        @Override
141        public RawProperty copy() {
142                return new RawProperty(this);
143        }
144
145        @Override
146        public int hashCode() {
147                final int prime = 31;
148                int result = super.hashCode();
149                result = prime * result + ((dataType == null) ? 0 : dataType.hashCode());
150                result = prime * result + ((propertyName == null) ? 0 : propertyName.toLowerCase().hashCode());
151                return result;
152        }
153
154        @Override
155        public boolean equals(Object obj) {
156                if (this == obj) return true;
157                if (!super.equals(obj)) return false;
158                RawProperty other = (RawProperty) obj;
159                if (dataType == null) {
160                        if (other.dataType != null) return false;
161                } else if (!dataType.equals(other.dataType)) return false;
162                if (propertyName == null) {
163                        if (other.propertyName != null) return false;
164                } else if (!propertyName.equalsIgnoreCase(other.propertyName)) return false;
165                return true;
166        }
167}