@@ -110,6 +110,76 @@ def _resolve_references(self, new_obj):
110110 resolve_references = make_resolve_references_traverser (new_obj )
111111 self .traverse (resolve_references )
112112
113+ def copy (self , target_doc = None , target_namespace = None ): # pylint: disable=R0912
114+
115+ # Delete this method in v1.1
116+ warnings .warn ('Use sbol3.copy() instead' , DeprecationWarning )
117+
118+ new_uri = self .identity
119+
120+ # If caller specified a target_namespace argument, then copy the object into this
121+ # new namespace.
122+ if target_namespace :
123+
124+ # Map the identity of self into the target namespace
125+ if hasattr (self , 'identity' ):
126+ old_uri = self .identity
127+ new_uri = replace_namespace (old_uri , target_namespace , self .getTypeURI ())
128+
129+ try :
130+ builder = BUILDER_REGISTER [self .type_uri ]
131+ except KeyError :
132+ logging .warning (f'No builder found for { self .type_uri } ; assuming { self .__class__ .__name__ } ' )
133+ builder = self .__class__
134+ new_obj = builder (** dict (identity = new_uri , type_uri = self .type_uri ))
135+
136+ # Copy properties
137+ for property_uri , value_store in self ._properties .items ():
138+ new_obj ._properties [property_uri ] = value_store .copy ()
139+
140+ # TODO: Map into new namespace
141+
142+ # Assign the new object to the target Document
143+ if target_doc is not None :
144+ try :
145+ target_doc .add (new_obj )
146+ except TypeError :
147+ pass # object is not TopLevel
148+
149+ # When an object is simply being cloned, the value of wasDerivedFrom should be
150+ # copied exactly as is from self. However, when copy is being used to generate
151+ # a new entity, the wasDerivedFrom should point back to self.
152+ if self .identity == new_obj .identity :
153+ new_obj .derived_from = self .derived_from
154+ else :
155+ new_obj .derived_from = self .identity
156+
157+ # Copy child objects recursively
158+ for property_uri , object_list in self ._owned_objects .items ():
159+ for o in object_list :
160+ o_copy = o .copy (target_doc , target_namespace )
161+ new_obj ._owned_objects [property_uri ].append (o_copy )
162+ o_copy .parent = self
163+
164+ # After we have copied all the owned objects, copy the referenced objects
165+ # and attempt to resolve the references
166+ if target_doc :
167+ for property_uri , object_store in self ._referenced_objects .items ():
168+ for o in object_store :
169+ referenced_obj = target_doc .find (o .identity )
170+ if referenced_obj :
171+ new_obj ._referenced_objects [property_uri ].append (referenced_obj )
172+ else :
173+ new_obj ._referenced_objects [property_uri ].append (SBOLObject (o .identity ))
174+ else :
175+ # If the copy does not belong to a Document, then treat all references
176+ # like external references
177+ for property_uri , object_store in self ._referenced_objects .items ():
178+ for o in object_store :
179+ new_obj ._referenced_objects [property_uri ].append (SBOLObject (o .identity ))
180+
181+ return new_obj
182+
113183 def lookup (self ):
114184 return self
115185
0 commit comments