001/*
002 * This file is part of the JDrupes non-blocking HTTP Codec
003 * Copyright (C) 2017 Michael N. Lipp
004 *
005 * This program is free software; you can redistribute it and/or modify it 
006 * under the terms of the GNU Lesser General Public License as published
007 * by the Free Software Foundation; either version 3 of the License, or 
008 * (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful, but 
011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
013 * License for more details.
014 *
015 * You should have received a copy of the GNU Lesser General Public License along 
016 * with this program; if not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jdrupes.httpcodec.types;
020
021import java.util.Arrays;
022
023/**
024 * Represents a value with a optional comments
025 * such as `value (comment)`.
026 * 
027 * @param <U> the type of the uncommented value
028 */
029public class CommentedValue<U> {
030
031        private static final String[] NO_COMMENTS = new String[0];
032        
033        private U value;
034        private String[] comments;
035        
036        /**
037         * Creates a new object with the given value and no comment. 
038         * 
039         * @param value the value
040         */
041        public CommentedValue(U value) {
042                this (value, (String[])null);
043        }
044
045        /**
046         * Creates a new object with the given value and comment. 
047         * 
048         * @param value the value
049         * @param comment the comment (without parenthesis)
050         */
051        public CommentedValue(U value, String comment) {
052                this (value, new String[] { comment });
053        }
054
055        /**
056         * Creates a new object with the given value and comments. 
057         * 
058         * @param value the value
059         * @param comments the comments (without parenthesis)
060         */
061        public CommentedValue(U value, String[] comments) {
062                this.value = value;
063                this.comments = comments;
064        }
065
066        /**
067         * Returns the value.
068         * 
069         * @return the value
070         */
071        public U value() {
072                return value;
073        }
074
075        /**
076         * Returns the comments (without parenthesis).
077         * 
078         * @return the comments 
079         */
080        public String[] comments() {
081                if (comments == null) {
082                        return NO_COMMENTS;
083                }
084                return Arrays.copyOf(comments, comments.length);
085        }
086        
087        /* (non-Javadoc)
088         * @see java.lang.Object#toString()
089         */
090        @Override
091        public String toString() {
092                StringBuilder builder = new StringBuilder();
093                builder.append("CommentedValue [");
094                if (value != null) {
095                        builder.append("value=");
096                        builder.append(value);
097                        builder.append(", ");
098                }
099                if (comments != null) {
100                        builder.append("comments=");
101                        builder.append(Arrays.toString(comments));
102                }
103                builder.append("]");
104                return builder.toString();
105        }
106
107        /* (non-Javadoc)
108         * @see java.lang.Object#hashCode()
109         */
110        @Override
111        public int hashCode() {
112                final int prime = 31;
113                int result = 1;
114                result = prime * result + Arrays.hashCode(comments);
115                result = prime * result + ((value == null) ? 0 : value.hashCode());
116                return result;
117        }
118
119        /* (non-Javadoc)
120         * @see java.lang.Object#equals(java.lang.Object)
121         */
122        @Override
123        public boolean equals(Object obj) {
124                if (this == obj) {
125                        return true;
126                }
127                if (obj == null) {
128                        return false;
129                }
130                if (getClass() != obj.getClass()) {
131                        return false;
132                }
133                @SuppressWarnings("rawtypes")
134                CommentedValue other = (CommentedValue) obj;
135                if (!Arrays.equals(comments, other.comments)) {
136                        return false;
137                }
138                if (value == null) {
139                        if (other.value != null) {
140                                return false;
141                        }
142                } else if (!value.equals(other.value)) {
143                        return false;
144                }
145                return true;
146        }
147
148        public static class CommentedValueConverter<U> 
149                implements Converter<CommentedValue<U>> {
150
151                private Converter<U> valueConverter;            
152                
153                /**
154                 * Creates a new converter with the given value converter.
155                 * 
156                 * @param valueConverter the value converter
157                 */
158                public CommentedValueConverter(Converter<U> valueConverter) {
159                        super();
160                        this.valueConverter = valueConverter;
161                }
162
163                @Override
164                public String asFieldValue(CommentedValue<U> value) {
165                        StringBuilder result = new StringBuilder();
166                        result.append(valueConverter.asFieldValue(value.value()));
167                        for (String comment: value.comments()) {
168                                result.append(" (");
169                                result.append(Converters.quote(comment, "()\\"));
170                                result.append(')');
171                        }
172                        return result.toString();
173                }
174
175                /* (non-Javadoc)
176                 * @see org.jdrupes.httpcodec.types.Converter#fromFieldValue(java.lang.String)
177                 */
178                @Override
179                public CommentedValue<U> fromFieldValue(String text) {
180                        throw new UnsupportedOperationException();
181                }
182                
183        }
184}