Coverage Report - org.argouml.model.mdr.CollaborationsFactoryMDRImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
CollaborationsFactoryMDRImpl
4%
8/182
0%
0/76
2.6
 
 1  
 /* $Id: CollaborationsFactoryMDRImpl.java 18765 2010-09-18 23:15:32Z tfmorris $
 2  
  *****************************************************************************
 3  
  * Copyright (c) 2009,2010 Contributors - see below
 4  
  * All rights reserved. This program and the accompanying materials
 5  
  * are made available under the terms of the Eclipse Public License v1.0
 6  
  * which accompanies this distribution, and is available at
 7  
  * http://www.eclipse.org/legal/epl-v10.html
 8  
  *
 9  
  * Contributors:
 10  
  *    bobtarling
 11  
  *    Tom Morris
 12  
  *****************************************************************************
 13  
  *
 14  
  * Some portions of this file was previously release using the BSD License:
 15  
  */
 16  
 
 17  
 // Copyright (c) 1996-2007 The Regents of the University of California. All
 18  
 // Rights Reserved. Permission to use, copy, modify, and distribute this
 19  
 // software and its documentation without fee, and without a written
 20  
 // agreement is hereby granted, provided that the above copyright notice
 21  
 // and this paragraph appear in all copies.  This software program and
 22  
 // documentation are copyrighted by The Regents of the University of
 23  
 // California. The software program and documentation are supplied "AS
 24  
 // IS", without any accompanying services from The Regents. The Regents
 25  
 // does not warrant that the operation of the program will be
 26  
 // uninterrupted or error-free. The end-user understands that the program
 27  
 // was developed for research purposes and is advised not to rely
 28  
 // exclusively on the program for any reason.  IN NO EVENT SHALL THE
 29  
 // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
 30  
 // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
 31  
 // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
 32  
 // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
 33  
 // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
 34  
 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 35  
 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
 36  
 // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
 37  
 // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
 38  
 // UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 39  
 
 40  
 package org.argouml.model.mdr;
 41  
 
 42  
 import java.util.Collection;
 43  
 import java.util.Iterator;
 44  
 
 45  
 import javax.jmi.reflect.InvalidObjectException;
 46  
 
 47  
 import org.argouml.model.CollaborationsFactory;
 48  
 import org.argouml.model.InvalidElementException;
 49  
 import org.argouml.model.Model;
 50  
 import org.omg.uml.behavioralelements.collaborations.AssociationEndRole;
 51  
 import org.omg.uml.behavioralelements.collaborations.AssociationRole;
 52  
 import org.omg.uml.behavioralelements.collaborations.ClassifierRole;
 53  
 import org.omg.uml.behavioralelements.collaborations.Collaboration;
 54  
 import org.omg.uml.behavioralelements.collaborations.CollaborationInstanceSet;
 55  
 import org.omg.uml.behavioralelements.collaborations.CollaborationsPackage;
 56  
 import org.omg.uml.behavioralelements.collaborations.Interaction;
 57  
 import org.omg.uml.behavioralelements.collaborations.InteractionInstanceSet;
 58  
 import org.omg.uml.behavioralelements.collaborations.Message;
 59  
 import org.omg.uml.behavioralelements.commonbehavior.Link;
 60  
 import org.omg.uml.foundation.core.Classifier;
 61  
 import org.omg.uml.foundation.core.Namespace;
 62  
 import org.omg.uml.foundation.core.Operation;
 63  
 import org.omg.uml.foundation.datatypes.AggregationKind;
 64  
 import org.omg.uml.foundation.datatypes.AggregationKindEnum;
 65  
 
 66  
 /**
 67  
  * Factory to create UML classes for the UML BehaviorialElements::Collaborations
 68  
  * package.<p>
 69  
  *
 70  
  * @since ARGO0.19.5
 71  
  * @author Ludovic Ma&icirc;tre
 72  
  * @author Tom Morris
 73  
  * @author Thierry Lach (did derivation from NSUML implementation)
 74  
  */
 75  76
 class CollaborationsFactoryMDRImpl extends AbstractUmlModelFactoryMDR
 76  
         implements CollaborationsFactory {
 77  
 
 78  
     /**
 79  
      * The model implementation.
 80  
      */
 81  
     private MDRModelImplementation modelImpl;
 82  
 
 83  
     /**
 84  
      * Don't allow instantiation.
 85  
      *
 86  
      * @param implementation
 87  
      *            To get other helpers and factories.
 88  
      */
 89  38
     CollaborationsFactoryMDRImpl(MDRModelImplementation implementation) {
 90  38
         modelImpl = implementation;
 91  38
     }
 92  
 
 93  
     public AssociationEndRole createAssociationEndRole() {
 94  0
         AssociationEndRole myAssociationEndRole =
 95  
             getCollabPkg().getAssociationEndRole().createAssociationEndRole();
 96  0
         super.initialize(myAssociationEndRole);
 97  0
         return myAssociationEndRole;
 98  
     }
 99  
     
 100  
     private CollaborationsPackage getCollabPkg() {
 101  38
         return modelImpl.getUmlPackage().getCollaborations();
 102  
     }
 103  
 
 104  
 
 105  
     public AssociationRole createAssociationRole() {
 106  0
         AssociationRole myAssociationRole =
 107  
             getCollabPkg().getAssociationRole().createAssociationRole();
 108  0
         super.initialize(myAssociationRole);
 109  0
         return myAssociationRole;
 110  
     }
 111  
 
 112  
 
 113  
     public ClassifierRole createClassifierRole() {
 114  0
         ClassifierRole myClassifierRole =
 115  
             getCollabPkg().getClassifierRole().createClassifierRole();
 116  0
         super.initialize(myClassifierRole);
 117  0
         return myClassifierRole;
 118  
     }
 119  
 
 120  
 
 121  
     public Collaboration createCollaboration() {
 122  38
         Collaboration myCollaboration =
 123  
             getCollabPkg().getCollaboration().createCollaboration();
 124  38
         super.initialize(myCollaboration);
 125  38
         return myCollaboration;
 126  
     }
 127  
 
 128  
 
 129  
     public CollaborationInstanceSet createCollaborationInstanceSet() {
 130  0
         CollaborationInstanceSet obj =
 131  
             getCollabPkg().getCollaborationInstanceSet()
 132  
                 .createCollaborationInstanceSet();
 133  0
         super.initialize(obj);
 134  0
         return obj;
 135  
     }
 136  
 
 137  
 
 138  
     public Interaction createInteraction() {
 139  0
         Interaction myInteraction =
 140  
             getCollabPkg().getInteraction().createInteraction();
 141  0
         super.initialize(myInteraction);
 142  0
         return myInteraction;
 143  
     }
 144  
 
 145  
 
 146  
     public InteractionInstanceSet createInteractionInstanceSet() {
 147  0
         InteractionInstanceSet obj =
 148  
             getCollabPkg().getInteractionInstanceSet()
 149  
                 .createInteractionInstanceSet();
 150  0
         super.initialize(obj);
 151  0
         return obj;
 152  
     }
 153  
 
 154  
     
 155  
     public Message createMessage() {
 156  0
         Message myMessage =
 157  
             getCollabPkg().getMessage().createMessage();
 158  0
         super.initialize(myMessage);
 159  0
         return myMessage;
 160  
     }
 161  
 
 162  
 
 163  
     public ClassifierRole buildClassifierRole(Object collaboration) {
 164  0
         Collaboration myCollaboration = (Collaboration) collaboration;
 165  0
         ClassifierRole classifierRole = createClassifierRole();
 166  0
         classifierRole.setNamespace(myCollaboration);
 167  0
         modelImpl.getCoreHelper().setMultiplicity(classifierRole, 1, 1);
 168  0
         return classifierRole;
 169  
     }
 170  
 
 171  
 
 172  
     public Object buildCollaboration(Object handle) {
 173  0
         Namespace namespace = (Namespace) handle;
 174  0
         Collaboration modelelement = createCollaboration();
 175  0
         modelelement.setNamespace(namespace);
 176  0
         modelelement.setName("newCollaboration");
 177  0
         modelelement.setAbstract(false);
 178  0
         return modelelement;
 179  
     }
 180  
 
 181  
 
 182  
     public Object buildCollaboration(Object namespace,
 183  
             Object representedElement) {
 184  0
         if (!(namespace instanceof Namespace)) {
 185  0
             throw new IllegalArgumentException("Argument is not "
 186  
                     + "a namespace");
 187  
         }
 188  
 
 189  0
         if (representedElement instanceof Classifier
 190  
                 || representedElement instanceof Operation) {
 191  
 
 192  0
             Collaboration collaboration =
 193  
                 (Collaboration) buildCollaboration(namespace);
 194  0
             if (representedElement instanceof Classifier) {
 195  0
                 collaboration.
 196  
                 setRepresentedClassifier((Classifier) representedElement);
 197  
 
 198  0
                 return collaboration;
 199  
             }
 200  0
             if (representedElement instanceof Operation) {
 201  0
                 collaboration.
 202  
                 setRepresentedOperation((Operation) representedElement);
 203  
 
 204  0
                 return collaboration;
 205  
             }
 206  
         }
 207  0
         throw new IllegalArgumentException("Represented element must be"
 208  
                 + " Collaboration or Operation");
 209  
     }
 210  
 
 211  
 
 212  
     public Interaction buildInteraction(Object handle) {
 213  0
         Collaboration collab = (Collaboration) handle;
 214  0
         Interaction inter = createInteraction();
 215  0
         inter.setContext(collab);
 216  0
         inter.setName("newInteraction");
 217  0
         return inter;
 218  
     }
 219  
 
 220  
 
 221  
     public AssociationEndRole buildAssociationEndRole(Object atype) {
 222  0
         ClassifierRole type = (ClassifierRole) atype;
 223  0
         AssociationEndRole end = createAssociationEndRole();
 224  0
         end.setParticipant(type);
 225  0
         return end;
 226  
     }
 227  
 
 228  
     
 229  
 
 230  
     public AssociationRole buildAssociationRole(Object from, Object to) {
 231  0
         return buildAssociationRole((ClassifierRole) from, (ClassifierRole) to);
 232  
     }
 233  
     
 234  
     /**
 235  
      * Internal type-checked version of buildAssociationRole.
 236  
      */
 237  
     private AssociationRole buildAssociationRole(ClassifierRole from,
 238  
             ClassifierRole to) {
 239  0
         Collaboration collaboration = (Collaboration) from.getNamespace();
 240  0
         if (collaboration == null 
 241  
                 || !collaboration.equals(to.getNamespace())) {
 242  0
             throw new IllegalArgumentException("ClassifierRoles must be in"
 243  
                     + " same non-null namespace");
 244  
         }
 245  0
         AssociationRole role = createAssociationRole();
 246  0
         role.setNamespace(collaboration);
 247  
         // The 4-arg version of this method depends on this ordering.
 248  
         // Don't change it!
 249  0
         role.getConnection().add(buildAssociationEndRole(from));
 250  0
         role.getConnection().add(buildAssociationEndRole(to));
 251  0
         return role;
 252  
     }
 253  
 
 254  
 
 255  
     @Deprecated
 256  
     public AssociationRole buildAssociationRole(Object from, Object agg1, Object to,
 257  
             Object agg2, Boolean unidirectional) {
 258  0
         if (unidirectional == null) {
 259  0
             return buildAssociationRole(from, agg1, to, agg2, false);
 260  
         } else {
 261  0
             return buildAssociationRole(from, agg1, to, agg2, 
 262  
                     unidirectional.booleanValue());
 263  
         }
 264  
     }
 265  
 
 266  
     
 267  
     public AssociationRole buildAssociationRole(Object from, Object agg1,
 268  
             Object to, Object agg2, boolean unidirectional) {
 269  
 
 270  0
         AggregationKind ak1 = checkAggregationKind(agg1);
 271  0
         AggregationKind ak2 = checkAggregationKind(agg2);
 272  
         
 273  0
         AssociationRole role = buildAssociationRole((ClassifierRole) from, 
 274  
                 (ClassifierRole) to);
 275  
 
 276  0
         AssociationEndRole end =
 277  
                 (AssociationEndRole) role.getConnection().get(0);
 278  0
         end.setAggregation(ak1);
 279  0
         end.setNavigable(!unidirectional);
 280  
 
 281  0
         end = (AssociationEndRole) role.getConnection().get(1);
 282  0
         end.setAggregation(ak2);
 283  0
         end.setNavigable(true); // probably redundant - just in case
 284  
 
 285  0
         return role;
 286  
     }
 287  
     
 288  
     /**
 289  
      * Checks that aggregationKind is valid and promotes null
 290  
      * to AK_NONE.
 291  
      * @param aggregationKind Candidate AggregationKind or null
 292  
      * @return valid checked AggregationKind
 293  
      */
 294  
     private AggregationKind checkAggregationKind(Object aggregationKind) {
 295  0
         if (aggregationKind == null) {
 296  0
             aggregationKind = AggregationKindEnum.AK_NONE;
 297  
         }
 298  0
         return (AggregationKind) aggregationKind;
 299  
     }
 300  
 
 301  
 
 302  
     public AssociationRole buildAssociationRole(Object link) {
 303  0
         if (!(link instanceof Link)) {
 304  0
             throw new IllegalArgumentException("Argument is not a link");
 305  
         }
 306  
 
 307  0
         Object from = modelImpl.getCoreHelper().getSource(link);
 308  0
         Object to = modelImpl.getCoreHelper().getDestination(link);
 309  0
         Object classifierRoleFrom =
 310  
             modelImpl.getFacade().getClassifiers(from).iterator().next();
 311  0
         Object classifierRoleTo =
 312  
             modelImpl.getFacade().getClassifiers(to).iterator().next();
 313  0
         Object collaboration =
 314  
             modelImpl.getFacade().getNamespace(classifierRoleFrom);
 315  0
         if (collaboration != modelImpl.getFacade().getNamespace(
 316  
                 classifierRoleTo)) {
 317  0
             throw new IllegalStateException("ClassifierRoles do not belong "
 318  
                     + "to the same collaboration");
 319  
         }
 320  0
         if (collaboration == null) {
 321  0
             throw new IllegalStateException("Collaboration may not be "
 322  
                     + "null");
 323  
         }
 324  0
         AssociationRole associationRole = createAssociationRole();
 325  0
         modelImpl.getCoreHelper().setNamespace(associationRole, collaboration);
 326  0
         modelImpl.getCoreHelper().addLink(associationRole, link);
 327  0
         return associationRole;
 328  
     }
 329  
 
 330  
     /**
 331  
      * Builds a message within some interaction related to some assocationrole.
 332  
      * The message is added as the last in the interaction sequence.
 333  
      * Furthermore, the message is added as the last to the list of messages
 334  
      * already attached to the role. Effectively, the already attached messages
 335  
      * become predecessors of this message.
 336  
      * TODO: This sets the activator as a side effect. However it is impossible
 337  
      * to determine the activator at this stage as we don't yet know what the
 338  
      * action will be of the message we're creating. See issue 5692.
 339  
      *
 340  
      * @param inter
 341  
      *            The Interaction.
 342  
      * @param role
 343  
      *            The Association Role.
 344  
      * @return The newly created Message.
 345  
      */
 346  
     private Message buildMessageInteraction(Interaction inter,
 347  
             AssociationRole role) {
 348  0
         assert inter != null : "An interaction must be provided";
 349  0
         assert role != null : "An association role must be provided";
 350  
 
 351  0
         Message message = createMessage();
 352  
 
 353  0
         inter.getMessage().add(message);
 354  
 
 355  0
         message.setCommunicationConnection(role);
 356  
 
 357  0
         if (role.getConnection().size() == 2) {
 358  0
             message.setSender((ClassifierRole) role.getConnection().get(0)
 359  
                     .getParticipant());
 360  0
             message.setReceiver((ClassifierRole) role.getConnection().get(1)
 361  
                     .getParticipant());
 362  
 
 363  0
             Collection<Message> messages =
 364  
                 Model.getFacade().getReceivedMessages(message.getSender());
 365  0
             Message lastMsg = lastMessage(messages, message);
 366  
 
 367  0
             if (lastMsg != null) {
 368  0
                 message.setActivator(lastMsg);
 369  0
                 messages = Model.getFacade().getActivatedMessages(lastMsg);
 370  
             } else {
 371  0
                 messages = Model.getFacade().getSentMessages(
 372  
                         message.getSender());
 373  
             }
 374  
 
 375  0
             lastMsg = lastMessage(messages, message);
 376  0
             if (lastMsg != null) {
 377  0
                 message.getPredecessor().add(findEnd(lastMsg));
 378  
             }
 379  
 
 380  
         }
 381  
 
 382  0
         return message;
 383  
     }
 384  
 
 385  
     /**
 386  
      * Finds the last message in the collection not equal to null and not equal
 387  
      * to m.
 388  
      *
 389  
      * @param c
 390  
      *            A collection containing exclusively Messages.
 391  
      * @param m
 392  
      *            A Message.
 393  
      * @return The last message in the collection, or null.
 394  
      */
 395  
     private Message lastMessage(Collection<Message> c, Message m) {
 396  0
         Message last = null;
 397  0
         for (Message msg : c) {
 398  0
             if (msg != null && msg != m) {
 399  0
                 last = msg;
 400  
             }
 401  
         }
 402  0
         return last;
 403  
     }
 404  
 
 405  
     /**
 406  
      * Walks the tree of successors to m rooted until a leaf is found. The leaf
 407  
      * is the returned. If m is itself a leaf, then m is returned.
 408  
      *
 409  
      * @param m A Message.
 410  
      * @return The last message in one branch of the tree rooted at m.
 411  
      */
 412  
     private Message findEnd(Message m) {
 413  
         while (true) {
 414  0
             Collection<Message> c = Model.getFacade().getSuccessors(m);
 415  0
             Iterator<Message> it = c.iterator();
 416  0
             if (!it.hasNext()) {
 417  0
                 return m;
 418  
             }
 419  0
             m = it.next();
 420  0
         }
 421  
     }
 422  
 
 423  
 
 424  
     public Message buildMessage(Object acollab, Object arole) {
 425  0
         if (!(arole instanceof AssociationRole)) {
 426  0
             throw new IllegalArgumentException(
 427  
                     "An association role must be supplied - got " + arole);
 428  
         }
 429  
         try {
 430  0
             if (acollab instanceof Collaboration) {
 431  0
                 return buildMessageCollab((Collaboration) acollab,
 432  
                         (AssociationRole) arole);
 433  
             }
 434  0
             if (acollab instanceof Interaction) {
 435  0
                 return buildMessageInteraction((Interaction) acollab,
 436  
                         (AssociationRole) arole);
 437  
             }
 438  0
             throw new IllegalArgumentException("No valid object " + acollab);
 439  0
         } catch (InvalidObjectException e) {
 440  0
             throw new InvalidElementException(e);
 441  
         }
 442  
     }
 443  
 
 444  
     private Message buildMessageCollab(Collaboration collab,
 445  
             AssociationRole role) {
 446  0
         Interaction inter = null;
 447  0
         if (collab.getInteraction().size() == 0) {
 448  0
             inter = buildInteraction(collab);
 449  
         } else {
 450  0
             inter = (Interaction) (collab.getInteraction().toArray())[0];
 451  
         }
 452  0
         return buildMessageInteraction(inter, role);
 453  
     }
 454  
 
 455  
 
 456  
     public Message buildActivator(Object owner, Object interaction) {
 457  0
         Message theOwner = (Message) owner;
 458  
         Interaction theInteraction;
 459  0
         if (interaction == null) {
 460  0
             theInteraction = theOwner.getInteraction();
 461  
         } else {
 462  0
             theInteraction = (Interaction) interaction;
 463  
         }
 464  0
         if (interaction == null) {
 465  0
             throw new IllegalArgumentException();
 466  
         }
 467  
 
 468  0
         Message activator = createMessage();
 469  0
         activator.setInteraction(theInteraction);
 470  0
         theOwner.setActivator(activator);
 471  0
         return activator;
 472  
     }
 473  
 
 474  
     /**
 475  
      * @param elem
 476  
      *            the associationendrole
 477  
      */
 478  
     void deleteAssociationEndRole(Object elem) {
 479  0
         if (!(elem instanceof AssociationEndRole)) {
 480  0
             throw new IllegalArgumentException();
 481  
         }
 482  
 
 483  0
     }
 484  
 
 485  
     /**
 486  
      * @param elem
 487  
      *            the associationrole
 488  
      */
 489  
     void deleteAssociationRole(Object elem) {
 490  0
         AssociationRole role = (AssociationRole) elem;
 491  0
         for (Message message : role.getMessage()) {
 492  0
             modelImpl.getUmlFactory().delete(message);
 493  
         }
 494  0
     }
 495  
 
 496  
     /**
 497  
      * @param elem
 498  
      *            the UML element to be deleted
 499  
      */
 500  
     void deleteClassifierRole(Object elem) {
 501  0
         ClassifierRole cr = (ClassifierRole) elem;
 502  
         // delete Messages which have this as sender or receiver
 503  0
         CollaborationsPackage cPkg = ((org.omg.uml.UmlPackage) cr
 504  
                 .refOutermostPackage()).getCollaborations();
 505  0
         modelImpl.getUmlHelper().deleteCollection(
 506  
                 cPkg.getAMessageSender().getMessage(cr));
 507  0
         modelImpl.getUmlHelper().deleteCollection(
 508  
                 cPkg.getAReceiverMessage().getMessage(cr));
 509  
         // TODO: delete Collaborations where this is the last ClassifierRole?
 510  
 //        Object owner = cr.refImmediateComposite();
 511  
 //        if (owner instanceof Collaboration) {
 512  
 //            Collection ownedElements = ((Collaboration) owner)
 513  
 //                    .getOwnedElement();
 514  
 //            if (ownedElements.size() == 1 && ownedElements.contains(cr))
 515  
 //                nsmodel.getUmlFactory().delete(owner);
 516  
 //        }
 517  0
     }
 518  
 
 519  
     /**
 520  
      * @param elem
 521  
      *            the UML element to be delete
 522  
      */
 523  
     void deleteCollaboration(Object elem) {
 524  0
         if (!(elem instanceof Collaboration)) {
 525  0
             throw new IllegalArgumentException();
 526  
         }
 527  0
     }
 528  
 
 529  
     /**
 530  
      * @param elem
 531  
      *            the UML element to be delete
 532  
      */
 533  
     void deleteCollaborationInstanceSet(Object elem) {
 534  0
         if (!(elem instanceof CollaborationInstanceSet)) {
 535  0
             throw new IllegalArgumentException();
 536  
         }
 537  
         // InteractionInstanceSets will get deleted automatically
 538  
         // because they are associated by composition
 539  0
     }
 540  
 
 541  
     /**
 542  
      * @param elem
 543  
      *            the UML element to be delete
 544  
      */
 545  
     void deleteInteraction(Object elem) {
 546  0
         if (!(elem instanceof Interaction)) {
 547  0
             throw new IllegalArgumentException();
 548  
         }
 549  0
     }
 550  
 
 551  
     /**
 552  
      * @param elem
 553  
      *            the UML element to be delete
 554  
      */
 555  
     void deleteInteractionInstanceSet(Object elem) {
 556  0
         if (!(elem instanceof InteractionInstanceSet)) {
 557  0
             throw new IllegalArgumentException();
 558  
         }
 559  0
     }
 560  
 
 561  
     /**
 562  
      * @param elem
 563  
      *            the UML element to be delete
 564  
      */
 565  
     void deleteMessage(Object elem) {
 566  0
         Message message = (Message) elem;
 567  
         // If this is the only message contained in the Interaction
 568  
         // we delete the Interaction
 569  0
         Interaction i = message.getInteraction();
 570  0
         if (i != null && i.getMessage().size() == 1) {
 571  0
             modelImpl.getUmlFactory().delete(i);
 572  
         }
 573  0
     }
 574  
 
 575  
 }