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                            final char first = line.charAt(0); 
073                            if (Character.isLetter(first)) {
074                                    
075                                    // new key
076                                    
077                                    if (buffer.length() > 0) {
078                                            // flush value of previous key
079                                            set(key, buffer.toString());
080                                            buffer = new StringBuffer();
081                                    }
082                                    
083                                    
084                                    final int i = line.indexOf(':');
085                                    
086                                    if (i < 0) {
087                                            throw new ParseException("Line misses ':' delimitter", linenr);
088                                    }
089                                    
090                                    key = line.substring(0, i);
091                                    buffer.append(line.substring(i+1).trim());
092                                    
093                                    continue;
094                            }
095                            
096                            // continuing old value
097                            buffer.append('\n').append(line.substring(1));
098                    }
099                    br.close();
100                    
101            }
102            
103            public void set( final String pKey, final String pValue ) {
104    
105                    if (resolver != null) {
106                            try {
107                                    values.put(pKey, Utils.replaceVariables(resolver, pValue, "[[", "]]"));
108                                    return;
109                            } catch (ParseException e) {
110                                    // FIXME maybe throw an Exception?
111                            }
112                    }
113                    
114                    values.put(pKey, pValue);
115            }
116            
117            public String get( final String pKey ) {
118                    return (String)values.get(pKey);
119            }
120    
121            public abstract String[] getMandatoryKeys();
122            
123            public boolean isValid() {
124                    return invalidKeys().size() == 0;
125            }
126            
127            public Set invalidKeys() {
128                    final Set invalid = new HashSet();
129    
130                    final String[] mk = getMandatoryKeys();
131                    for (int i = 0; i < mk.length; i++) {
132                            if (get(mk[i]) == null) {
133                                    invalid.add(mk[i]);
134                            }
135                    }
136                    
137                    return invalid;
138            }
139            
140            String toString( final String[] pKeys ) {
141                    final StringBuffer s = new StringBuffer();
142                    for (int i = 0; i < pKeys.length; i++) {
143                            final String key = pKeys[i];
144                            final String value = (String) values.get(key);
145                            if (value != null) {
146                                    s.append(key).append(":");
147    
148                                    try {
149                                            BufferedReader reader = new BufferedReader(new StringReader(value));
150                                            String line;
151                                            while ((line = reader.readLine()) != null) {
152                                                    if (line.length() != 0 && !Character.isWhitespace(line.charAt(0))) {
153                                                            s.append(' ');
154                                                    }
155    
156                                                    s.append(line).append('\n');
157                                            }
158                                    } catch (IOException e) {
159                                            e.printStackTrace();
160                                    }
161                            }                       
162                    }
163                    return s.toString();
164            }
165    }