001    /*----------------------------------------------------------------------------
002     This file is part of deegree, http://deegree.org/
003     Copyright (C) 2001-2009 by:
004       Department of Geography, University of Bonn
005     and
006       lat/lon GmbH
007    
008     This library is free software; you can redistribute it and/or modify it under
009     the terms of the GNU Lesser General Public License as published by the Free
010     Software Foundation; either version 2.1 of the License, or (at your option)
011     any later version.
012     This library is distributed in the hope that it will be useful, but WITHOUT
013     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
014     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
015     details.
016     You should have received a copy of the GNU Lesser General Public License
017     along with this library; if not, write to the Free Software Foundation, Inc.,
018     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019    
020     Contact information:
021    
022     lat/lon GmbH
023     Aennchenstr. 19, 53177 Bonn
024     Germany
025     http://lat-lon.de/
026    
027     Department of Geography, University of Bonn
028     Prof. Dr. Klaus Greve
029     Postfach 1147, 53001 Bonn
030     Germany
031     http://www.geographie.uni-bonn.de/deegree/
032    
033     e-mail: info@deegree.org
034    ----------------------------------------------------------------------------*/
035    package org.deegree.portal.standard.security.control;
036    
037    import java.io.File;
038    import java.text.ParseException;
039    import java.util.Collection;
040    import java.util.Iterator;
041    import java.util.Vector;
042    
043    /**
044     * TODO add documentation here
045     *
046     * @author <a href="mailto:elmasry@lat-lon.de">Moataz Elmasry</a>
047     * @author last edited by: $Author: elmasri$
048     *
049     * @version $Revision: $, $Date: 08-Mar-2007 16:46:12$
050     */
051    public class RelativePath {
052    
053        /**
054         * get the first match from the many delimiters give as input
055         *
056         * @param source
057         * @param delimiters
058         * @return String
059         */
060        public static String getFirstMatch( String source, String[] delimiters ) {
061    
062            Vector<Delimiter> indices = new Vector<Delimiter>();
063    
064            for ( int i = 0; i < delimiters.length; i++ ) {
065                // we added the indices of all matches to the vector
066                indices.add( new Delimiter( i, source.indexOf( delimiters[i] ), delimiters[i] ) );
067            }
068    
069            Delimiter delimiter = getFirstIndex( indices );
070            if ( delimiter.getValue() == null ) {
071                return null;
072            }
073    
074            return source.substring( 0, delimiter.getFoundAt() + 1 );
075        }
076    
077        /**
078         * Gets the first index of a match from the many delimiters given as input Takes many delimiters
079         * returns the delimiter that occured first
080         *
081         * @param collection
082         * @return instance of Delimiter class
083         */
084        private static Delimiter getFirstIndex( Collection<Delimiter> collection ) {
085    
086            Delimiter delimiter = new Delimiter( -1, 999, null );
087            Iterator it = collection.iterator();
088            // comparing the matches to see which match occured first
089            while ( it.hasNext() ) {
090                Delimiter temp = (Delimiter) it.next();
091                int indexOf = temp.foundAt;
092                if ( indexOf < delimiter.getFoundAt() && indexOf > -1 ) {
093                    delimiter = temp;
094                }
095            }
096    
097            if ( delimiter == null ) {
098                return null;
099            }
100            return delimiter;
101    
102        }
103    
104        /**
105         * Split a string based on the given delimiters and return an array of strings(tokens)
106         *
107         * @param source
108         * @param delimiters
109         * @return tokens from a given string
110         */
111        public static String[] splitString( String source, String[] delimiters ) {
112    
113            if ( source == null || delimiters == null )
114                return null;
115    
116            Vector<String> returnedStrings = new Vector<String>();
117            String tempSource = source;
118    
119            while ( tempSource.length() != 0 ) {
120    
121                int delimiterLength = 0;
122                String match = getFirstMatch( tempSource, delimiters );
123                // if this is the last token in the String
124                if ( match == null ) {
125                    returnedStrings.add( tempSource );
126                    break;
127                } else {
128    
129                    // removing any delimiters that could exist
130                    for ( int i = 0; i < delimiters.length; i++ ) {
131                        if ( match.contains( delimiters[i] ) ) {
132                            match = match.replace( delimiters[i], "" );
133                            delimiterLength = delimiters[i].length();
134                            break;
135                        }
136    
137                    }
138                    // Ignore the ./ and don't add it to the array
139                    if ( match.compareTo( "./" ) != 0 ) {
140                        returnedStrings.add( match );
141                    }
142                    tempSource = tempSource.substring( match.length() + delimiterLength, tempSource.length() );
143                }
144    
145            }
146    
147            String[] strings = new String[returnedStrings.size()];
148            for ( int i = 0; i < returnedStrings.size(); i++ ) {
149                strings[i] = returnedStrings.elementAt( i );
150            }
151            return strings;
152        }
153    
154        /**
155         * Maps from a source sTring to a target String, based on the delimiters given the delimiters
156         * are basically "\\" or "/", but it also could be anything else Two absolute pathes should be
157         * given here Don't give relative or non existing pathes
158         *
159         * @param source
160         * @param target
161         * @param delimiters
162         * @return the mapped path
163         * @throws ParseException
164         */
165        public static String mapRelativePath( String source, String target, String[] delimiters )
166                                throws ParseException {
167    
168            if ( !new File( source ).isAbsolute() ) {
169                throw new ParseException( "The source path is not absolute", 0 );
170            }
171            if ( !new File( target ).isAbsolute() ) {
172                throw new ParseException( "The target path is not absolute", 0 );
173            }
174    
175            String[] sourceTokens = splitString( source, delimiters );
176            String[] targetTokens = splitString( target, delimiters );
177            if ( sourceTokens == null || targetTokens == null )
178                return null;
179            if ( sourceTokens.length == 0 || targetTokens.length == 0 )
180                return null;
181    
182            int lessTokens = 0;
183            if ( sourceTokens.length < targetTokens.length ) {
184                lessTokens = sourceTokens.length;
185            } else {
186                lessTokens = targetTokens.length;
187            }
188    
189            int counter = 0;
190            for ( counter = 0; counter < lessTokens; counter++ ) {
191                if ( !sourceTokens[counter].equals( targetTokens[counter] ) )
192                    break;
193            }
194    
195            StringBuffer buffer = new StringBuffer();
196            for ( int i = counter; i < sourceTokens.length; i++ ) {
197                if ( i != sourceTokens.length - 1 ) {
198                    buffer.append( "../" );
199                } else {
200                    // We are checking if the last token in the source String is a file or a directory
201                    // if its a file we don'tn write it
202                    File sourceFile = new File( source );
203                    if ( sourceFile.isDirectory() ) {
204                        buffer.append( "../" );
205                    }
206                }
207    
208            }
209    
210            // This is used when the target is only one token different/larger than the source, so we
211            // just take
212            // the last token in the target
213            if ( ( counter == sourceTokens.length ) && ( sourceTokens.length == targetTokens.length + 1 )
214                 && ( sourceTokens[counter - 1].equals( targetTokens[counter - 1] ) ) ) {
215                return targetTokens[targetTokens.length - 1];
216            }
217            for ( int i = counter; i < targetTokens.length; i++ ) {
218                if ( buffer.length() == 0 ) {
219                    // This is the first token in the path
220                    buffer.append( "./" );
221                }
222                buffer.append( targetTokens[i] );
223                if ( i != targetTokens.length - 1 ) {
224                    buffer.append( "/" );
225                }
226    
227            }
228    
229            return buffer.toString();
230        }
231    
232        static class Delimiter {
233            int index;
234    
235            String value;
236    
237            int foundAt;
238    
239            /**
240             * @param index
241             * @param foundAt
242             * @param value
243             */
244            public Delimiter( int index, int foundAt, String value ) {
245                this.index = index;
246                this.value = value;
247                this.foundAt = foundAt;
248            }
249    
250            /**
251             * @return int
252             */
253            public int getIndex() {
254                return index;
255            }
256    
257            /**
258             * @param index
259             */
260            public void setIndex( int index ) {
261                this.index = index;
262            }
263    
264            /**
265             * @return String
266             */
267            public String getValue() {
268                return value;
269            }
270    
271            /**
272             * @param value
273             */
274            public void setValue( String value ) {
275                this.value = value;
276            }
277    
278            /**
279             * @return int
280             */
281            public int getFoundAt() {
282                return foundAt;
283            }
284    
285            /**
286             * @param foundAt
287             */
288            public void setFoundAt( int foundAt ) {
289                this.foundAt = foundAt;
290            }
291        }
292    
293    }