001    //$HeadURL: http://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/security/drm/model/RightSet.java $
002    /*----------------------------------------------------------------------------
003     This file is part of deegree, http://deegree.org/
004     Copyright (C) 2001-2009 by:
005     Department of Geography, University of Bonn
006     and
007     lat/lon GmbH
008    
009     This library is free software; you can redistribute it and/or modify it under
010     the terms of the GNU Lesser General Public License as published by the Free
011     Software Foundation; either version 2.1 of the License, or (at your option)
012     any later version.
013     This library is distributed in the hope that it will be useful, but WITHOUT
014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016     details.
017     You should have received a copy of the GNU Lesser General Public License
018     along with this library; if not, write to the Free Software Foundation, Inc.,
019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020    
021     Contact information:
022    
023     lat/lon GmbH
024     Aennchenstr. 19, 53177 Bonn
025     Germany
026     http://lat-lon.de/
027    
028     Department of Geography, University of Bonn
029     Prof. Dr. Klaus Greve
030     Postfach 1147, 53001 Bonn
031     Germany
032     http://www.geographie.uni-bonn.de/deegree/
033    
034     e-mail: info@deegree.org
035     ----------------------------------------------------------------------------*/
036    package org.deegree.security.drm.model;
037    
038    import java.util.ArrayList;
039    import java.util.HashMap;
040    import java.util.Iterator;
041    import java.util.Map;
042    
043    import org.deegree.model.feature.Feature;
044    import org.deegree.security.GeneralSecurityException;
045    
046    /**
047     * A <code>RightSet</code> encapsulates a number of <code>Right</code> objects. This are grouped by the
048     * <code>SecurableObject</code> for which they apply to support an efficient implementation of the merge()-operation.
049     * The merge()-operation results in a <code>RightSet</code> that contains the logical rights of boths sets, but only one
050     * <code>Right</code> object of each <code>RightType</code> (and <code>SecurableObject</code>). This is accomplished by
051     * merging the constraints of the <code>Rights</code> of the same type (and object).
052     * 
053     * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider </a>
054     * @version $Revision: 32121 $
055     */
056    public class RightSet {
057    
058        // keys are SecurableObjects (for which the rights are defined), values
059        // are Maps (keys are RightTypes, values are Rights)
060        private Map<SecurableObject, Map<RightType, Right>> secObjects = new HashMap<SecurableObject, Map<RightType, Right>>();
061    
062        private boolean isEmpty;
063    
064        RightSet() {
065        }
066    
067        /**
068         * @param rights
069         */
070        public RightSet( Right[] rights ) {
071            this.isEmpty = rights == null || rights.length == 0;
072            for ( int i = 0; i < rights.length; i++ ) {
073                Map<RightType, Right> rightMap = secObjects.get( rights[i].getSecurableObject() );
074                if ( rightMap == null ) {
075                    rightMap = new HashMap<RightType, Right>();
076                }
077                rightMap.put( rights[i].getType(), rights[i] );
078                secObjects.put( rights[i].getSecurableObject(), rightMap );
079            }
080        }
081    
082        public boolean isEmpty() {
083            return isEmpty;
084        }
085    
086        /**
087         * Checks if the <code>RightSet</code> contains the permissions for a <code>SecurableObject</code> and a concrete
088         * situation (the situation is represented by the given <code>Feature</code>).
089         * 
090         * @param object
091         * @param type
092         * @param situation
093         * @return true, if the right applies
094         * @throws GeneralSecurityException
095         */
096        public boolean applies( SecurableObject object, RightType type, Feature situation )
097                                throws GeneralSecurityException {
098            boolean applies = false;
099            Map<RightType, Right> rightMap = secObjects.get( object );
100            if ( rightMap != null ) {
101                Right right = rightMap.get( type );
102                if ( right != null ) {
103                    applies = right.applies( object, situation );
104                }
105            }
106            return applies;
107        }
108    
109        /**
110         * Checks if the <code>RightSet</code> contains the (unrestricted) permissions for a <code>SecurableObject</code>
111         * and a certain type of right.
112         * 
113         * @param object
114         * @param type
115         * @return true, if the right applies
116         */
117        public boolean applies( SecurableObject object, RightType type ) {
118            boolean applies = false;
119            Map<RightType, Right> rightMap = secObjects.get( object );
120            if ( rightMap != null ) {
121                Right right = rightMap.get( type );
122                if ( right != null ) {
123                    applies = right.applies( object );
124                }
125    
126            }
127            return applies;
128        }
129    
130        /**
131         * @param secObject
132         * @param type
133         * @return the <code>Right</code> of the specified <code>RightType</code> that this <code>RightSet</code> defines on
134         *         the specified <code>SecurableObject</code>.
135         */
136        public Right getRight( SecurableObject secObject, RightType type ) {
137            Right right = null;
138            if ( secObjects.get( secObject ) != null ) {
139                right = secObjects.get( secObject ).get( type );
140            }
141            return right;
142        }
143    
144        /**
145         * @param secObject
146         * @return the encapulated <code>Rights</code> (for one <code>SecurableObject</code>) as an one-dimensional array.
147         */
148        public Right[] toArray( SecurableObject secObject ) {
149            Right[] rights = new Right[0];
150            Map<RightType, Right> rightMap = secObjects.get( secObject );
151            if ( rightMap != null ) {
152                rights = rightMap.values().toArray( new Right[rightMap.size()] );
153            }
154            return rights;
155        }
156    
157        /**
158         * @return the encapulated <code>Rights</code> as a two-dimensional array:
159         *         <ul>
160         *         <li>first index: runs the different <code>SecurableObjects</code>
161         *         <li>second index: runs the different <code>Rights</code>
162         *         </ul>
163         */
164        public Right[][] toArray2() {
165            ArrayList<Right[]> secObjectList = new ArrayList<Right[]>();
166            Iterator<Map<RightType, Right>> it = secObjects.values().iterator();
167            while ( it.hasNext() ) {
168                Map<RightType, Right> rightMap = it.next();
169                Right[] rights = rightMap.values().toArray( new Right[rightMap.size()] );
170                secObjectList.add( rights );
171            }
172            return secObjectList.toArray( new Right[secObjectList.size()][] );
173        }
174    
175        /**
176         * Produces the logical disjunction of two <code>RightSets</code>.
177         * 
178         * @param that
179         * @return the new right set
180         */
181        public RightSet merge( RightSet that ) {
182    
183            ArrayList<Right> mergedRights = new ArrayList<Right>( 20 );
184            Iterator<SecurableObject> secObjectsIt = this.secObjects.keySet().iterator();
185    
186            // add all rights from 'this' (and merge them with corresponding right
187            // from 'that')
188            while ( secObjectsIt.hasNext() ) {
189                SecurableObject secObject = secObjectsIt.next();
190                Map<RightType, Right> thisRightMap = this.secObjects.get( secObject );
191                Map<RightType, Right> thatRightMap = that.secObjects.get( secObject );
192                Iterator<RightType> rightIt = ( thisRightMap ).keySet().iterator();
193                while ( rightIt.hasNext() ) {
194                    RightType type = rightIt.next();
195                    Right mergedRight = thisRightMap.get( type );
196    
197                    // find corresponding Right (if any) in the other RightSet
198                    if ( thatRightMap != null && thatRightMap.get( type ) != null ) {
199                        try {
200                            mergedRight = mergedRight.merge( thatRightMap.get( type ) );
201                        } catch ( GeneralSecurityException e ) {
202                            e.printStackTrace();
203                        }
204                    }
205                    mergedRights.add( mergedRight );
206                }
207            }
208    
209            // add role rights from 'that'
210            secObjectsIt = that.secObjects.keySet().iterator();
211            while ( secObjectsIt.hasNext() ) {
212                SecurableObject secObject = secObjectsIt.next();
213                Map<RightType, Right> thisRightMap = this.secObjects.get( secObject );
214                Map<RightType, Right> thatRightMap = that.secObjects.get( secObject );
215    
216                Iterator<RightType> it = thatRightMap.keySet().iterator();
217                while ( it.hasNext() ) {
218                    Object o = it.next();
219                    RightType type = (RightType) o;
220                    // find corresponding Right (if none, add)
221                    if ( thisRightMap == null || thisRightMap.get( type ) == null ) {
222                        mergedRights.add( thatRightMap.get( type ) );
223                    }
224                }
225            }
226            return new RightSet( mergedRights.toArray( new Right[mergedRights.size()] ) );
227        }
228    
229        @Override
230        public String toString() {
231            StringBuffer sb = new StringBuffer( "RightSet:" );
232            Iterator<SecurableObject> it = secObjects.keySet().iterator();
233            while ( it.hasNext() ) {
234                SecurableObject secObject = it.next();
235                sb.append( "on SecurableObject " ).append( secObject ).append( "\n" );
236                Map<RightType, Right> rightMap = secObjects.get( secObject );
237                Iterator<RightType> rights = rightMap.keySet().iterator();
238                while ( rights.hasNext() ) {
239                    RightType rightType = rights.next();
240                    sb.append( "- Right " ).append( rightMap.get( rightType ) ).append( "\n" );
241                }
242            }
243            return sb.toString();
244        }
245    
246    }