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