コード例 #1
0
class SoftwareSystem(Element):

    def __init__(self):
        super().__init__()
        self._location = Location.UNSPECIFIED
        self._containers = OrderedSet()

    def get_parent(self):
        return None

    # TODO: This is duplicated in Person
    def get_location(self):
        return self._location

    # TODO: This is duplicated in Person
    def set_location(self, location):
        if not isinstance(location, Location):
            raise TypeError("{!r} is not a {}".format(location, Location.__name__))
        self._location = location if location is not None else Location.UNSPECIFIED

    def add_existing_container(self, container):
        from structurizr.model.container import Container
        if not isinstance(container, Container):
            raise TypeError("{!r} is not a {}".format(container, Container.__name__))
        self._containers.add(container)

    def get_containers(self):
        return self._containers.copy()

    def add_container(self, name, description, technology):
        return self.get_model().add_container(self, name, description, technology)

    def get_container_with_name(self, name):
        return next((c for c in self.get_containers() if c.get_name() == name), None)

    def get_container_with_id(self, id):
        return next((c for c in self.get_containers() if c.get_id() == id), None)

    # TODO: This is duplicated in Person
    def get_canonical_name(self):
        return CANONICAL_NAME_SEPARATOR + self._format_for_canonical_name(self.get_name())

    def get_required_tags(self):
        return OrderedSet([tags.ELEMENT, tags.SOFTWARE_SYSTEM])
コード例 #2
0
def gen_aliases(name, domain, do_alias = True):
    
#     prefixes = ["RESTAURANT", "LODGE", "HOTEL", "GUESTHOUSE", "HOUSE", "CAFE", "BAR"]
#     suffixes = ["RESTAURANT", "LODGE", "HOTEL", "GUESTHOUSE", "HOUSE", "CAFE", "BAR"]
    prefixes = [domain.upper()]
    suffixes = [domain.upper()]
    synonyms_sets = [["&", " & ", "AND", " AND "]]
    oneway_synonyms_sets = {"-": ["", " "], "(^LA | LA | LA$)": [" THE "]}
    if do_alias:
        prefixes = list(set(prefixes + ["RESTAURANT", "HOTEL", "GUESTHOUSE", "HOUSE", "CAFE", "BAR", "THE"]))
        suffixes = list(set(suffixes + ["RESTAURANT", "HOTEL", "GUESTHOUSE", "HOUSE", "CAFE", "BAR"]))
        synonyms_sets.append(["GUESTHOUSE", "GUEST HOUSE"])
    
    aliases = OrderedSet()
    aliases_tmp = aliases.copy()
    
    name_upper = name.upper()
    aliases_tmp.add(name_upper)

#     print (aliases)
#     print ()

    
    # generate alias by replacing synonyms with each other
    while(len(aliases_tmp) != len(aliases)):
        aliases = aliases_tmp.copy()
        for alias in aliases:
            for synonyms in synonyms_sets:
                for idx in range(len(synonyms)):
                    replacing_syn = synonyms[idx]
    #                 print (replacing_syn)
                    matching_syn = synonyms.copy()
    #                 matching_syn.pop(idx)
    #                 print (matching_syn)
                    rmSuffix_name = re.sub(("|").join(matching_syn), replacing_syn, alias)
                    rmSuffix_name_strip = re.sub(" +", " ", rmSuffix_name).strip()
                    aliases_tmp.add(rmSuffix_name_strip)

#     pprint (aliases_tmp)
#     print ()

    # generate for one-way synonym replaced aliases
    aliases = OrderedSet()
    while(len(aliases_tmp) != len(aliases)):
        aliases = aliases_tmp.copy()
        for alias in aliases:
            for matching_syn in oneway_synonyms_sets:
                for replacing_syn in oneway_synonyms_sets[matching_syn]:
                    rmSuffix_name = re.sub(matching_syn, replacing_syn, alias)
                    rmSuffix_name_strip = re.sub(" +", " ", rmSuffix_name).strip()
                    aliases_tmp.add(rmSuffix_name_strip)
                    
    # generate alias by removing suffixes
    aliases = OrderedSet()
    while(len(aliases_tmp) != len(aliases)):
        aliases = aliases_tmp.copy()
        for alias in aliases:
            for suffix in suffixes:
                rmSuffix_name = re.sub("(.*) " + suffix + "$", "\g<1>", alias)
                rmSuffix_name_strip = re.sub(" +", " ", rmSuffix_name).strip()
                aliases_tmp.add(rmSuffix_name_strip)
                
                        
    # generate alias by removing prefixes
    aliases = OrderedSet()
    while(len(aliases_tmp) != len(aliases)):
        aliases = aliases_tmp.copy()
        for alias in aliases:
            for prefix in prefixes:
                rmPrefix_name = re.sub("^" + prefix + " (.*)", "\g<1>", alias)
                rmPrefix_name_strip = re.sub(" +", " ", rmPrefix_name).strip()
                aliases_tmp.add(rmPrefix_name_strip)
                
    return aliases_tmp
コード例 #3
0
class Element(Taggable):

    def __init__(self):
        super().__init__()
        self._model = None
        self._id = ""
        self._name = None
        self._description = None
        self._url = None
        self._relationships = OrderedSet()

    def get_model(self):
        return self._model

    def set_model(self, model):
        self._model = model

    def get_id(self):
        return self._id

    def set_id(self, id):
        self._id = id

    def get_name(self):
        return self._name

    def set_name(self, name):
        if not name:
            raise ValueError("The name of an element must not be None or empty.")
        self._name = name

    def get_url(self):
        return self._url

    def set_url(self, url):
        if url and url.strip():
            if is_well_formed_url(url):
                self._url = url
            else:
                raise ValueError("{} is not a valid URL".format(url))

    @abstractmethod
    def get_canonical_name(self):
        raise NotImplementedError

    def _format_for_canonical_name(self, name):
        return name.replace(CANONICAL_NAME_SEPARATOR, "")

    def get_description(self):
        return self._description

    def set_description(self, description):
        self._description = description

    @abstractmethod
    def get_parent(self):
        raise NotImplementedError

    def get_relationships(self):
        return self._relationships.copy()

    def uses(self, destination, description, technology=None, interaction_style=None):
        """Adds a unidirectional "uses" style relationship between this element and a software system or component.

        Args:
            destination: The target of the relationship
            description: A description of the relationship (e.g. "uses", "gets data from", "sends data to")
            technology:  The technology details (e.g. JSON/HTTPS)
            interaction_style: The interaction style (sync vs async)

        Returns: The relationship that has just been created and added to the model
        """
        return self.get_model().add_relationship(self, destination, description, technology, interaction_style)

    def delivers(self, destination, description, technology=None, interaction_style=None):
        """Adds a unidirectional "uses" style relationship between this element and a person.

        Args:
            destination: The target of the relationship
            description: A description of the relationship (e.g. "uses", "gets data from", "sends data to")
            technology:  The technology details (e.g. JSON/HTTPS)
            interaction_style: The interaction style (sync vs async)

        Returns: The relationship that has just been created and added to the model
        """

    def has_afferent_relationships(self):
        """Determines whether this element has afferent (incoming) relationships.
        """
        return any(r.get_destination() == self for r in self.get_model().get_relationships())

    def has_efferent_relationships(self, element):
        return self.get_efferent_relationship_with(element) is not None

    def get_efferent_relationship_with(self, element):
        next((r for r in self._relationships if r.get_destination() == element), None)

    def has(self, relationship):
        return relationship in self._relationships

    def add_relationship(self, relationship):
        self._relationships.add(relationship)

    def __str__(self):
        return "{{{id} | {name} | {description}}}".format(
            id=self.get_id(),
            name=self.get_name(),
            description=self.get_description())

    # TODO: We should probably override __hash__ here too. Java has the same rule that if you
    # TODO: override .equals() you must ensure objects have the same .hashCode(), although the
    # TODO: Java Structurizr does not do this. Possibly an upstream bug.

    def __eq__(self, rhs):
        if self is rhs:
            return True

        if not isinstance(0, type(self)):
            return NotImplemented

        return self.get_canonical_name() == rhs.get_canonical_name()

    def __ne__(self, rhs):
        return not (self == rhs)
コード例 #4
0
class Model:
    def __init__(self):
        self._id_generator = _SequentialIntegerGeneratorStrategy()
        self._elements_by_id = {}
        self._relationships_by_id = {}
        self._enterprise = None
        self._people = OrderedSet()
        self._software_systems = OrderedSet()

    def get_enterprise(self):
        return self._enterprise

    def set_enterprise(self, enterprise):
        if not isinstance(enterprise, Enterprise):
            raise TypeError("{!r} is not an {}".format(enterprise,
                                                       Enterprise.__name__))
        self._enterprise = enterprise

    def add_software_system(self,
                            name,
                            description,
                            location=Location.UNSPECIFIED):
        if self.get_software_system_with_name(name) is not None:
            raise ValueError(
                "A software system named {} already exists".format(name))
        software_system = SoftwareSystem()
        software_system.set_location(location)
        software_system.set_name(name)
        software_system.set_description(description)
        self._software_systems.add(software_system)
        software_system.set_id(self._id_generator.generate_id(software_system))
        self._add_element_to_internal_structures(software_system)
        return software_system

    def add_person(self, name, description, location=Location.UNSPECIFIED):
        if self.get_person_with_name(name) is not None:
            raise ValueError("A person named {} already exists".format(name))
        person = Person()
        person.set_location(location)
        person.set_name(name)
        person.set_description(description)
        self._people.add(person)
        person.set_id(self._id_generator.generate_id(person))
        self._add_element_to_internal_structures(person)
        return person

    def add_container(self, software_system, name, description, technology):
        if not isinstance(software_system, SoftwareSystem):
            raise TypeError("{} is not a {}".format(software_system,
                                                    SoftwareSystem.__name__))
        if self.get_container_with_name(name) is not None:
            raise ValueError(
                "A software system named {} already exists".format(name))
        container = Container()
        container.set_name(name)
        container.set_description(description)
        container.set_technology(technology)
        container.set_parent(software_system)
        software_system.add_existing_container(container)
        container.set_id(self._id_generator.generate_id(container))
        self._add_element_to_internal_structures(container)

    def add_component_of_type(self, container, name, type_name, description,
                              technology):
        if not isinstance(container, Container):
            raise TypeError("{} is not a {}".format(container,
                                                    Container.__name__))
        component = Component()
        component.set_name(name)
        component.set_type(type_name)
        component.set_description(description)
        component.set_technology(technology)
        component.set_parent(container)
        container.add_existing_component(component)
        component.set_id(self._id_generator.generate_id(component))
        self._add_element_to_internal_structures(component)

    def add_component(self, container, name, description):
        if not isinstance(container, Container):
            raise TypeError("{} is not a {}".format(container,
                                                    Container.__name__))
        component = Component()
        component.set_name(name)
        component.set_description(description)
        component.set_parent(container)
        container.add_existing_component(component)
        component.set_id(self._id_generator.generate_id(component))
        self._add_element_to_internal_structures(component)

    def add_relationship(self,
                         source,
                         destination,
                         description,
                         technology=None,
                         interaction_style=InteractionStyle.SYNCHRONOUS):
        relationship = Relationship(source, destination, description,
                                    technology, interaction_style)
        if self.add_existing_relationship(relationship):
            return relationship
        return None

    def add_existing_relationship(self, relationship):
        if not relationship.get_source().has(relationship):
            relationship.set_id(self._id_generator.generate_id(relationship))
            relationship.get_source().add_relationship(relationship)
            self._add_relationship_to_internal_structures(relationship)
            return True
        return False

    def _add_element_to_internal_structures(self, element):
        self._elements_by_id[element.get_id()] = element
        element.set_model(self)
        self._id_generator.found(element.get_id())

    def _add_relationship_to_internal_structures(self, relationship):
        self._relationships_by_id[relationship.get_id()] = relationship
        self._id_generator.found(relationship.get_id())

    def get_elements(self):
        return set(self._elements_by_id.values()
                   )  # TODO: Returning a copy again here?

    def get_element(self, id):
        return self._elements_by_id[id]

    def get_relationships(self):
        return set(self._relationships_by_id.values())

    def get_relationship(self, id):
        return self._relationships_by_id[id]

    def get_people(self):
        return self._people.copy()

    def get_software_systems(self):
        return self._software_systems.copy()

    # TODO: Omitting the hydrate stuff for now until I have a better understanding

    def contains(self, element):
        return element in self._elements_by_id.values()

    def get_software_system_with_name(self, name):
        return next(
            (ss for ss in self._software_systems if ss.get_name() == name),
            None)

    def get_software_system_with_id(self, id):
        return next((ss for ss in self._software_systems if ss.get_id() == id),
                    None)

    def get_person_with_name(self, name):
        return next((p for p in self._people if p.get_name() == name), None)

    def add_implicit_relationships(self):
        implicit_relationships = set()

        for relationship in self.get_relationships():
            source = relationship.get_source()
            destination = relationship.get_destination()

            while source != None:
                while destination != None:
                    if not source.has_efferent_relationships_with(destination):
                        if self._propagated_relationship_is_allowed(
                                source, destination):
                            implicit_relationship = self.add_relationship(
                                source, destination, "")
                            if implicit_relationship is not None:
                                implicit_relationship.add(
                                    implicit_relationship)
                    destination = destination.get_parent()
                destination = relationship.get_destination()
                source = source.get_parent()

        return implicit_relationships

    def _propagated_relationship_is_allowed(self, source, destination):
        if source == destination:
            return False

        if source.get_parent() is not None:
            if destination == source.get_parent():
                return False

            if source.get_parent().get_parent() is not None:
                if destination == source.get_parent().get_parent():
                    return False

        if destination.get_parent() is not None:
            if source == destination.get_parent():
                return False

            if destination.get_parent().get_parent() is not None:
                if source == destination.get_parent().get_parent():
                    return False

        return True

    def is_empty(self):
        return (len(self._people) != 0) or (len(self._software_systems) != 0)