Class: Lutaml::Cli::ElementIdentifier

Inherits:
Object
  • Object
show all
Defined in:
lib/lutaml/cli/element_identifier.rb

Overview

ElementIdentifier parses and manages element references

Provides a unified syntax for referring to UML elements:

  • “package:ModelRoot::Core”

  • “class:ModelRoot::Core::Building”

  • “diagram:ClassDiagram1”

  • “attribute:ModelRoot::Core::Building::name”

Supports auto-detection when type prefix is omitted.

Examples:

Parse an identifier with explicit type

id = ElementIdentifier.parse("class:Building")
id.type # => :class
id.path # => "Building"

Parse an identifier with auto-detection

id = ElementIdentifier.parse("ModelRoot::Core::Building")
id.type # => :class (auto-detected from pattern)
id.path # => "ModelRoot::Core::Building"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type, path) ⇒ ElementIdentifier

Initialize an identifier

Parameters:

  • type (Symbol)

    Element type

  • path (String)

    Element path/name



64
65
66
67
# File 'lib/lutaml/cli/element_identifier.rb', line 64

def initialize(type, path)
  @type = type
  @path = path
end

Instance Attribute Details

#pathObject (readonly)

Returns the value of attribute path.



27
28
29
# File 'lib/lutaml/cli/element_identifier.rb', line 27

def path
  @path
end

#typeObject (readonly)

Returns the value of attribute type.



27
28
29
# File 'lib/lutaml/cli/element_identifier.rb', line 27

def type
  @type
end

Class Method Details

.detect_type(identifier) ⇒ Symbol

Detect element type from identifier pattern

Uses heuristics to determine type:

  • Multiple

    separators → likely a class

  • Starts with uppercase → likely a class or package

  • Contains “Diagram” → likely a diagram

  • Otherwise → package (safest default)

Parameters:

  • identifier (String)

    Identifier without type prefix

Returns:

  • (Symbol)

    Detected type



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/lutaml/cli/element_identifier.rb', line 96

def self.detect_type(identifier) # rubocop:disable Metrics/MethodLength
  # Check for diagram patterns
  return :diagram if identifier.match?(/diagram/i)

  # Count package separators
  separator_count = identifier.scan("::").size

  case separator_count
  when 0
    # No separators - single name
    # Could be package, class, or diagram
    if identifier.match?(/^[A-Z]/)
      # Starts with uppercase - likely a class or package name
      # Default to package as it's more general
      :package
    else
      # Lowercase start - could be attribute or diagram name
      :diagram
    end
  when 1
    # One separator - likely Package::Class
    :class
  when 2..Float::INFINITY
    # Multiple separators - likely fully qualified class name
    # e.g., ModelRoot::Package::Class
    :class
  else
    # Default
    :package
  end
end

.has_type_prefix?(identifier) ⇒ Boolean

Check if this identifier has an explicit type prefix

Parameters:

  • identifier (String)

    Identifier string

Returns:

  • (Boolean)

    True if has explicit type prefix



80
81
82
83
84
# File 'lib/lutaml/cli/element_identifier.rb', line 80

def self.has_type_prefix?(identifier)
  identifier.include?(":") &&
    ResourceRegistry.type_registered?(identifier.split(":",
                                                       2).first.to_sym)
end

.parse(identifier) ⇒ ElementIdentifier

Parse an element identifier string

or just “path” registered

Parameters:

  • identifier (String)

    Element identifier in format “type:path”

Returns:

Raises:

  • (ArgumentError)

    If identifier is invalid or type is not



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/lutaml/cli/element_identifier.rb', line 36

def self.parse(identifier) # rubocop:disable Metrics/MethodLength
  if identifier.nil? || identifier.empty?
    raise ArgumentError,
          "Identifier cannot be nil or empty"
  end

  if identifier.include?(":")
    type, path = identifier.split(":", 2)
    type_sym = type.to_sym

    unless ResourceRegistry.type_registered?(type_sym)
      raise ArgumentError, "Unknown element type: #{type}. " \
                           "Valid types: " \
                           "#{ResourceRegistry.types.join(', ')}"
    end

    new(type_sym, path)
  else
    # Auto-detect type from pattern
    detected_type = detect_type(identifier)
    new(detected_type, identifier)
  end
end

Instance Method Details

#parent_pathString?

Get the parent path (everything before last ::)

Returns:

  • (String, nil)

    Parent path or nil if not qualified



145
146
147
148
149
150
# File 'lib/lutaml/cli/element_identifier.rb', line 145

def parent_path
  return nil unless qualified?

  parts = @path.split("::")
  parts[0...-1].join("::")
end

#qualified?Boolean

Check if identifier is a qualified name (contains ::)

Returns:

  • (Boolean)

    True if qualified



131
132
133
# File 'lib/lutaml/cli/element_identifier.rb', line 131

def qualified?
  @path.include?("::")
end

#simple_nameString

Get the simple name (last component after ::)

Returns:

  • (String)

    Simple name



138
139
140
# File 'lib/lutaml/cli/element_identifier.rb', line 138

def simple_name
  qualified? ? @path.split("::").last : @path
end

#to_hHash

Convert to hash representation

Returns:

  • (Hash)

    Hash with type and path keys



155
156
157
158
159
160
161
162
# File 'lib/lutaml/cli/element_identifier.rb', line 155

def to_h
  {
    type: @type,
    path: @path,
    simple_name: simple_name,
    qualified: qualified?,
  }
end

#to_sString

Get a human-readable string representation

Returns:

  • (String)

    String representation



72
73
74
# File 'lib/lutaml/cli/element_identifier.rb', line 72

def to_s
  "#{type}:#{path}"
end