001    /*
002     * Copyright 2005 The Apache Software Foundation.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.vafer.jdeb.descriptors;
017    
018    import java.io.BufferedReader;
019    import java.io.IOException;
020    import java.io.InputStream;
021    import java.io.InputStreamReader;
022    import java.io.StringReader;
023    import java.text.ParseException;
024    import java.util.HashMap;
025    import java.util.HashSet;
026    import java.util.Map;
027    import java.util.Set;
028    
029    import org.vafer.jdeb.utils.Utils;
030    import org.vafer.jdeb.utils.VariableResolver;
031    
032    /**
033     * A descriptor holds the usual key value pairs.
034     *
035     * @see <a href="http://www.debian.org/doc/debian-policy/ch-controlfields.html">Debian Policy Manual - Control files and their fields</a>
036     * 
037     * @author Torsten Curdt <tcurdt@vafer.org>
038     */
039    public abstract class AbstractDescriptor {
040            
041            private final Map values = new HashMap();
042            private final VariableResolver resolver;
043            
044            public AbstractDescriptor( final VariableResolver pResolver ) {
045                    resolver = pResolver;
046            }
047    
048            public AbstractDescriptor( final AbstractDescriptor pDescriptor ) {
049                    values.putAll(pDescriptor.values);
050                    resolver = pDescriptor.resolver;
051            }
052    
053            protected void parse( final InputStream pInput ) throws IOException, ParseException {
054                    final BufferedReader br = new BufferedReader(new InputStreamReader(pInput));
055                    StringBuffer buffer = new StringBuffer();
056                    String key = null;
057                    int linenr = 0;
058                    while(true) {
059                            final String line = br.readLine();
060                            
061                            if (line == null) {
062                                    if (buffer.length() > 0) {
063                                            // flush value of previous key
064                                            set(key, buffer.toString());
065                                            buffer = null;
066                                    }
067                                    break;
068                            }
069    
070                            linenr++;
071    
072                            if (line.length() == 0) {
073                                    throw new ParseException("Empty line", linenr);
074                            }
075                            
076                            final char first = line.charAt(0); 
077                            if (Character.isLetter(first)) {
078                                    
079                                    // new key
080                                    
081                                    if (buffer.length() > 0) {
082                                            // flush value of previous key
083                                            set(key, buffer.toString());
084                                            buffer = new StringBuffer();
085                                    }
086                                    
087                                    
088                                    final int i = line.indexOf(':');
089                                    
090                                    if (i < 0) {
091                                            throw new ParseException("Line misses ':' delimitter", linenr);
092                                    }
093                                    
094                                    key = line.substring(0, i);
095                                    buffer.append(line.substring(i+1).trim());
096                                    
097                                    continue;
098                            }
099                            
100                            // continuing old value
101                            buffer.append('\n').append(line.substring(1));
102                    }
103                    br.close();
104                    
105            }
106            
107            public void set( final String pKey, final String pValue ) {
108    
109                    if (resolver != null) {
110                            try {
111                                    values.put(pKey, Utils.replaceVariables(resolver, pValue, "[[", "]]"));
112                                    return;
113                            } catch (ParseException e) {
114                                    // FIXME maybe throw an Exception?
115                            }
116                    }
117                    
118                    values.put(pKey, pValue);
119            }
120            
121            public String get( final String pKey ) {
122                    return (String)values.get(pKey);
123            }
124    
125            public abstract String[] getMandatoryKeys();
126            
127            public boolean isValid() {
128                    return invalidKeys().size() == 0;
129            }
130            
131            public Set invalidKeys() {
132                    final Set invalid = new HashSet();
133    
134                    final String[] mk = getMandatoryKeys();
135                    for (int i = 0; i < mk.length; i++) {
136                            if (get(mk[i]) == null) {
137                                    invalid.add(mk[i]);
138                            }
139                    }
140                    
141                    return invalid;
142            }
143            
144            String toString( final String[] pKeys ) {
145                    final StringBuffer s = new StringBuffer();
146                    for (int i = 0; i < pKeys.length; i++) {
147                            final String key = pKeys[i];
148                            final String value = (String) values.get(key);
149                            if (value != null) {
150                                    s.append(key).append(":");
151    
152                                    try {
153                                            BufferedReader reader = new BufferedReader(new StringReader(value));
154                                            String line;
155                                            while ((line = reader.readLine()) != null) {
156                                                    if (line.length() != 0 && !Character.isWhitespace(line.charAt(0))) {
157                                                            s.append(' ');
158                                                    }
159    
160                                                    s.append(line).append('\n');
161                                            }
162                                    } catch (IOException e) {
163                                            e.printStackTrace();
164                                    }
165                            }                       
166                    }
167                    return s.toString();
168            }
169    }