Changeset 3299


Ignore:
Timestamp:
08/07/13 16:29:01 (11 years ago)
Author:
olhsha
Message:

source Dao is tested: get, retrieve lists, delete, add. Still to test: getSourceInfos and constructNewOrExistingSourceInfo

Location:
DASISH/t5.6/backend/annotator-backend/trunk/annotator-backend/src
Files:
1 added
9 edited

Legend:

Unmodified
Added
Removed
  • DASISH/t5.6/backend/annotator-backend/trunk/annotator-backend/src/main/java/eu/dasish/annotation/backend/dao/SourceDao.java

    r3298 r3299  
    8585   
    8686    public NewOrExistingSourceInfos contructNewOrExistingSourceInfo(List<SourceInfo> sourceInfoList);
     87   
     88    /**
     89     *
     90     * @param sourceID
     91     * @return delete all the rows in "sources_versions" table with sourceID
     92     */
     93    public int deleteSourceVersionRows(Number sourceID);
    8794       
    8895}
  • DASISH/t5.6/backend/annotator-backend/trunk/annotator-backend/src/main/java/eu/dasish/annotation/backend/dao/VersionDao.java

    r3298 r3299  
    6868    public Version addVersion(Version version);
    6969   
    70 
    71    
     70    /**
     71     *
     72     * @param versionID
     73     * @return removes the rows (versionID, some cached representation id) from the joint table "versions_cached_representations"
     74     */
     75    public int deleteVersionCachedRepresentationRow(Number versionID);
    7276   
    7377}
  • DASISH/t5.6/backend/annotator-backend/trunk/annotator-backend/src/main/java/eu/dasish/annotation/backend/dao/impl/JdbcCachedRepresentationDao.java

    r3298 r3299  
    4444    @Override
    4545    public CachedRepresentationIdentifier getExternalID(Number internalID) {
    46       return new CachedRepresentationIdentifier(super.getExternalIdentifier(internalID));
     46        return new CachedRepresentationIdentifier(super.getExternalIdentifier(internalID));
    4747    }
    48    
     48
    4949    @Override
    5050    public CachedRepresentationInfo getCachedRepresentationInfo(Number internalID) {
     
    106106        final int affectedRows = getSimpleJdbcTemplate().update(sql, params);
    107107
    108         CachedRepresentationInfo cachedNew = makeFreshCopy(cached);
    109         cachedNew.setRef(externalIdentifier.toString());
    110 
    111         return cachedNew;
     108        if (affectedRows == 1) {
     109            CachedRepresentationInfo cachedNew = makeFreshCopy(cached);
     110            cachedNew.setRef(externalIdentifier.toString());
     111            return cachedNew;
     112        } else {
     113            return null;
     114        }
    112115    }
    113116
     
    118121        String sqlCheck = "SELECT " + cached_representation_id + " FROM " + versionsCachedRepresentationsTableName + " WHERE " + cached_representation_id + "= ?";
    119122        List<Number> result = getSimpleJdbcTemplate().query(sqlCheck, cachedRepresentationCheckerRowMapper, internalID);
    120        
     123
    121124        if (result.isEmpty()) {
    122125            // rou can remove the cached representation
     
    128131        }
    129132    }
    130    
    131133    private final RowMapper<Number> cachedRepresentationCheckerRowMapper = new RowMapper<Number>() {
    132134        @Override
     
    136138        }
    137139    };
    138 
    139    
    140    
    141140
    142141    ////////// Helpers ///////////////////
  • DASISH/t5.6/backend/annotator-backend/trunk/annotator-backend/src/main/java/eu/dasish/annotation/backend/dao/impl/JdbcResourceDao.java

    r3298 r3299  
    192192       
    193193        if (vals == null) {
    194             return "()";
     194            return null;
    195195        }
    196196       
    197197        if (vals.isEmpty()) {           
    198             return "()";
     198            return null;
    199199        }
    200200       
  • DASISH/t5.6/backend/annotator-backend/trunk/annotator-backend/src/main/java/eu/dasish/annotation/backend/dao/impl/JdbcSourceDao.java

    r3298 r3299  
    2121import eu.dasish.annotation.backend.dao.VersionDao;
    2222import eu.dasish.annotation.backend.identifiers.SourceIdentifier;
     23import eu.dasish.annotation.backend.identifiers.VersionIdentifier;
    2324import eu.dasish.annotation.schema.NewOrExistingSourceInfo;
    2425import eu.dasish.annotation.schema.NewOrExistingSourceInfos;
     
    2829import java.sql.SQLException;
    2930import java.util.ArrayList;
     31import java.util.Date;
     32import java.util.GregorianCalendar;
    3033import java.util.HashMap;
    3134import java.util.List;
     
    4245 * @author olhsha
    4346 */
    44 public class JdbcSourceDao extends JdbcResourceDao implements SourceDao{
    45    
     47public class JdbcSourceDao extends JdbcResourceDao implements SourceDao {
     48
    4649    @Autowired
    4750    VersionDao versionDao;
    48    
    49      public JdbcSourceDao(DataSource dataSource) {
    50         setDataSource(dataSource);       
     51
     52    public JdbcSourceDao(DataSource dataSource) {
     53        setDataSource(dataSource);
    5154        internalIdName = source_id;
    5255        resourceTableName = sourceTableName;
    5356    }
    54    
    55      //////////////////////////////////////////////////////////////////////////////////////////////////////
     57
     58    //////////////////////////////////////////////////////////////////////////////////////////////////////
    5659    @Override
    5760    public SourceIdentifier getExternalID(Number internalID) {
    58       return new SourceIdentifier(super.getExternalIdentifier(internalID));
    59     }
    60    
    61  
    62     @Override
    63     public List<Number> retrieveSourceIDs(Number annotationID){
    64        String sql = "SELECT "+source_id+" FROM "+annotationsSourcesTableName+" WHERE "+annotation_id  +"= ?";
    65        List<Number> result= getSimpleJdbcTemplate().query(sql, annotationSourceRowMapper, annotationID);
    66        
    67        if (result == null) {
    68            return null;
    69        }
    70        if (result.isEmpty()) {
    71            return null;
    72        }
    73        return result;
    74      }
    75      
    76      private final RowMapper<Number> annotationSourceRowMapper = new RowMapper<Number>() {       
     61        return new SourceIdentifier(super.getExternalIdentifier(internalID));
     62    }
     63
     64    @Override
     65    public List<Number> retrieveSourceIDs(Number annotationID) {
     66        String sql = "SELECT " + source_id + " FROM " + annotationsSourcesTableName + " WHERE " + annotation_id + "= ?";
     67        List<Number> result = getSimpleJdbcTemplate().query(sql, annotationSourceRowMapper, annotationID);
     68
     69        if (result == null) {
     70            return null;
     71        }
     72        if (result.isEmpty()) {
     73            return null;
     74        }
     75        return result;
     76    }
     77    private final RowMapper<Number> annotationSourceRowMapper = new RowMapper<Number>() {
    7778        @Override
    7879        public Number mapRow(ResultSet rs, int rowNumber) throws SQLException {
     
    8081            return result;
    8182        }
    82      };
    83    
     83    };
     84
    8485    ///////////////////////////////////////////////////////////////////////////////
    8586    @Override
    8687    public Source getSource(Number internalID) {
    87        String sql = "SELECT "+sourceStar+"FROM "+sourceTableName+" WHERE "+source_id  +" = ?";
    88        List<Source> result= getSimpleJdbcTemplate().query(sql, SourceRowMapper, internalID);       
    89        return result.get(0);
    90     }
    91    
    92       private final RowMapper<Source> SourceRowMapper = new RowMapper<Source>() {       
    93         @Override
    94         public Source mapRow(ResultSet rs, int rowNumber) throws SQLException {           
     88        String sql = "SELECT " + sourceStar + "FROM " + sourceTableName + " WHERE " + source_id + " = ?";
     89        List<Source> result = getSimpleJdbcTemplate().query(sql, SourceRowMapper, internalID);
     90        return result.get(0);
     91    }
     92    private final RowMapper<Source> SourceRowMapper = new RowMapper<Source>() {
     93        @Override
     94        public Source mapRow(ResultSet rs, int rowNumber) throws SQLException {
    9595            try {
    96                 Source result = constructSource(new SourceIdentifier(rs.getString(external_id)), rs.getString(link_uri), rs.getString(version), rs.getString(time_stamp));
     96
     97                Date date = rs.getDate(time_stamp);
     98                GregorianCalendar c = new GregorianCalendar();
     99                c.setTime(date);
     100                XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
     101
     102                Source result = constructSource(new SourceIdentifier(rs.getString(external_id)), rs.getString(link_uri),
     103                        versionDao.getExternalID(rs.getInt(version_id)), xmlDate);
    97104                return result;
    98             }
    99             catch (DatatypeConfigurationException e) {
     105            } catch (DatatypeConfigurationException e) {
    100106                // TODO: what logger are we going to use
    101107                System.out.println("Cannot construct time stam: probably worng date/time format");
     
    103109            }
    104110        }
    105     }; 
    106    
    107      ///////////////////////////////////////////////////////////////////
    108     @Override
    109     public int deleteSource(Number internalID){
    110        
     111    };
     112
     113    ///////////////////////////////////////////////////////////////////
     114    @Override
     115    public int deleteSource(Number internalID) {
     116
    111117        // check if there are annotations referring to the source with "internalID", in the table "annotations_sources"
    112118        String sqlAnnotationsSources = "SELECT " + annotation_id + " FROM " + annotationsSourcesTableName + " WHERE " + source_id + "= ?";
    113119        List<Number> resultAnnotationsSources = getSimpleJdbcTemplate().query(sqlAnnotationsSources, annotationsSourcesRowMapper, internalID);
    114        
     120
    115121        if (resultAnnotationsSources.isEmpty()) {
    116122
     
    120126            List<Number> versions = versionDao.retrieveVersionList(internalID);
    121127
    122             // remove all the pairs (internalID, version_id) from the joint table       
    123             String sqlSourcesVersions = "DELETE FROM " + sourcesVersionsTableName + " where " + source_id + " = ?";
    124             int affected_sources_versions_rows = getSimpleJdbcTemplate().update(sqlSourcesVersions, internalID);
    125 
     128            // remove all the pairs (internalID, version_id) from the joint table
     129            deleteSourceVersionRows(internalID);
    126130            // the main action: remove the source with internalID from "source" table
    127131            String sql = "DELETE FROM " + sourceTableName + " where " + source_id + " = ?";
     
    139143        }
    140144    }
    141    
    142145    private final RowMapper<Number> annotationsSourcesRowMapper = new RowMapper<Number>() {
    143146        @Override
     
    147150        }
    148151    };
    149    
    150    
    151      ///////////////////////////////////////////////////////////////////
    152     @Override
    153     public Source addSource(Source freshSource){
    154        
     152
     153    ///////////////////////////////////////////////////////////////////
     154    @Override
     155    public Source addSource(Source freshSource) {
     156
    155157        SourceIdentifier externalIdentifier = new SourceIdentifier();
    156158
     
    168170        int affectedRowsJoint = getSimpleJdbcTemplate().update(sqlSourceVersion, paramsJoint);
    169171       
    170         Source result = makeFreshCopy(freshSource);
    171         result.setURI(externalIdentifier.toString());
    172 
    173         return result;
    174    
    175     }
    176    
    177    
     172        if (affectedRows == 1 && affectedRowsJoint == 1) {
     173            Source result = makeFreshCopy(freshSource);
     174            result.setURI(externalIdentifier.toString());
     175            return result;
     176        } else {
     177            return null;
     178        }
     179
     180    }
     181
    178182    ////////////////////////////////////////////////////////////////
    179      ///////////////////////////////////////////////////////////////////
    180     @Override
    181     public List<SourceInfo> getSourceInfos(Number annotationID){
    182        String sourceIDs = makeListOfValues(retrieveSourceIDs(annotationID));
    183        String sql = "SELECT "+external_id+","+ link_uri +"," + version+"FROM "+sourceTableName+" WHERE "+source_id  +" IN "+sourceIDs;
    184        List<SourceInfo> result= getSimpleJdbcTemplate().query(sql, SourceInfoRowMapper);       
    185        return result;
    186     }
    187    
    188       private final RowMapper<SourceInfo> SourceInfoRowMapper = new RowMapper<SourceInfo>() {       
     183    ///////////////////////////////////////////////////////////////////
     184    @Override
     185    public List<SourceInfo> getSourceInfos(Number annotationID) {
     186        List<Number> sources = retrieveSourceIDs(annotationID);
     187        if (sources == null) {
     188            return null;
     189        }
     190        if (sources.isEmpty()) {
     191            return new ArrayList<SourceInfo>();
     192        }
     193       
     194        String sourceIDs = makeListOfValues(sources);
     195        String sql = "SELECT " + external_id + "," + link_uri + "," + version_id + " FROM " + sourceTableName + " WHERE " + source_id + " IN " + sourceIDs;
     196        List<SourceInfo> result = getSimpleJdbcTemplate().query(sql, SourceInfoRowMapper);
     197        return result;
     198    }
     199    private final RowMapper<SourceInfo> SourceInfoRowMapper = new RowMapper<SourceInfo>() {
    189200        @Override
    190201        public SourceInfo mapRow(ResultSet rs, int rowNumber) throws SQLException {
    191           return constructSourceInfo(new SourceIdentifier(rs.getString(external_id)), rs.getString(link_uri), rs.getString(version));
    192         }
    193     };
    194    
    195    
     202            return constructSourceInfo(new SourceIdentifier(rs.getString(external_id)), rs.getString(link_uri), versionDao.getExternalID(rs.getInt(version_id)));
     203        }
     204    };
     205
    196206    //////////////////////////////////////////
    197207    @Override
    198     public NewOrExistingSourceInfos contructNewOrExistingSourceInfo(List<SourceInfo> sourceInfoList){
    199            List<NewOrExistingSourceInfo> noeSourceInfoList = new ArrayList<NewOrExistingSourceInfo>();
    200            for (SourceInfo sourceInfo: sourceInfoList) {
    201                 NewOrExistingSourceInfo noeSourceInfo = new NewOrExistingSourceInfo();
    202                 noeSourceInfo.setSource(sourceInfo);
    203                 noeSourceInfoList.add(noeSourceInfo);
    204            }   
    205            NewOrExistingSourceInfos result = new  NewOrExistingSourceInfos();
    206            result.getTarget().addAll(noeSourceInfoList);
    207            return result;
    208      }
    209    
    210      
    211      
     208    public NewOrExistingSourceInfos contructNewOrExistingSourceInfo(List<SourceInfo> sourceInfoList) {
     209        List<NewOrExistingSourceInfo> noeSourceInfoList = new ArrayList<NewOrExistingSourceInfo>();
     210        for (SourceInfo sourceInfo : sourceInfoList) {
     211            NewOrExistingSourceInfo noeSourceInfo = new NewOrExistingSourceInfo();
     212            noeSourceInfo.setSource(sourceInfo);
     213            noeSourceInfoList.add(noeSourceInfo);
     214        }
     215        NewOrExistingSourceInfos result = new NewOrExistingSourceInfos();
     216        result.getTarget().addAll(noeSourceInfoList);
     217        return result;
     218    }
     219
     220    /////////////////////////////////////////////////
     221    @Override
     222    public int deleteSourceVersionRows(Number sourceID) {
     223        // remove all the pairs (internalID, version_id) from the joint table       
     224        String sqlSourcesVersions = "DELETE FROM " + sourcesVersionsTableName + " where " + source_id + " = ?";
     225        return (getSimpleJdbcTemplate().update(sqlSourcesVersions, sourceID));
     226
     227    }
     228
    212229    //////// HELPERS //////////////////////
    213    
    214  
    215230    ////////////////////////////////////////////////////////
    216     private SourceInfo constructSourceInfo(SourceIdentifier sourceIdentifier, String link, String version){
     231    private SourceInfo constructSourceInfo(SourceIdentifier sourceIdentifier, String link, VersionIdentifier versionIdentifier) {
    217232        SourceInfo sourceInfo = new SourceInfo();
    218233        sourceInfo.setRef(sourceIdentifier.toString());
    219234        sourceInfo.setLink(link);
    220         sourceInfo.setVersion(version);
     235        sourceInfo.setVersion(versionIdentifier.toString());
    221236        return sourceInfo;
    222237    }
    223    
    224     private Source constructSource(SourceIdentifier sourceIdentifier, String link, String version, String timeStamp) throws DatatypeConfigurationException{
    225         Source source = new Source();         
    226         XMLGregorianCalendar xmlTimeStamp = DatatypeFactory.newInstance().newXMLGregorianCalendar(timeStamp);
     238
     239    private Source constructSource(SourceIdentifier sourceIdentifier, String link, VersionIdentifier version, XMLGregorianCalendar xmlTimeStamp) {
     240        Source source = new Source();
    227241        source.setURI(sourceIdentifier.toString());
    228242        source.setTimeSatmp(xmlTimeStamp);
    229243        source.setLink(link);
    230         source.setVersion(version);
     244        source.setVersion(version.toString());
     245
    231246        return source;
    232247    }
    233    
    234      private Source makeFreshCopy(Source source) {
     248
     249    private Source makeFreshCopy(Source source) {
    235250        Source result = new Source();
    236251        result.setLink(source.getLink());
  • DASISH/t5.6/backend/annotator-backend/trunk/annotator-backend/src/main/java/eu/dasish/annotation/backend/dao/impl/JdbcVersionDao.java

    r3298 r3299  
    9494    };
    9595
     96    /////////////////////////////////////////
     97    @Override
     98    public int deleteVersionCachedRepresentationRow(Number versionID) {
     99        // remove all the pairs (internalID, cached_representation) from the joint table       
     100        String sqlVersionsCachedRepresentations = "DELETE FROM " + versionsCachedRepresentationsTableName + " where " + version_id + " = ?";
     101        return (getSimpleJdbcTemplate().update(sqlVersionsCachedRepresentations, versionID));
     102    }
     103
    96104    /////////////////////////////////////////
    97105    //TODO: refactor ???
     
    102110        String sqlSourcesVersions = "SELECT " + source_id + " FROM " + sourcesVersionsTableName + " WHERE " + version_id + "= ?";
    103111        List<Number> resultSourcesVersions = getSimpleJdbcTemplate().query(sqlSourcesVersions, sourcesVersionsRowMapper, internalID);
    104        
     112
    105113        // check if there is a source referring to the version "intrenalID", in the table "source"
    106114        String sqlSource = "SELECT " + source_id + " FROM " + sourceTableName + " WHERE " + version_id + "= ?";
    107115        List<Number> resultSource = getSimpleJdbcTemplate().query(sqlSource, sourceRowMapper, internalID);
    108        
     116
    109117
    110118        if (resultSourcesVersions.isEmpty() && resultSource.isEmpty()) {
     
    116124
    117125            // remove all the pairs (internalID, cached_representation) from the joint table       
    118             String sqlVersionsCachedRepresentations = "DELETE FROM " + versionsCachedRepresentationsTableName + " where " + version_id + " = ?";
    119             int affected_versions_cached_representations_rows = getSimpleJdbcTemplate().update(sqlVersionsCachedRepresentations, internalID);
     126            deleteVersionCachedRepresentationRow(internalID);
    120127
    121128            // the main action: remove the version with internalID from "version" table
     
    134141        }
    135142    }
    136      
    137    
    138143    private final RowMapper<Number> sourcesVersionsRowMapper = new RowMapper<Number>() {
    139144        @Override
     
    143148        }
    144149    };
    145    
    146    
    147150    private final RowMapper<Number> sourceRowMapper = new RowMapper<Number>() {
    148151        @Override
     
    152155        }
    153156    };
    154    
    155157
    156158    /////////////////////////////////////////////////
     
    166168        String sql = "INSERT INTO " + versionTableName + "(" + external_id + "," + version + " ) VALUES (:externalId, :version)";
    167169        final int affectedRows = getSimpleJdbcTemplate().update(sql, params);
    168         Version versionAdded = makeFreshCopy(freshVersion);
    169         // TODO change for external identifier when the shcem is fixed
    170         versionAdded.setVersion(newExternalIdentifier);
    171         return versionAdded;
     170
     171        if (affectedRows == 1) {
     172            Version versionAdded = makeFreshCopy(freshVersion);
     173            // TODO change for external identifier when the shcem is fixed
     174            versionAdded.setVersion(newExternalIdentifier);
     175            return versionAdded;
     176        } else {
     177            return null;
     178        }
    172179    }
    173 
    174    
    175 
    176180
    177181    private Version makeFreshCopy(Version version) {
  • DASISH/t5.6/backend/annotator-backend/trunk/annotator-backend/src/test/java/eu/dasish/annotation/backend/TestBackendConstants.java

    r3247 r3299  
    8989   
    9090    public static final String _TEST_VERSION_1_EXT_ID = "00000000-0000-0000-0000-000000000041";
     91    public static final String _TEST_VERSION_2_EXT_ID = "00000000-0000-0000-0000-000000000042";
     92    public static final String _TEST_VERSION_3_EXT_ID = "00000000-0000-0000-0000-000000000043";
    9193}
    9294
  • DASISH/t5.6/backend/annotator-backend/trunk/annotator-backend/src/test/java/eu/dasish/annotation/backend/dao/impl/JdbcVersionDaoTest.java

    r3298 r3299  
    104104    }
    105105
     106     /**
     107     * Test of deleteVersionCachedRepresentationRows method, of class JdbcVersionDao.
     108     */
     109    @Test
     110    public void testDeleteVersionCachedRepresentationRows() {
     111        System.out.println("deleteVersion");
     112        Number internalID = 6; // there is no sources (in target_source and sources_versions - sibling table) connected to this version in the test table
     113        int result = jdbcVersionDao.deleteVersionCachedRepresentationRow(internalID);
     114        assertEquals(1, result);
     115    }
     116   
    106117    /**
    107118     * Test of deleteVersion method, of class JdbcVersionDao.
     
    110121    public void testDeleteVersion() {
    111122        System.out.println("deleteVersion");
    112         final Number internalID = 5; // there is no sources (in target_source and sources_versions - sibling table) connected to this version in the test table
     123        final Number internalID = 6; // there is no sources (in target_source and sources_versions - sibling table) connected to this version in the test table
    113124        final Number cachedID =5;
    114125        final List<Number> versions = new ArrayList<Number>();
  • DASISH/t5.6/backend/annotator-backend/trunk/annotator-backend/src/test/resources/test-data/InsertTestData.sql

    r3297 r3299  
    6767INSERT INTO version (external_id, version) VALUES ('00000000-0000-0000-0000-000000000043', 'Gaudi wiki -version 2013'); -- 3
    6868INSERT INTO version (external_id, version) VALUES ('00000000-0000-0000-0000-000000000044', 'Art Nuveau wiki -version 2013'); --4
    69 INSERT INTO version (external_id, version) VALUES ('00000000-0000-0000-0000-000000000045', 'Art Nuveau wiki -version 2012'); --5 not used
     69INSERT INTO version (external_id, version) VALUES ('00000000-0000-0000-0000-000000000045', 'Art Nuveau wiki -version 2012'); --5
    7070INSERT INTO version (external_id, version) VALUES ('00000000-0000-0000-0000-000000000046', 'Art Nuveau wiki -version 2011'); --6  not used
    7171
     
    8484INSERT INTO target_source (external_id, link_uri, version_id) VALUES ('00000000-0000-0000-0000-000000000032', 'http://nl.wikipedia.org/wiki/Antoni_Gaud%C3%AD', 3); --2
    8585INSERT INTO target_source (external_id, link_uri, version_id) VALUES ('00000000-0000-0000-0000-000000000033', 'http://en.wikipedia.org/wiki/Art_Nouveau', 4); --3
     86INSERT INTO target_source (external_id, link_uri, version_id) VALUES ('00000000-0000-0000-0000-000000000034', '???', 5); --4
    8687
    8788-- CREATE TABLE annotations_target_sources (
     
    9596INSERT INTO annotations_target_sources (annotation_id, source_id) VALUES (3, 2);
    9697INSERT INTO annotations_target_sources (annotation_id, source_id) VALUES (4, 3);
    97 
    9898
    9999----------------------------------------------------------------
     
    109109INSERT INTO sources_versions (source_id, version_id) VALUES (2, 3);
    110110INSERT INTO sources_versions (source_id, version_id) VALUES (3, 4);
     111INSERT INTO sources_versions (source_id, version_id) VALUES (4, 5);
    111112
    112113--------------------------------------------------------------
     
    144145INSERT INTO versions_cached_representations (version_id, cached_representation_id) VALUES (4, 4);
    145146INSERT INTO versions_cached_representations (version_id, cached_representation_id) VALUES (1, 5);
    146 INSERT INTO versions_cached_representations (version_id, cached_representation_id) VALUES (5, 5);
     147INSERT INTO versions_cached_representations (version_id, cached_representation_id) VALUES (6, 5);
     148
    147149
    148150---- PERMISSIONS --------------------------------------------------------------------------------------------
Note: See TracChangeset for help on using the changeset viewer.