[ 
https://issues.apache.org/jira/browse/TINKERPOP-3261?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18094636#comment-18094636
 ] 

ASF GitHub Bot commented on TINKERPOP-3261:
-------------------------------------------

spmallette commented on code in PR #3483:
URL: https://github.com/apache/tinkerpop/pull/3483#discussion_r3545955917


##########
tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerVertex.java:
##########
@@ -54,31 +57,150 @@ public class TinkerVertex extends TinkerElement implements 
Vertex {
     private boolean allowNullPropertyValues;
     private final boolean isTxMode;
 
+    /**
+     * Multi-label storage for this vertex. Starts as an immutable set 
(lightweight) and is
+     * upgraded to a mutable ConcurrentHashMap-backed set on first label 
mutation.
+     */
+    protected Set<String> vertexLabels;
+
     protected TinkerVertex(final Object id, final String label, final 
AbstractTinkerGraph graph) {
-        super(id, label);
-        this.graph = graph;
-        this.isTxMode = graph instanceof TinkerTransactionGraph;
-        this.allowNullPropertyValues = 
graph.features().vertex().supportsNullPropertyValues();
+        this(id, Collections.singleton(label != null ? label : 
Vertex.DEFAULT_LABEL), graph, -1);
     }
 
     protected TinkerVertex(final Object id, final String label, final 
AbstractTinkerGraph graph, final long currentVersion) {
-        super(id, label, currentVersion);
+        this(id, Collections.singleton(label != null ? label : 
Vertex.DEFAULT_LABEL), graph, currentVersion);
+    }
+
+    /**
+     * Constructs a TinkerVertex with multiple labels.
+     */
+    protected TinkerVertex(final Object id, final Set<String> labels, final 
AbstractTinkerGraph graph) {
+        this(id, labels, graph, -1);
+    }
+
+    /**
+     * Canonical constructor. Constructs a TinkerVertex with multiple labels 
and a specific version (for transactional graphs).
+     * Uses a single-switch pattern to handle default label injection per the 
configured cardinality.
+     */
+    protected TinkerVertex(final Object id, final Set<String> labels, final 
AbstractTinkerGraph graph, final long currentVersion) {
+        super(id, null, currentVersion);  // label field set below
         this.graph = graph;
         this.isTxMode = graph instanceof TinkerTransactionGraph;
         this.allowNullPropertyValues = 
graph.features().vertex().supportsNullPropertyValues();
+
+        // Build the initial label set. Use lightweight immutable sets when 
possible.
+        final Set<String> initial = new LinkedHashSet<>();
+        switch (graph.vertexLabelCardinality) {
+            case ONE:
+                // Exactly 1 label: use provided or default
+                if (labels != null && !labels.isEmpty())
+                    initial.addAll(labels);
+                else
+                    initial.add(graph.defaultVertexLabel);
+                break;
+            case ONE_OR_MORE:
+                // Default label always present alongside any user labels
+                initial.add(graph.defaultVertexLabel);
+                if (labels != null) initial.addAll(labels);
+                break;
+            case ZERO_OR_MORE:
+                if (labels != null) initial.addAll(labels);
+                break;
+        }
+
+        // Validate the resulting set conforms to cardinality
+        
LabelCardinalityValidator.validateCreation(graph.vertexLabelCardinality, 
initial);
+
+        // Store as immutable — will be upgraded on first mutation via 
ensureMutableLabels()
+        this.vertexLabels = initial.size() <= 1
+                ? (initial.isEmpty() ? Collections.emptySet() : 
Collections.singleton(initial.iterator().next()))
+                : Collections.unmodifiableSet(initial);
+
+        this.label = this.vertexLabels.isEmpty() ? "" : 
this.vertexLabels.iterator().next();
+    }
+
+    /**
+     * Upgrades the label set to a mutable ConcurrentHashMap-backed set on 
first mutation.
+     * This is a one-time cost per vertex that actually needs label mutation.
+     */
+    private void ensureMutableLabels() {

Review Comment:
   TinkerGraph isn't built for concurrency i guess, but it might be good to 
update the javadoc to make it clear that we actively decided that concurrent 
label mutation on the same vertex is not safe.





> Enable multiple label support on vertex with configurable label cardinality
> ---------------------------------------------------------------------------
>
>                 Key: TINKERPOP-3261
>                 URL: https://issues.apache.org/jira/browse/TINKERPOP-3261
>             Project: TinkerPop
>          Issue Type: Task
>    Affects Versions: 4.0.0
>            Reporter: Yang Xia
>            Priority: Major
>
> Vertices are currently limited to a single immutable label assigned at 
> creation. This prevents modeling common real-world scenarios where entities 
> naturally belong to multiple categories (e.g., a person who is both an 
> employee and a manager).
>   
> Introduce a configurable LabelCardinality that controls how many labels a 
> vertex may have and whether they can be mutated after creation. Three 
> proposed modes: ONE (current behavior, default), ONE_OR_MORE (mutable, 
> minimum one), ZERO_OR_MORE (fully flexible).
>   
> New steps:
>   
> - labels() — flatMap step emitting each label as a traverser
> - addLabel(String, String...) — add labels to a vertex
> - dropLabel(String, String...) — remove specific labels
> - dropLabels() — remove all labels
> Edge labels remain at cardinality ONE. The infrastructure would support 
> future edge multi-label enablement without wire format changes.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to