Coverage Report - org.kuali.student.kim.permission.mock.RoleServiceMockImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
RoleServiceMockImpl
0%
0/121
0%
0/72
2.352
 
 1  
 /*
 2  
  * Copyright 2011 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may        obtain a copy of the License at
 7  
  *
 8  
  *         http://www.osedu.org/licenses/ECL-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.kuali.student.kim.permission.mock;
 17  
 
 18  
 import java.util.*;
 19  
 import org.kuali.rice.kim.bo.Role;
 20  
 import org.kuali.rice.kim.bo.role.dto.DelegateMemberCompleteInfo;
 21  
 import org.kuali.rice.kim.bo.role.dto.DelegateTypeInfo;
 22  
 import org.kuali.rice.kim.bo.role.dto.KimRoleInfo;
 23  
 import org.kuali.rice.kim.bo.role.dto.RoleMemberCompleteInfo;
 24  
 import org.kuali.rice.kim.bo.role.dto.RoleMembershipInfo;
 25  
 import org.kuali.rice.kim.bo.role.dto.RoleResponsibilityActionInfo;
 26  
 import org.kuali.rice.kim.bo.role.dto.RoleResponsibilityInfo;
 27  
 import org.kuali.rice.kim.bo.types.dto.AttributeSet;
 28  
 import org.kuali.rice.kim.service.GroupService;
 29  
 import org.kuali.rice.kim.service.GroupUpdateService;
 30  
 import org.kuali.rice.kim.service.KimTypeInfoService;
 31  
 import org.kuali.rice.kim.service.RoleService;
 32  
 import org.kuali.rice.kim.service.RoleUpdateService;
 33  
 
 34  
 /**
 35  
  * @author nwright
 36  
  */
 37  0
 public class RoleServiceMockImpl implements
 38  
         RoleService,
 39  
         RoleUpdateService {
 40  
 
 41  0
     private transient Map<String, KimRoleInfo> roleCache = new HashMap<String, KimRoleInfo>();
 42  0
     private transient Map<String, RoleMembershipInfo> roleMembershipCache = new HashMap<String, RoleMembershipInfo>();
 43  0
     private transient Map<String, RoleMemberCompleteInfo> roleMemberCompleteInfoCache = new HashMap<String, RoleMemberCompleteInfo>();
 44  
     private GroupService groupService;
 45  
     private GroupUpdateService groupUpdateService;
 46  
     private KimTypeInfoService kimTypeInfoService;
 47  
 
 48  
     public GroupService getGroupService() {
 49  0
         return groupService;
 50  
     }
 51  
 
 52  
     public void setGroupService(GroupService groupService) {
 53  0
         this.groupService = groupService;
 54  0
     }
 55  
 
 56  
     public KimTypeInfoService getKimTypeInfoService() {
 57  0
         return kimTypeInfoService;
 58  
     }
 59  
 
 60  
     public void setKimTypeInfoService(KimTypeInfoService kimTypeInfoService) {
 61  0
         this.kimTypeInfoService = kimTypeInfoService;
 62  0
     }
 63  
 
 64  
     /**
 65  
      * Get the KIM Role object with the given ID.
 66  
      *
 67  
      * If the roleId is blank, this method returns <code>null</code>.
 68  
      */
 69  
     @Override
 70  
     public KimRoleInfo getRole(String roleId) {
 71  0
         return roleCache.get(roleId);
 72  
     }
 73  
 
 74  
     /**
 75  
      * Get the KIM Role objects for the role IDs in the given List.
 76  
      */
 77  
     @Override
 78  
     public List<KimRoleInfo> getRoles(List<String> roleIds) {
 79  0
         List<KimRoleInfo> list = new ArrayList<KimRoleInfo>();
 80  0
         for (String roleId : roleIds) {
 81  0
             list.add(this.getRole(roleId));
 82  
         }
 83  0
         return list;
 84  
     }
 85  
 
 86  
     /**
 87  
      * Get the KIM Role object with the unique combination of namespace, component,
 88  
      * and role name.
 89  
      *
 90  
      * If any parameter is blank, this method returns <code>null</code>.
 91  
      */
 92  
     @Override
 93  
     public KimRoleInfo getRoleByName(String namespaceCode, String roleName) {
 94  0
         for (KimRoleInfo role : this.roleCache.values()) {
 95  0
             if (namespaceCode.equals(role.getNamespaceCode())) {
 96  0
                 if (roleName.equals(role.getRoleName())) {
 97  0
                     return role;
 98  
                 }
 99  
             }
 100  
         }
 101  0
         return null;
 102  
     }
 103  
 
 104  
     /**
 105  
      * Return the Role ID for the given unique combination of namespace,
 106  
      * component and role name.
 107  
      */
 108  
     @Override
 109  
     public String getRoleIdByName(String namespaceCode, String roleName) {
 110  0
         for (KimRoleInfo role : this.roleCache.values()) {
 111  0
             if (namespaceCode.equals(role.getNamespaceCode())) {
 112  0
                 if (roleName.equals(role.getRoleName())) {
 113  0
                     return role.getRoleId();
 114  
                 }
 115  
             }
 116  
         }
 117  0
         return null;
 118  
     }
 119  
 
 120  
     /**
 121  
      * Checks whether the role with the given role ID is active.
 122  
      *
 123  
      * @param roleId
 124  
      * @return
 125  
      */
 126  
     @Override
 127  
     public boolean isRoleActive(String roleId) {
 128  0
         return this.getRole(roleId).isActive();
 129  
     }
 130  
 
 131  
     /**
 132  
      * Returns a list of role qualifiers that the given principal has without taking into consideration
 133  
      * that the principal may be a member via an assigned group or role.  Use in situations where
 134  
      * you are only interested in the qualifiers that are directly assigned to the principal.
 135  
      */
 136  
     @Override
 137  
     public List<AttributeSet> getRoleQualifiersForPrincipal(String principalId, List<String> roleIds, AttributeSet qualification) {
 138  0
         throw new UnsupportedOperationException("Not supported Yet");
 139  
     }
 140  
 
 141  
     /**
 142  
      * Returns a list of role qualifiers that the given principal has without taking into consideration
 143  
      * that the principal may be a member via an assigned group or role.  Use in situations where
 144  
      * you are only interested in the qualifiers that are directly assigned to the principal.
 145  
      */
 146  
     @Override
 147  
     public List<AttributeSet> getRoleQualifiersForPrincipal(String principalId, String namespaceCode, String roleName, AttributeSet qualification) {
 148  0
         throw new UnsupportedOperationException("Not supported Yet");
 149  
     }
 150  
 
 151  
     /**
 152  
      * Returns a list of role qualifiers that the given principal.  If the principal's membership
 153  
      * is via a group or role, that group or role's qualifier on the given role is returned.
 154  
      */
 155  
     @Override
 156  
     public List<AttributeSet> getRoleQualifiersForPrincipalIncludingNested(String principalId, String namespaceCode, String roleName, AttributeSet qualification) {
 157  0
         throw new UnsupportedOperationException("Not supported Yet");
 158  
     }
 159  
 
 160  
     /**
 161  
      * Returns a list of role qualifiers that the given principal.  If the principal's membership
 162  
      * is via a group or role, that group or role's qualifier on the given role is returned.
 163  
      */
 164  
     @Override
 165  
     public List<AttributeSet> getRoleQualifiersForPrincipalIncludingNested(String principalId, List<String> roleIds, AttributeSet qualification) {
 166  0
         throw new UnsupportedOperationException("Not supported Yet");
 167  
     }
 168  
 
 169  
     // --------------------
 170  
     // Role Membership Checks
 171  
     // --------------------
 172  
     /**
 173  
      * Get all the role members (groups and principals) associated with the given list of roles
 174  
      * where their role membership/assignment matches the given qualification.
 175  
      *
 176  
      * The return object will have each membership relationship along with the delegations
 177  
      *
 178  
      */
 179  
     @Override
 180  
     public List<RoleMembershipInfo> getRoleMembers(List<String> roleIds, AttributeSet qualification) {
 181  0
         List<RoleMembershipInfo> list = new ArrayList<RoleMembershipInfo>();
 182  0
         for (RoleMembershipInfo info : this.roleMembershipCache.values()) {
 183  0
             if (roleIds.contains(info.getRoleId())) {
 184  0
                 if (matchesQualifiers(info, qualification)) {
 185  0
                     list.add(info);
 186  
                 }
 187  
             }
 188  
         }
 189  0
         return list;
 190  
     }
 191  
 
 192  
     private boolean matchesQualifiers(RoleMembershipInfo info, AttributeSet qualification) {
 193  
         // TODO: implement check
 194  0
         return true;
 195  
     }
 196  
 
 197  
     private Collection<String> getAllRoleMemberPrincipalIds(String roleId, AttributeSet qualification) {
 198  0
         Collection<String> principals = new ArrayList<String>();
 199  0
         for (RoleMembershipInfo info : this.roleMembershipCache.values()) {
 200  0
             if (roleId.equals(info.getRoleId())) {
 201  0
                 if (matchesQualifiers(info, qualification)) {
 202  0
                     if (info.getMemberTypeCode().equals(Role.PRINCIPAL_MEMBER_TYPE)) {
 203  0
                         principals.add(info.getMemberId());
 204  0
                     } else if (info.getMemberTypeCode().equals(Role.GROUP_MEMBER_TYPE)) {
 205  0
                         principals.addAll(groupService.getMemberPrincipalIds(info.getMemberId()));
 206  0
                     } else if (info.getMemberTypeCode().equals(Role.ROLE_MEMBER_TYPE)) {
 207  0
                         principals.addAll(this.getAllRoleMemberPrincipalIds(info.getMemberId(), qualification));
 208  
                     }
 209  
                 }
 210  
             }
 211  
         }
 212  0
         return principals;
 213  
     }
 214  
 
 215  
     /**
 216  
      * This method gets all the members, then traverses down into members of type role and group to obtain the nested principal ids
 217  
      *
 218  
      * @return list of member principal ids
 219  
      */
 220  
     @Override
 221  
     public Collection<String> getRoleMemberPrincipalIds(String namespaceCode, String roleName, AttributeSet qualification) {
 222  0
         KimRoleInfo roleInfo = this.getRoleByName(namespaceCode, roleName);
 223  0
         if (roleInfo == null) {
 224  0
             throw new IllegalArgumentException("role name not found");
 225  
         }
 226  0
         return this.getAllRoleMemberPrincipalIds(roleName, qualification);
 227  
     }
 228  
 
 229  
     private boolean principalHasThisRole(String principalId, String roleId, AttributeSet qualification) {
 230  0
         return (this.getAllRoleMemberPrincipalIds(roleId, qualification).contains(principalId));
 231  
     }
 232  
 
 233  
     /**
 234  
      * Returns whether the given principal has any of the passed role IDs with the given qualification.
 235  
      */
 236  
     @Override
 237  
     public boolean principalHasRole(String principalId, List<String> roleIds, AttributeSet qualification) {
 238  0
         for (String roleId : roleIds) {
 239  0
             if (this.principalHasThisRole(principalId, roleId, qualification)) {
 240  0
                 return true;
 241  
             }
 242  
         }
 243  0
         return false;
 244  
     }
 245  
 
 246  
     /**
 247  
      * Returns the subset of the given principal ID list which has the given role and qualification.
 248  
      * This is designed to be used by lookups of people by their roles.
 249  
      */
 250  
     @Override
 251  
     public List<String> getPrincipalIdSubListWithRole(List<String> principalIds,
 252  
             String roleNamespaceCode, String roleName, AttributeSet qualification) {
 253  0
         List<String> subList = new ArrayList<String>();
 254  0
         KimRoleInfo role = getRoleByName(roleNamespaceCode, roleName);
 255  0
         for (String principalId : principalIds) {
 256  0
             if (principalHasThisRole(principalId, role.getRoleId(), qualification)) {
 257  0
                 subList.add(principalId);
 258  
             }
 259  
         }
 260  0
         return subList;
 261  
     }
 262  
 
 263  
     /**
 264  
      *
 265  
      * This method get search results for role lookup
 266  
      */
 267  
     @Override
 268  
     public List<? extends Role> getRolesSearchResults(java.util.Map<String, String> fieldValues) {
 269  0
         throw new UnsupportedOperationException("Not supported Yet");
 270  
     }
 271  
 
 272  
     /**
 273  
      * Notifies all of a principal's roles and role types that the principal has been inactivated.
 274  
      */
 275  
     @Override
 276  
     public void principalInactivated(String principalId) {
 277  0
         for (RoleMembershipInfo membership : this.roleMembershipCache.values()) {
 278  0
             if (membership.getMemberTypeCode().equals(Role.PRINCIPAL_MEMBER_TYPE)) {
 279  0
                 if (principalId.equals(membership.getMemberId())) {
 280  0
                     this.roleMembershipCache.remove(membership.getRoleMemberId());
 281  
                 }
 282  
             }
 283  
         }
 284  0
     }
 285  
 
 286  
     /**
 287  
      * Notifies the role service that the role with the given id has been inactivated.
 288  
      */
 289  
     @Override
 290  
     public void roleInactivated(String roleId) {
 291  0
         for (RoleMembershipInfo membership : this.roleMembershipCache.values()) {
 292  0
             if (membership.getMemberTypeCode().equals(Role.ROLE_MEMBER_TYPE)) {
 293  0
                 if (roleId.equals(membership.getMemberId())) {
 294  0
                     this.roleMembershipCache.remove(membership.getRoleMemberId());
 295  
                 }
 296  0
                 if (roleId.equals(membership.getRoleId())) {
 297  0
                     this.roleMembershipCache.remove(membership.getRoleMemberId());
 298  
                 }
 299  
             }
 300  
         }
 301  0
         this.roleCache.remove(roleId);
 302  0
     }
 303  
 
 304  
     /**
 305  
      * Notifies the role service that the group with the given id has been inactivated.
 306  
      */
 307  
     @Override
 308  
     public void groupInactivated(String groupId) {
 309  0
         for (RoleMembershipInfo membership : this.roleMembershipCache.values()) {
 310  0
             if (membership.getMemberTypeCode().equals(Role.GROUP_MEMBER_TYPE)) {
 311  0
                 if (groupId.equals(membership.getMemberId())) {
 312  0
                     this.roleMembershipCache.remove(membership.getRoleMemberId());
 313  
                 }
 314  
             }
 315  
         }
 316  0
     }
 317  
 
 318  
     /**
 319  
      * Gets all direct members of the roles that have ids within the given list
 320  
      * of role ids.  This method does not recurse into any nested roles.
 321  
      *
 322  
      *  <p>The resulting List of role membership will contain membership for
 323  
      *  all the roles with the specified ids.  The list is not guaranteed to be
 324  
      *  in any particular order and may have membership info for the
 325  
      *  different roles interleaved with each other.
 326  
      */
 327  
     @Override
 328  
     public List<RoleMembershipInfo> getFirstLevelRoleMembers(List<String> roleIds) {
 329  0
         List<RoleMembershipInfo> list = new ArrayList<RoleMembershipInfo>();
 330  0
         for (RoleMembershipInfo membership : this.roleMembershipCache.values()) {
 331  0
             if (roleIds.contains(membership.getRoleId())) {
 332  0
                 this.roleMembershipCache.remove(membership.getRoleMemberId());
 333  
             }
 334  
         }
 335  0
         return list;
 336  
     }
 337  
 
 338  
     /**
 339  
      * Gets role member information based on the given search criteria.  The
 340  
      * map of criteria contains attributes of RoleMembershipInfo as it's
 341  
      * key and the values to search on as the value.
 342  
      */
 343  
     @Override
 344  
     public List<RoleMembershipInfo> findRoleMembers(java.util.Map<String, String> fieldValues) {
 345  0
         throw new UnsupportedOperationException("Not supported Yet");
 346  
     }
 347  
 
 348  
     /**
 349  
      *
 350  
      * Gets a list of Roles that the given member belongs to.
 351  
      *
 352  
      */
 353  
     @Override
 354  
     public List<String> getMemberParentRoleIds(String memberType, String memberId) {
 355  0
         List<String> list = new ArrayList<String>();
 356  0
         for (RoleMembershipInfo membership : this.roleMembershipCache.values()) {
 357  0
             if (memberType.equals(membership.getMemberTypeCode())) {
 358  0
                 if (memberId.equals(membership.getRoleMemberId())) {
 359  0
                     list.add(membership.getRoleId());
 360  
                 }
 361  
             }
 362  
         }
 363  0
         return list;
 364  
     }
 365  
 
 366  
     @Override
 367  
     public List<RoleMemberCompleteInfo> findRoleMembersCompleteInfo(java.util.Map<String, String> fieldValues) {
 368  0
         throw new UnsupportedOperationException("Not supported Yet");
 369  
     }
 370  
 
 371  
     @Override
 372  
     public List<DelegateMemberCompleteInfo> findDelegateMembersCompleteInfo(java.util.Map<String, String> fieldValues) {
 373  0
         throw new UnsupportedOperationException("Not supported Yet");
 374  
     }
 375  
 
 376  
     /**
 377  
      * Gets delegation member information based on the given search criteria.  The
 378  
      * map of criteria contains attributes of DelegateInfo as it's
 379  
      * key and the values to search on as the value.
 380  
      */
 381  
     @Override
 382  
     public List<DelegateMemberCompleteInfo> getDelegationMembersByDelegationId(String delegationId) {
 383  0
         throw new UnsupportedOperationException("Not supported Yet");
 384  
     }
 385  
 
 386  
     @Override
 387  
     public DelegateMemberCompleteInfo getDelegationMemberByDelegationAndMemberId(String delegationId, String memberId) {
 388  0
         throw new UnsupportedOperationException("Not supported Yet");
 389  
     }
 390  
 
 391  
     @Override
 392  
     public DelegateMemberCompleteInfo getDelegationMemberById(String delegationMemberId) {
 393  0
         throw new UnsupportedOperationException("Not supported Yet");
 394  
     }
 395  
 
 396  
     @Override
 397  
     public List<RoleResponsibilityInfo> getRoleResponsibilities(String roleId) {
 398  0
         throw new UnsupportedOperationException("Not supported Yet");
 399  
     }
 400  
 
 401  
     @Override
 402  
     public List<RoleResponsibilityActionInfo> getRoleMemberResponsibilityActionInfo(String roleMemberId) {
 403  0
         throw new UnsupportedOperationException("Not supported Yet");
 404  
     }
 405  
 
 406  
     @Override
 407  
     public DelegateTypeInfo getDelegateTypeInfo(String roleId, String delegationTypeCode) {
 408  0
         throw new UnsupportedOperationException("Not supported Yet");
 409  
     }
 410  
 
 411  
     @Override
 412  
     public DelegateTypeInfo getDelegateTypeInfoById(String delegationId) {
 413  0
         throw new UnsupportedOperationException("Not supported Yet");
 414  
     }
 415  
 
 416  
     @Override
 417  
     public void applicationRoleMembershipChanged(String roleId) {
 418  0
         throw new UnsupportedOperationException("Not supported Yet");
 419  
     }
 420  
 
 421  
     @Override
 422  
     public List<KimRoleInfo> lookupRoles(Map<String, String> searchCriteria) {
 423  0
         throw new UnsupportedOperationException("Not supported Yet");
 424  
     }
 425  
 
 426  
     /**
 427  
      * Flushes an internal role cache used by the base implementation to prevent repeated database I/O.
 428  
      */
 429  
     @Override
 430  
     public void flushInternalRoleCache() {
 431  0
         throw new UnsupportedOperationException("Not supported Yet");
 432  
     }
 433  
 
 434  
     /**
 435  
      * Flushes an internal role member cache used by the base implementation to prevent repeated database I/O.
 436  
      */
 437  
     @Override
 438  
     public void flushInternalRoleMemberCache() {
 439  0
         throw new UnsupportedOperationException("Not supported Yet");
 440  
     }
 441  
 
 442  
     /**
 443  
      * Flushes an internal delegation cache used by the base implementation to prevent repeated database I/O.
 444  
      */
 445  
     @Override
 446  
     public void flushInternalDelegationCache() {
 447  0
         throw new UnsupportedOperationException("Not supported Yet");
 448  
     }
 449  
 
 450  
     /**
 451  
      * Flushes an internal delegation member cache used by the base implementation to prevent repeated database I/O.
 452  
      */
 453  
     @Override
 454  
     public void flushInternalDelegationMemberCache() {
 455  0
         throw new UnsupportedOperationException("Not supported Yet");
 456  
     }
 457  
 
 458  
     @Override
 459  
     public void assignGroupToRole(String groupId, String namespaceCode,
 460  
             String roleName, AttributeSet qualifications)
 461  
             throws UnsupportedOperationException {
 462  0
         throw new UnsupportedOperationException("Not supported yet.");
 463  
     }
 464  
 
 465  
     @Override
 466  
     public void assignPermissionToRole(String permissionId, String roleId) throws UnsupportedOperationException {
 467  0
         throw new UnsupportedOperationException("Not supported yet.");
 468  
     }
 469  
 
 470  
     @Override
 471  
     public void assignPrincipalToRole(String principalId, String namespaceCode,
 472  
             String roleName, AttributeSet qualifications)
 473  
             throws UnsupportedOperationException {
 474  0
         throw new UnsupportedOperationException("Not supported yet.");
 475  
     }
 476  
 
 477  
     @Override
 478  
     public void assignRoleToRole(String roleId, String namespaceCode,
 479  
             String roleName, AttributeSet qualifications)
 480  
             throws UnsupportedOperationException {
 481  0
         throw new UnsupportedOperationException("Not supported yet.");
 482  
     }
 483  
 
 484  
     @Override
 485  
     public String getNextAvailableRoleId() throws UnsupportedOperationException {
 486  0
         throw new UnsupportedOperationException("Not supported yet.");
 487  
     }
 488  
 
 489  
     @Override
 490  
     public void removeGroupFromRole(String groupId, String namespaceCode,
 491  
             String roleName, AttributeSet qualifications)
 492  
             throws UnsupportedOperationException {
 493  0
         throw new UnsupportedOperationException("Not supported yet.");
 494  
     }
 495  
 
 496  
     @Override
 497  
     public void removePrincipalFromRole(String principalId, String namespaceCode,
 498  
             String roleName,
 499  
             AttributeSet qualifications) throws UnsupportedOperationException {
 500  0
         throw new UnsupportedOperationException("Not supported yet.");
 501  
     }
 502  
 
 503  
     @Override
 504  
     public void removeRoleFromRole(String roleId, String namespaceCode,
 505  
             String roleName, AttributeSet qualifications)
 506  
             throws UnsupportedOperationException {
 507  0
         throw new UnsupportedOperationException("Not supported yet.");
 508  
     }
 509  
 
 510  
     @Override
 511  
     public void saveDelegationMemberForRole(String delegationMemberId,
 512  
             String roleMemberId, String memberId,
 513  
             String memberTypeCode,
 514  
             String delegationTypeCode,
 515  
             String roleId,
 516  
             AttributeSet qualifications,
 517  
             java.sql.Date activeFromDate, java.sql.Date activeToDate)
 518  
             throws UnsupportedOperationException {
 519  0
         throw new UnsupportedOperationException("Not supported yet.");
 520  
     }
 521  
 
 522  
     @Override
 523  
     public void saveRole(String roleId, String roleName, String roleDescription,
 524  
             boolean active, String kimTypeId, String namespaceCode)
 525  
             throws UnsupportedOperationException {
 526  0
         throw new UnsupportedOperationException("Not supported yet.");
 527  
     }
 528  
 
 529  
     @Override
 530  
     public RoleMemberCompleteInfo saveRoleMemberForRole(String roleMemberId,
 531  
             String memberId,
 532  
             String memberTypeCode,
 533  
             String roleId,
 534  
             AttributeSet qualifications,
 535  
             java.sql.Date activeFromDate,
 536  
             java.sql.Date activeToDate) throws UnsupportedOperationException {
 537  0
         throw new UnsupportedOperationException("Not supported yet.");
 538  
     }
 539  
 
 540  
     @Override
 541  
     public void saveRoleRspActions(String roleResponsibilityActionId,
 542  
             String roleId, String roleResponsibilityId,
 543  
             String roleMemberId, String actionTypeCode,
 544  
             String actionPolicyCode, Integer priorityNumber,
 545  
             Boolean forceAction) {
 546  0
         throw new UnsupportedOperationException("Not supported yet.");
 547  
     }
 548  
 }
 549