Beispiel #1
0
 public boolean concurrentState() {
   final Group cur = getCurrentGroup();
   if (cur != null && cur.getType() == GroupType.CONCURRENT_STATE) {
     super.endGroup();
   }
   final Group conc1 =
       getOrCreateGroup(
           "CONC" + UniqueSequence.getValue(),
           "",
           null,
           GroupType.CONCURRENT_STATE,
           getCurrentGroup());
   conc1.setDashed(true);
   if (cur != null && cur.getType() == GroupType.STATE) {
     cur.moveEntitiesTo(conc1);
     super.endGroup();
     final Group conc2 =
         getOrCreateGroup(
             "CONC" + UniqueSequence.getValue(),
             "",
             null,
             GroupType.CONCURRENT_STATE,
             getCurrentGroup());
     conc2.setDashed(true);
   }
   return true;
 }
  @Override
  protected CommandExecutionResult executeArg(List<String> arg) {
    final String pos = arg.get(0);
    final Entity note = getSystem().createNote("GN" + UniqueSequence.getValue(), arg.get(2));
    note.setSpecificBackcolor(HtmlColor.getColorIfValid(arg.get(1)));

    IEntity activity = getSystem().getLastEntityConsulted();
    if (activity == null) {
      activity = getSystem().getStart();
    }

    final Position position =
        Position.valueOf(pos.toUpperCase()).withRankdir(getSystem().getRankdir());
    final Link link;

    final LinkType type = new LinkType(LinkDecor.NONE, LinkDecor.NONE).getDashed();
    if (position == Position.RIGHT) {
      link = new Link(activity, note, type, null, 1);
    } else if (position == Position.LEFT) {
      link = new Link(note, activity, type, null, 1);
    } else if (position == Position.BOTTOM) {
      link = new Link(activity, note, type, null, 2);
    } else if (position == Position.TOP) {
      link = new Link(note, activity, type, null, 2);
    } else {
      throw new IllegalArgumentException();
    }
    getSystem().addLink(link);
    return CommandExecutionResult.ok();
  }
 @Override
 protected CommandExecutionResult executeArg(List<String> arg) {
   final String code;
   final String display;
   if (arg.get(1) == null) {
     if (StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(arg.get(0)).length() == 0) {
       code = "##" + UniqueSequence.getValue();
       display = null;
     } else {
       code = StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(arg.get(0));
       display = code;
     }
   } else {
     display = StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(arg.get(0));
     code = arg.get(1);
   }
   final Group currentPackage = getSystem().getCurrentGroup();
   // if (getSystem().entityExist(code)) {
   // return CommandExecutionResult.error("Package cannot have the same
   // name as an existing class");
   // }
   final Group p =
       getSystem().getOrCreateGroup(code, display, null, GroupType.PACKAGE, currentPackage);
   p.setBold(true);
   final String color = arg.get(2);
   if (color != null) {
     p.setBackColor(HtmlColor.getColorIfValid(color));
   }
   return CommandExecutionResult.ok();
 }
  private Element createEntityNode(IEntity entity) {
    // <UML:Class xmi.id="UMLClass.5" name="Class1" visibility="public"
    // isSpecification="false"
    // namespace="UMLModel.4" isRoot="false" isLeaf="false"
    // isAbstract="false" participant="UMLAssociationEnd.11"
    // isActive="false">
    final Element cla = document.createElement("UML:Class");

    cla.setAttribute("xmi.id", entity.getUid());
    cla.setAttribute("name", entity.getDisplay2().get(0).toString());
    cla.setAttribute("namespace", "model1");

    final Element feature = document.createElement("UML:Classifier.feature");
    cla.appendChild(feature);

    for (Member m : entity.getFieldsToDisplay()) {
      // <UML:Attribute xmi.id="UMLAttribute.6" name="Attribute1"
      // visibility="public" isSpecification="false"
      // ownerScope="instance" changeability="changeable"
      // targetScope="instance" type="" owner="UMLClass.5"/>
      final Element attribute = document.createElement("UML:Attribute");
      attribute.setAttribute("xmi.id", "att" + UniqueSequence.getValue());
      attribute.setAttribute("name", m.getDisplayWithoutVisibilityChar());
      feature.appendChild(attribute);
    }

    for (Member m : entity.getMethodsToDisplay()) {
      // <UML:Operation xmi.id="UMLOperation.7" name="Operation1"
      // visibility="public" isSpecification="false"
      // ownerScope="instance" isQuery="false" concurrency="sequential"
      // isRoot="false" isLeaf="false"
      // isAbstract="false" specification="" owner="UMLClass.5"/>
      final Element operation = document.createElement("UML:Operation");
      operation.setAttribute("xmi.id", "att" + UniqueSequence.getValue());
      operation.setAttribute("name", m.getDisplayWithoutVisibilityChar());
      feature.appendChild(operation);
    }
    return cla;
  }
  public final CommandExecutionResult execute(List<String> lines) {

    final List<String> line0 = StringUtils.getSplit(getStartingPattern(), lines.get(0).trim());
    final String pos = line0.get(0);

    final IEntity activity = getSystem().getLastEntityConsulted();
    if (activity == null) {
      // activity = getSystem().getStart();
      return CommandExecutionResult.error("No activity defined");
    }

    final List<String> strings = StringUtils.removeEmptyColumns(lines.subList(1, lines.size() - 1));
    //		final String s = StringUtils.getMergedLines(strings);

    final IEntity note =
        getSystem().createLeaf(UniqueSequence.getCode("GMN"), strings, LeafType.NOTE);
    note.setSpecificBackcolor(HtmlColorUtils.getColorIfValid(line0.get(1)));

    final Link link;

    final Position position =
        Position.valueOf(pos.toUpperCase()).withRankdir(getSystem().getRankdir());

    final LinkType type = new LinkType(LinkDecor.NONE, LinkDecor.NONE).getDashed();

    if (position == Position.RIGHT) {
      link = new Link(activity, note, type, null, 1);
    } else if (position == Position.LEFT) {
      link = new Link(note, activity, type, null, 1);
    } else if (position == Position.BOTTOM) {
      link = new Link(activity, note, type, null, 2);
    } else if (position == Position.TOP) {
      link = new Link(note, activity, type, null, 2);
    } else {
      throw new IllegalArgumentException();
    }
    getSystem().addLink(link);
    return CommandExecutionResult.ok();
  }
  private void addLink(Link link) {
    final String assId = "ass" + UniqueSequence.getValue();
    if (link.getType().getDecor1() == LinkDecor.EXTENDS
        || link.getType().getDecor2() == LinkDecor.EXTENDS) {
      addExtension(link, assId);
      return;
    }
    final Element association = document.createElement("UML:Association");
    association.setAttribute("xmi.id", assId);
    association.setAttribute("namespace", "model1");
    if (link.getLabel() != null) {
      association.setAttribute("name", forXMI(link.getLabel()));
    }

    final Element connection = document.createElement("UML:Association.connection");
    final Element end1 = document.createElement("UML:AssociationEnd");
    end1.setAttribute("xmi.id", "end" + UniqueSequence.getValue());
    end1.setAttribute("association", assId);
    end1.setAttribute("type", link.getEntity1().getUid());
    if (link.getQualifier1() != null) {
      end1.setAttribute("name", forXMI(link.getQualifier1()));
    }
    final Element endparticipant1 = document.createElement("UML:AssociationEnd.participant");
    // if (fileFormat == FileFormat.XMI_ARGO) {
    // if (done.contains(link.getEntity1())) {
    // endparticipant1.appendChild(createEntityNodeRef(link.getEntity1()));
    // } else {
    // endparticipant1.appendChild(createEntityNode(link.getEntity1()));
    // done.add(link.getEntity1());
    // }
    // } else if (fileFormat == FileFormat.XMI_STAR) {
    if (link.getType().getDecor2() == LinkDecor.COMPOSITION) {
      end1.setAttribute("aggregation", "composite");
    }
    if (link.getType().getDecor2() == LinkDecor.AGREGATION) {
      end1.setAttribute("aggregation", "aggregate");
    }
    // }
    end1.appendChild(endparticipant1);
    connection.appendChild(end1);

    final Element end2 = document.createElement("UML:AssociationEnd");
    end2.setAttribute("xmi.id", "end" + UniqueSequence.getValue());
    end2.setAttribute("association", assId);
    end2.setAttribute("type", link.getEntity2().getUid());
    if (link.getQualifier2() != null) {
      end2.setAttribute("name", forXMI(link.getQualifier2()));
    }
    final Element endparticipant2 = document.createElement("UML:AssociationEnd.participant");
    // if (fileFormat == FileFormat.XMI_ARGO) {
    // if (done.contains(link.getEntity2())) {
    // endparticipant2.appendChild(createEntityNodeRef(link.getEntity2()));
    // } else {
    // endparticipant2.appendChild(createEntityNode(link.getEntity2()));
    // done.add(link.getEntity2());
    // }
    // } else if (fileFormat == FileFormat.XMI_STAR) {
    if (link.getType().getDecor1() == LinkDecor.COMPOSITION) {
      end2.setAttribute("aggregation", "composite");
    }
    if (link.getType().getDecor1() == LinkDecor.AGREGATION) {
      end2.setAttribute("aggregation", "aggregate");
    }
    // }
    end2.appendChild(endparticipant2);
    connection.appendChild(end2);

    association.appendChild(connection);

    ownedElement.appendChild(association);
  }
  @Override
  protected CommandExecutionResult executeArg(RegexResult arg) {

    final Code ent1 = Code.of(arg.get("ENT1", 1));
    final Code ent2 = Code.of(arg.get("ENT2", 1));

    final IEntity cl1;
    final IEntity cl2;
    final IEntity normalEntity;

    final String suffix = "lol" + UniqueSequence.getValue();
    if (arg.get("LOL_THEN_ENT", 0) == null) {
      assert arg.get("ENT_THEN_LOL", 0) != null;
      cl1 = getSystem().getOrCreateClass(ent1);
      cl2 =
          getSystem()
              .createLeaf(
                  cl1.getCode().addSuffix(suffix),
                  StringUtils.getWithNewlines(ent2),
                  LeafType.LOLLIPOP);
      normalEntity = cl1;
    } else {
      cl2 = getSystem().getOrCreateClass(ent2);
      cl1 =
          getSystem()
              .createLeaf(
                  cl2.getCode().addSuffix(suffix),
                  StringUtils.getWithNewlines(ent1),
                  LeafType.LOLLIPOP);
      normalEntity = cl2;
    }

    final LinkType linkType = getLinkType(arg);
    final String queue = getQueue(arg);

    int length = queue.length();
    if (length == 1 && getSystem().getNbOfHozizontalLollipop(normalEntity) > 1) {
      length++;
    }

    String firstLabel = arg.get("FIRST_LABEL", 0);
    String secondLabel = arg.get("SECOND_LABEL", 0);

    String labelLink = null;

    if (arg.get("LABEL_LINK", 0) != null) {
      labelLink = arg.get("LABEL_LINK", 0);
      if (firstLabel == null && secondLabel == null) {
        final Pattern p1 = Pattern.compile("^\"([^\"]+)\"([^\"]+)\"([^\"]+)\"$");
        final Matcher m1 = p1.matcher(labelLink);
        if (m1.matches()) {
          firstLabel = m1.group(1);
          labelLink =
              StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(m1.group(2).trim()).trim();
          secondLabel = m1.group(3);
        } else {
          final Pattern p2 = Pattern.compile("^\"([^\"]+)\"([^\"]+)$");
          final Matcher m2 = p2.matcher(labelLink);
          if (m2.matches()) {
            firstLabel = m2.group(1);
            labelLink =
                StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(m2.group(2).trim()).trim();
            secondLabel = null;
          } else {
            final Pattern p3 = Pattern.compile("^([^\"]+)\"([^\"]+)\"$");
            final Matcher m3 = p3.matcher(labelLink);
            if (m3.matches()) {
              firstLabel = null;
              labelLink =
                  StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(m3.group(1).trim())
                      .trim();
              secondLabel = m3.group(2);
            }
          }
        }
      }
      labelLink = StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(labelLink);
    } /*
       * else if (arg.get("LABEL_LINK_XT").get(0) != null ||
       * arg.get("LABEL_LINK_XT").get(1) != null ||
       * arg.get("LABEL_LINK_XT").get(2) != null) { labelLink =
       * arg.get("LABEL_LINK_XT").get(1); firstLabel = merge(firstLabel,
       * arg.get("LABEL_LINK_XT").get(0)); secondLabel =
       * merge(arg.get("LABEL_LINK_XT").get(2), secondLabel); }
       */

    final Link link =
        new Link(
            cl1,
            cl2,
            linkType,
            labelLink,
            length,
            firstLabel,
            secondLabel,
            getSystem().getLabeldistance(),
            getSystem().getLabelangle());
    getSystem().resetPragmaLabel();
    addLink(link, arg.get("HEADER", 0));

    return CommandExecutionResult.ok();
  }
Beispiel #8
0
public class Link {

  private final IEntity cl1;
  private final IEntity cl2;
  private final LinkType type;
  private final String label;

  private int length;
  private final String qualifier1;
  private final String qualifier2;
  private final String uid = "LNK" + UniqueSequence.getValue();

  private List<? extends CharSequence> note;
  private Position notePosition;
  private HtmlColor noteColor;

  private boolean invis = false;
  private double weight = 1.0;

  private final String labeldistance;
  private final String labelangle;

  private HtmlColor specificColor;
  private boolean constraint = true;
  private boolean inverted = false;
  private LinkArrow linkArrow = LinkArrow.NONE;

  public final boolean isInverted() {
    return inverted;
  }

  public Link(IEntity cl1, IEntity cl2, LinkType type, String label, int length) {
    this(cl1, cl2, type, label, length, null, null, null, null, null);
  }

  public Link(
      IEntity cl1,
      IEntity cl2,
      LinkType type,
      String label,
      int length,
      String qualifier1,
      String qualifier2,
      String labeldistance,
      String labelangle) {
    this(cl1, cl2, type, label, length, qualifier1, qualifier2, labeldistance, labelangle, null);
  }

  public Link(
      IEntity cl1,
      IEntity cl2,
      LinkType type,
      String label,
      int length,
      String qualifier1,
      String qualifier2,
      String labeldistance,
      String labelangle,
      HtmlColor specificColor) {
    if (length < 1) {
      throw new IllegalArgumentException();
    }
    if (cl1 == null || cl2 == null) {
      throw new IllegalArgumentException();
    }
    if (cl1.getEntityType() == EntityType.STATE_CONCURRENT) {
      throw new IllegalArgumentException();
    }
    if (cl2.getEntityType() == EntityType.STATE_CONCURRENT) {
      throw new IllegalArgumentException();
    }
    if (cl1 instanceof EntityMutable == false) {
      throw new IllegalArgumentException();
    }
    if (cl2 instanceof EntityMutable == false) {
      throw new IllegalArgumentException();
    }
    this.cl1 = cl1;
    this.cl2 = cl2;
    this.type = type;
    this.label = label;
    this.length = length;
    this.qualifier1 = qualifier1;
    this.qualifier2 = qualifier2;
    this.labeldistance = labeldistance;
    this.labelangle = labelangle;
    this.specificColor = specificColor;
    if (qualifier1 != null) {
      cl1.setNearDecoration(true);
    }
    if (qualifier2 != null) {
      cl2.setNearDecoration(true);
    }
  }

  public Link getInv() {
    // if (getLength() == 1) {
    // final int x = cl1.getXposition();
    // cl2.setXposition(x-1);
    // }
    final Link result =
        new Link(
            cl2,
            cl1,
            getType().getInversed(),
            label,
            length,
            qualifier2,
            qualifier1,
            labeldistance,
            labelangle,
            specificColor);
    result.inverted = true;
    return result;
  }

  public Link getDashed() {
    return new Link(
        cl1,
        cl2,
        getType().getDashed(),
        label,
        length,
        qualifier1,
        qualifier2,
        labeldistance,
        labelangle,
        specificColor);
  }

  public Link getDotted() {
    return new Link(
        cl1,
        cl2,
        getType().getDotted(),
        label,
        length,
        qualifier1,
        qualifier2,
        labeldistance,
        labelangle,
        specificColor);
  }

  public Link getBold() {
    return new Link(
        cl1,
        cl2,
        getType().getBold(),
        label,
        length,
        qualifier1,
        qualifier2,
        labeldistance,
        labelangle,
        specificColor);
  }

  public String getLabeldistance() {
    // Default in dot 1.0
    return labeldistance;
  }

  public String getLabelangle() {
    // Default in dot -25
    return labelangle;
  }

  public String getUid() {
    return uid;
  }

  public final boolean isInvis() {
    if (type.isInvisible()) {
      return true;
    }
    return invis;
  }

  public final void setInvis(boolean invis) {
    this.invis = invis;
  }

  public boolean insideGroup(Group g) {
    if (EntityUtils.equals(cl1.getContainer(), g)
        && ((IEntityMutable) cl1).isGroup() == false
        && EntityUtils.equals(cl2.getContainer(), g)
        && ((IEntityMutable) cl2).isGroup() == false) {
      return true;
    }
    return false;
  }

  private static IEntity muteProxy(IEntity ent, Group g, IEntity proxy) {
    if (((IEntityMutable) ent).isGroup()) {
      if (EntityUtils.equals((Group) ent, g)) {
        return proxy;
      }
    }
    return ent;
  }

  public Link mute(Group g, IEntity proxy) {
    final Group g1 = EntityUtils.getContainerOrEquivalent(cl1);
    final Group g2 = EntityUtils.getContainerOrEquivalent(cl2);
    if (EntityUtils.equals(g1, g)
        && ((IEntityMutable) cl1).isGroup() == false
        && EntityUtils.equals(g, g2)
        && ((IEntityMutable) cl2).isGroup() == false) {
      return null;
    }
    final IEntity ent1 = muteProxy(cl1, g, proxy);
    final IEntity ent2 = muteProxy(cl2, g, proxy);
    if (this.cl1 == ent1 && this.cl2 == ent2) {
      return this;
    }
    return new Link(
        ent1, ent2, getType(), label, length, qualifier1, qualifier2, labeldistance, labelangle);
  }

  public Link mute2(Group g) {
    final Group g1 = cl1.getContainer();
    final Group g2 = cl2.getContainer();
    if (g1 == g && g2 == g) {
      return null;
    }
    return this;
  }

  public boolean isBetween(IEntity cl1, IEntity cl2) {
    if (cl1.equals(this.cl1) && cl2.equals(this.cl2)) {
      return true;
    }
    if (cl1.equals(this.cl2) && cl2.equals(this.cl1)) {
      return true;
    }
    return false;
  }

  @Override
  public String toString() {
    return super.toString() + " " + cl1 + "-->" + cl2;
  }

  public IEntity getEntity1() {
    return cl1;
  }

  public IEntity getEntity2() {
    return cl2;
  }

  public LinkType getType() {
    if (opale) {
      return new LinkType(LinkDecor.NONE, LinkDecor.NONE);
    }
    return type;
  }

  public String getLabel() {
    return label;
  }

  public int getLength() {
    return length;
  }

  public final void setLength(int length) {
    this.length = length;
  }

  public String getQualifier1() {
    return qualifier1;
  }

  public String getQualifier2() {
    return qualifier2;
  }

  public final double getWeight() {
    return weight;
  }

  public final void setWeight(double weight) {
    this.weight = weight;
  }

  public final List<? extends CharSequence> getNote() {
    return note;
  }

  public final HtmlColor getNoteColor() {
    return noteColor;
  }

  public final Position getNotePosition() {
    return notePosition;
  }

  public final void addNote(
      List<? extends CharSequence> note, Position position, HtmlColor noteColor) {
    this.note = note;
    this.notePosition = position;
    this.noteColor = noteColor;
  }

  public final void addNote(String n, Position position, HtmlColor noteColor) {
    this.note = StringUtils.getWithNewlines(n);
    this.notePosition = position;
    this.noteColor = noteColor;
  }

  public boolean isAutolink(Group g) {
    if (((IEntityMutable) getEntity1()).isGroup() == false) {
      return false;
    }
    if (((IEntityMutable) getEntity2()).isGroup() == false) {
      return false;
    }
    if (EntityUtils.equals(g, (Group) getEntity1())
        && EntityUtils.equals(g, (Group) getEntity1())) {
      return true;
    }
    // if (getEntity1() == g.zgetEntityCluster() && getEntity2() == g.zgetEntityCluster()) {
    // assert getEntity1().getType() == EntityType.GROUP;
    // assert getEntity2().getType() == EntityType.GROUP;
    // return true;
    // }
    return false;
  }

  public boolean isAutoLinkOfAGroup() {
    if (((IEntityMutable) getEntity1()).isGroup() == false) {
      return false;
    }
    if (((IEntityMutable) getEntity2()).isGroup() == false) {
      return false;
    }
    if (getEntity1() == getEntity2()) {
      return true;
    }
    return false;
  }

  public boolean isToEdgeLink(Group g) {
    final Group g1 = EntityUtils.getContainerOrEquivalent(getEntity1());
    final Group g2 = EntityUtils.getContainerOrEquivalent(getEntity2());
    if (EntityUtils.equals(g1, g) == false || EntityUtils.equals(g2, g) == false) {
      return false;
    }
    assert EntityUtils.equals(g1, g) && EntityUtils.equals(g2, g);
    if (isAutolink(g)) {
      return false;
    }

    if (((IEntityMutable) getEntity2()).isGroup()) {
      assert ((EntityMutable) getEntity1()).isGroup() == false;
      return true;
    }
    return false;
  }

  public boolean isFromEdgeLink(Group g) {
    final Group g1 = EntityUtils.getContainerOrEquivalent(getEntity1());
    final Group g2 = EntityUtils.getContainerOrEquivalent(getEntity2());
    if (EntityUtils.equals(g1, g) == false || EntityUtils.equals(g2, g) == false) {
      return false;
    }
    assert EntityUtils.equals(g1, g) && EntityUtils.equals(g2, g);
    if (isAutolink(g)) {
      return false;
    }

    if (((EntityMutable) getEntity1()).isGroup()) {
      assert ((EntityMutable) getEntity2()).isGroup() == false;
      return true;
    }
    return false;
  }

  public boolean containsType(EntityType type) {
    if (getEntity1().getEntityType() == type || getEntity2().getEntityType() == type) {
      return true;
    }
    return false;
  }

  public boolean contains(IEntity entity) {
    if (getEntity1() == entity || getEntity2() == entity) {
      return true;
    }
    return false;
  }

  public IEntity getOther(IEntity entity) {
    if (getEntity1() == entity) {
      return getEntity2();
    }
    if (getEntity2() == entity) {
      return getEntity1();
    }
    throw new IllegalArgumentException();
  }

  public double getMarginDecors1(
      StringBounder stringBounder, UFont fontQualif, SpriteContainer spriteContainer) {
    final double q = getQualifierMargin(stringBounder, fontQualif, qualifier1, spriteContainer);
    final LinkDecor decor = getType().getDecor1();
    return decor.getSize() + q;
  }

  public double getMarginDecors2(
      StringBounder stringBounder, UFont fontQualif, SpriteContainer spriteContainer) {
    final double q = getQualifierMargin(stringBounder, fontQualif, qualifier2, spriteContainer);
    final LinkDecor decor = getType().getDecor2();
    return decor.getSize() + q;
  }

  private double getQualifierMargin(
      StringBounder stringBounder,
      UFont fontQualif,
      String qualif,
      SpriteContainer spriteContainer) {
    if (qualif != null) {
      final TextBlock b =
          TextBlockUtils.create(
              Arrays.asList(qualif),
              new FontConfiguration(fontQualif, HtmlColorUtils.BLACK),
              HorizontalAlignement.LEFT,
              spriteContainer);
      final Dimension2D dim = b.calculateDimension(stringBounder);
      return Math.max(dim.getWidth(), dim.getHeight());
    }
    return 0;
  }

  public HtmlColor getSpecificColor() {
    return specificColor;
  }

  public void setSpecificColor(String s) {
    this.specificColor = HtmlColorUtils.getColorIfValid(s);
  }

  public final boolean isConstraint() {
    return constraint;
  }

  public final void setConstraint(boolean constraint) {
    this.constraint = constraint;
  }

  private boolean opale;

  public void setOpale(boolean opale) {
    this.opale = opale;
  }

  public static boolean onlyOneLink(IEntity ent, Collection<Link> links) {
    int nb = 0;
    for (Link link : links) {
      if (link.contains(ent)) {
        nb++;
      }
      if (nb > 1) {
        return false;
      }
    }
    return nb == 1;
  }

  private boolean horizontalSolitary;

  public final void setHorizontalSolitary(boolean horizontalSolitary) {
    this.horizontalSolitary = horizontalSolitary;
  }

  public final boolean isHorizontalSolitary() {
    return horizontalSolitary;
  }

  public final LinkArrow getLinkArrow() {
    if (inverted) {
      return linkArrow.reverse();
    }
    return linkArrow;
  }

  public final void setLinkArrow(LinkArrow linkArrow) {
    this.linkArrow = linkArrow;
  }
}