Skip to content

Commit 0a76886

Browse files
committed
Partial implementation of ModelSpecConverter
Change ModelCopyManager to remove type parameter Signed-off-by: Gary O'Neall <gary@sourceauditor.com>
1 parent 5502454 commit 0a76886

9 files changed

Lines changed: 250 additions & 101 deletions

File tree

src/main/java/org/spdx/library/ModelCopyConverter.java

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,17 @@
1717
*/
1818
package org.spdx.library;
1919

20+
import java.util.HashMap;
21+
import java.util.Map;
22+
import java.util.Objects;
23+
24+
import org.spdx.core.IndividualUriValue;
25+
import org.spdx.core.InvalidSPDXAnalysisException;
26+
import org.spdx.core.SimpleUriValue;
27+
import org.spdx.core.TypedValue;
28+
import org.spdx.storage.IModelStore;
29+
import org.spdx.storage.PropertyDescriptor;
30+
2031
/**
2132
* @author Gary O'Neall
2233
*
@@ -25,8 +36,133 @@
2536
*/
2637
public class ModelCopyConverter {
2738

39+
static Map<String, Map<String, ModelSpecConverter>> SPEC_CONVERTER_MAP = new HashMap<>();
40+
2841
private ModelCopyConverter() {
2942
// static class
3043
}
3144

45+
/**
46+
* @param fromTv typed value to convert from
47+
* @param toSpecVersion for the return converted byp
48+
* @return the type to be used for the toSpecVersion of the <code>fromTv.getType()</code>
49+
* @throws InvalidSPDXAnalysisException
50+
*/
51+
public static String convertType(TypedValue fromTv,
52+
String toSpecVersion) throws InvalidSPDXAnalysisException {
53+
if (versionsCompatible(fromTv.getSpecVersion(), toSpecVersion)) {
54+
return fromTv.getType();
55+
} else {
56+
ModelSpecConverter specConverter = getSpecConverter(fromTv.getSpecVersion(), toSpecVersion);
57+
return specConverter.convertType(fromTv.getType());
58+
}
59+
}
60+
61+
/**
62+
* @param fromSpecVersion from spec version
63+
* @param toSpecVersion to spec version
64+
* @return true if no conversion is needed from the fromSpecVersion to the toSpecVersion
65+
*/
66+
public static boolean versionsCompatible(String fromSpecVersion,
67+
String toSpecVersion) {
68+
Objects.requireNonNull(fromSpecVersion);
69+
Objects.requireNonNull(toSpecVersion);
70+
return fromSpecVersion.startsWith("SPDX-2") && toSpecVersion.startsWith("SPDX-2") ||
71+
fromSpecVersion.startsWith("3.0.") && toSpecVersion.startsWith("3.0.");
72+
}
73+
74+
/**
75+
* @param fromSpecVersion from spec version
76+
* @param toSpecVersion to spec version
77+
* @return the model spec converter from the fromSpecVersion to the toSpecVersion
78+
* @throws InvalidSPDXAnalysisException if a converter is not found
79+
*/
80+
private static ModelSpecConverter getSpecConverter(String fromSpecVersion,
81+
String toSpecVersion) throws InvalidSPDXAnalysisException {
82+
Map<String, ModelSpecConverter> conversionMap = SPEC_CONVERTER_MAP.get(fromSpecVersion);
83+
if (Objects.isNull(conversionMap)) {
84+
throw new InvalidSPDXAnalysisException("No conversions for spec version "+fromSpecVersion);
85+
}
86+
ModelSpecConverter specConverter = conversionMap.get(toSpecVersion);
87+
if (Objects.isNull(specConverter)) {
88+
throw new InvalidSPDXAnalysisException("No conversion from spec version "+fromSpecVersion+" to "+toSpecVersion);
89+
}
90+
return specConverter;
91+
}
92+
93+
/**
94+
* Converts (if needed) the value then store the result in the toStore
95+
* @param toStore Model Store to copy to
96+
* @param toTV to typedValue to copy the property to
97+
* @param fromStore Model Store containing the source item
98+
* @param fromTV typedValue to copy the property from
99+
* @param fromPropDescriptor Descriptor for the property to be copied from
100+
* @param value value from the fromStore
101+
* @param toNamespace Namespace to use if an ID needs to be generated for the to object
102+
* @param modelCopyManager copyManager to use for any typedValue results
103+
* @throws InvalidSPDXAnalysisException on any issues converting or storing the value
104+
*/
105+
public static void copyConvertedPropertyValue(
106+
IModelStore toStore, TypedValue toTv, IModelStore fromStore,
107+
TypedValue fromTv, PropertyDescriptor fromPropDescriptor,
108+
Object value, String toNamespace,
109+
ModelCopyManager modelCopyManager) throws InvalidSPDXAnalysisException {
110+
if (versionsCompatible(fromTv.getSpecVersion(), toTv.getSpecVersion())) {
111+
112+
if (value instanceof IndividualUriValue) {
113+
toStore.setValue(toTv.getObjectUri(), fromPropDescriptor, new SimpleUriValue((IndividualUriValue)value));
114+
} else if (value instanceof TypedValue) {
115+
TypedValue valueTv = (TypedValue)value;
116+
if (fromStore.equals(toStore)) {
117+
toStore.setValue(toTv.getObjectUri(), fromPropDescriptor, valueTv);
118+
} else {
119+
toStore.setValue(toTv.getObjectUri(), fromPropDescriptor,
120+
modelCopyManager.copy(toStore, fromStore, valueTv.getObjectUri(),
121+
toTv.getSpecVersion(), toNamespace));
122+
}
123+
} else {
124+
toStore.setValue(toTv.getObjectUri(), fromPropDescriptor, value);
125+
}
126+
} else {
127+
throw new InvalidSPDXAnalysisException("Unimplemented");
128+
}
129+
}
130+
131+
/**
132+
* Converts (if needed) the value then adds the result to a collection in the toStore
133+
* @param toStore Model Store to copy to
134+
* @param toTV to typedValue to copy the property to
135+
* @param fromStore Model Store containing the source item
136+
* @param fromTV typedValue to copy the property from
137+
* @param fromPropDescriptor Descriptor for the property to be copied from
138+
* @param value value from the fromStore
139+
* @param toNamespace Namespace to use if an ID needs to be generated for the to object
140+
* @param modelCopyManager copyManager to use for any typedValue results
141+
* @throws InvalidSPDXAnalysisException on any issues converting or storing the value
142+
*/
143+
public static void addConvertedPropertyValue(
144+
IModelStore toStore, TypedValue toTv, IModelStore fromStore,
145+
TypedValue fromTv, PropertyDescriptor fromPropDescriptor,
146+
Object value, String toNamespace,
147+
ModelCopyManager modelCopyManager) throws InvalidSPDXAnalysisException {
148+
if (versionsCompatible(fromTv.getSpecVersion(), toTv.getSpecVersion())) {
149+
if (value instanceof IndividualUriValue) {
150+
toStore.addValueToCollection(toTv.getObjectUri(), fromPropDescriptor, new SimpleUriValue((IndividualUriValue)value));
151+
} else if (value instanceof TypedValue) {
152+
TypedValue valueTv = (TypedValue)value;
153+
if (fromStore.equals(toStore)) {
154+
toStore.addValueToCollection(toTv.getObjectUri(), fromPropDescriptor, valueTv);
155+
} else {
156+
toStore.addValueToCollection(toTv.getObjectUri(), fromPropDescriptor,
157+
modelCopyManager.copy(toStore, fromStore, valueTv.getObjectUri(),
158+
toTv.getSpecVersion(), toNamespace));
159+
}
160+
} else {
161+
toStore.addValueToCollection(toTv.getObjectUri(), fromPropDescriptor, value);
162+
}
163+
} else {
164+
throw new InvalidSPDXAnalysisException("Unimplemented");
165+
}
166+
}
167+
32168
}

src/main/java/org/spdx/library/ModelCopyManager.java

Lines changed: 52 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public class ModelCopyManager implements IModelCopyManager {
6161
new ConcurrentHashMap<>();
6262

6363
/**
64-
* Create a CompatV2ModelCopyManager with default options
64+
* Create a ModelCopyManager with default options
6565
*/
6666
public ModelCopyManager() {
6767
// Required empty constructor
@@ -118,122 +118,104 @@ public String putCopiedId(IModelStore fromStore, String fromObjectUri, IModelSto
118118
* @param fromStore Model Store containing the source item
119119
* @param fromDocumentUri Document URI for the source item
120120
* @param fromId ID source ID
121-
* @param type Type to copy
122121
* @param toSpecVersion version of the spec the to value should comply with
123122
* @param toNamespace Namespace to use if an ID needs to be generated for the to object
124123
* @throws InvalidSPDXAnalysisException
125124
*/
126125
public void copy(IModelStore toStore, String toObjectUri,
127-
IModelStore fromStore, String fromObjectUri,
128-
String type, String toSpecVersion,
126+
IModelStore fromStore, String fromObjectUri, String toSpecVersion,
129127
@Nullable String toNamespace) throws InvalidSPDXAnalysisException {
130128
Objects.requireNonNull(toStore, "ToStore can not be null");
131129
Objects.requireNonNull(toObjectUri, "To Object URI can not be null");
132130
Objects.requireNonNull(fromStore, "FromStore can not be null");
133131
Objects.requireNonNull(fromObjectUri, "From ObjectUri can not be null");
134-
Objects.requireNonNull(type, "Type can not be null");
135132
Objects.requireNonNull(toSpecVersion, "To spec version can not be null");
136133
if (fromStore.equals(toStore) && fromObjectUri.equals(toObjectUri)) {
137134
return; // trying to copy the same thing!
138135
}
139-
if (!toStore.exists(toObjectUri)) {
140-
toStore.create(new TypedValue(toObjectUri, type, toSpecVersion));
136+
Optional<TypedValue> fromTv = fromStore.getTypedValue(fromObjectUri);
137+
if (!fromTv.isPresent()) {
138+
throw new InvalidSPDXAnalysisException("Missing from object URI "+fromObjectUri);
139+
}
140+
String toType = ModelCopyConverter.convertType(fromTv.get(), toSpecVersion);
141+
Optional<TypedValue> toTv = toStore.getTypedValue(toObjectUri);
142+
if (toTv.isPresent()) {
143+
if (!toType.equals(toTv.get().getType())) {
144+
throw new InvalidSPDXAnalysisException("Incompatible type for copy. Stored type is " +
145+
toTv.get().getType() + " and requested type is "+toType);
146+
}
147+
} else {
148+
toTv = Optional.of(new TypedValue(toObjectUri, toType, toSpecVersion));
149+
toStore.create(toTv.get());
141150
}
142151
putCopiedId(fromStore, fromObjectUri, toStore, toObjectUri);
143-
List<PropertyDescriptor> propertyDescriptors = fromStore.getPropertyValueDescriptors(fromObjectUri);
144-
for (PropertyDescriptor propDesc:propertyDescriptors) {
152+
153+
List<PropertyDescriptor> fromPropertyDescriptors = fromStore.getPropertyValueDescriptors(fromObjectUri);
154+
for (PropertyDescriptor propDesc:fromPropertyDescriptors) {
145155
if (fromStore.isCollectionProperty(fromObjectUri, propDesc)) {
146-
copyCollectionProperty(toStore, toObjectUri, fromStore, fromObjectUri, propDesc, toSpecVersion, toNamespace);
156+
copyCollectionProperty(toStore, toTv.get(), fromStore, fromTv.get(), propDesc, toNamespace);
147157
} else {
148-
copyIndividualProperty(toStore, toObjectUri, fromStore, fromObjectUri, propDesc, toSpecVersion, toNamespace);
158+
copyIndividualProperty(toStore, toTv.get(), fromStore, fromTv.get(), propDesc, toNamespace);
149159
}
150160
}
151161
}
152162

153163
/**
154164
* Copies an individual property value (non-collection property value)
155165
* @param toStore Model Store to copy to
156-
* @param toObjectUri to object URI to copy to
166+
* @param toTV to typedValue to copy the property to
157167
* @param fromStore Model Store containing the source item
158-
* @param fromObjectUri object to copy from
159-
* @param propDescriptor Descriptor for the property
160-
* @param toSpecVersion Version of the SPDX spec the to value complies with
168+
* @param fromTV typedValue to copy the property from
169+
* @param fromPropDescriptor Descriptor for the property to be copied from
161170
* @param toNamespace Namespace to use if an ID needs to be generated for the to object
162171
* @throws InvalidSPDXAnalysisException
163172
*/
164-
private void copyIndividualProperty(IModelStore toStore, String toObjectUri, IModelStore fromStore,
165-
String fromObjectUri, PropertyDescriptor propDescriptor,
166-
String toSpecVersion, @Nullable String toNamespace) throws InvalidSPDXAnalysisException {
173+
private void copyIndividualProperty(IModelStore toStore, TypedValue toTv, IModelStore fromStore,
174+
TypedValue fromTv, PropertyDescriptor fromPropDescriptor,
175+
@Nullable String toNamespace) throws InvalidSPDXAnalysisException {
167176
IModelStoreLock fromStoreLock = fromStore.enterCriticalSection(false);
168177
//Note: we use a write lock since the RDF store may end up creating a property to check if it is a collection
169178
Optional<Object> result = Optional.empty();
170179
try {
171-
if (fromStore.isCollectionProperty(fromObjectUri, propDescriptor)) {
172-
throw new InvalidSPDXAnalysisException("Property "+propDescriptor+" is a collection type");
180+
if (fromStore.isCollectionProperty(fromTv.getObjectUri(), fromPropDescriptor)) {
181+
throw new InvalidSPDXAnalysisException("Property "+fromPropDescriptor+" is a collection type");
173182
}
174-
result = fromStore.getValue(fromObjectUri, propDescriptor);
183+
result = fromStore.getValue(fromTv.getObjectUri(), fromPropDescriptor);
175184
} finally {
176185
fromStoreLock.unlock();
177186
}
178-
if (result.isPresent()) {
179-
if (result.get() instanceof IndividualUriValue) {
180-
toStore.setValue(toObjectUri, propDescriptor, new SimpleUriValue((IndividualUriValue)result.get()));
181-
} else if (result.get() instanceof TypedValue) {
182-
TypedValue tv = (TypedValue)result.get();
183-
if (fromStore.equals(toStore)) {
184-
toStore.setValue(toObjectUri, propDescriptor, tv);
185-
} else {
186-
toStore.setValue(toObjectUri, propDescriptor,
187-
copy(toStore, fromStore, tv.getObjectUri(), tv.getType(), toSpecVersion, toNamespace));
188-
}
189-
} else {
190-
toStore.setValue(toObjectUri, propDescriptor, result.get());
191-
}
192-
}
187+
if (result.isPresent()) {
188+
ModelCopyConverter.copyConvertedPropertyValue(toStore, toTv, fromStore, fromTv, fromPropDescriptor, result.get(), toNamespace, this);
189+
}
193190
}
194191

195192
/**
196193
* Copies a property which is is a collection
197194
* @param toStore Model Store to copy to
198-
* @param toObjectUri URI to copy to
195+
* @param toTv typed value to copy to
199196
* @param fromStore Model Store containing the source item
200-
* @param fromDocumentUri Object URI to copy from
201-
* @param propDescriptor Descriptor for the property
202-
* @param toSpecVersion Version of the SPDX spec the to value complies with
197+
* @param fromTv typed value to copy from
198+
* @param fromPropDescriptor Descriptor for the property to be copied from
203199
* @param toNamespace Namespace to use if an ID needs to be generated for the to object
204-
* @throws InvalidSPDXAnalysisException
200+
* @throws InvalidSPDXAnalysisException on conversion or store error
205201
*/
206-
private void copyCollectionProperty(IModelStore toStore, String toObjectUri, IModelStore fromStore,
207-
String fromObjectUri, PropertyDescriptor propDescriptor,
208-
String toSpecVersion, @Nullable String toNamespace) throws InvalidSPDXAnalysisException {
202+
private void copyCollectionProperty(IModelStore toStore, TypedValue toTv, IModelStore fromStore,
203+
TypedValue fromTv, PropertyDescriptor fromPropDescriptor,
204+
@Nullable String toNamespace) throws InvalidSPDXAnalysisException {
209205
IModelStoreLock fromStoreLock = fromStore.enterCriticalSection(false);
210206
//Note: we use a write lock since the RDF store may end up creating a property to check if it is a collection
211207
Iterator<Object> fromListIter = null;
212208
try {
213-
if (!fromStore.isCollectionProperty(fromObjectUri, propDescriptor)) {
214-
throw new InvalidSPDXAnalysisException("Property "+propDescriptor+" is not a collection type");
209+
if (!fromStore.isCollectionProperty(fromTv.getObjectUri(), fromPropDescriptor)) {
210+
throw new InvalidSPDXAnalysisException("Property "+fromPropDescriptor+" is not a collection type");
215211
}
216-
fromListIter = fromStore.listValues(fromObjectUri, propDescriptor);
212+
fromListIter = fromStore.listValues(fromTv.getObjectUri(), fromPropDescriptor);
217213
} finally {
218214
fromStoreLock.unlock();
219215
}
220216
while (fromListIter.hasNext()) {
221217
Object listItem = fromListIter.next();
222-
Object toStoreItem;
223-
if (listItem instanceof IndividualUriValue) {
224-
toStoreItem = new SimpleUriValue((IndividualUriValue)listItem);
225-
} else if (listItem instanceof TypedValue) {
226-
TypedValue listItemTv = (TypedValue)listItem;
227-
if (toStore.equals(fromStore)) {
228-
toStoreItem = listItemTv;
229-
} else {
230-
toStoreItem = copy(toStore, fromStore, listItemTv.getObjectUri(),
231-
listItemTv.getType(), toSpecVersion, toNamespace);
232-
}
233-
} else {
234-
toStoreItem = listItem;
235-
}
236-
toStore.addValueToCollection(toObjectUri, propDescriptor, toStoreItem);
218+
ModelCopyConverter.addConvertedPropertyValue(toStore, toTv, fromStore, fromTv, fromPropDescriptor, listItem, toNamespace, this);
237219
}
238220
}
239221

@@ -242,28 +224,30 @@ private void copyCollectionProperty(IModelStore toStore, String toObjectUri, IMo
242224
* @param toStore Model Store to copy to
243225
* @param fromStore Model Store containing the source item
244226
* @param sourceUri URI for the Source object
245-
* @param type Type to copy
246227
* @param toSpecVersion Version of the SPDX spec the to value complies with
247228
* @param toNamespace Namespace to use if an ID needs to be generated for the to object - must be a unique prefix to the store
248229
* @return Object URI for the copied object
249230
* @throws InvalidSPDXAnalysisException
250231
*/
251232
public TypedValue copy(IModelStore toStore, IModelStore fromStore,
252-
String sourceUri, String type, String toSpecVersion, @Nullable String toNamespace) throws InvalidSPDXAnalysisException {
233+
String sourceUri, String toSpecVersion, @Nullable String toNamespace) throws InvalidSPDXAnalysisException {
253234
Objects.requireNonNull(toStore, "To Store can not be null");
254235
Objects.requireNonNull(fromStore, "From Store can not be null");
255236
Objects.requireNonNull(sourceUri, "Source URI can not be null");
256-
Objects.requireNonNull(type, "Type can not be null");
257237
Objects.requireNonNull(toSpecVersion, "To specVersion can not be null");
258238

259239
String toObjectUri = getCopiedObjectUri(fromStore, sourceUri, toStore);
260240
if (Objects.isNull(toObjectUri)) {
241+
Optional<TypedValue> fromTv = fromStore.getTypedValue(sourceUri);
242+
if (!fromTv.isPresent()) {
243+
throw new InvalidSPDXAnalysisException(sourceUri + " does not exist in the from Store");
244+
}
261245
toObjectUri = toSpecVersion.startsWith("SPDX-2") ? sourceUriToObjectUriV2Compat(sourceUri,
262-
fromStore.getIdType(sourceUri), toStore, toNamespace, SpdxConstantsCompatV2.CLASS_EXTERNAL_DOC_REF.equals(type)) :
246+
fromStore.getIdType(sourceUri), toStore, toNamespace, SpdxConstantsCompatV2.CLASS_EXTERNAL_DOC_REF.equals(fromTv.get().getType())) :
263247
sourceUriToObjectUri(sourceUri, fromStore.getIdType(sourceUri), toStore, toNamespace);
264-
copy(toStore, toObjectUri, fromStore, sourceUri, type, toSpecVersion, toNamespace);
248+
copy(toStore, toObjectUri, fromStore, sourceUri, toSpecVersion, toNamespace);
265249
}
266-
return new TypedValue(toObjectUri, type, toSpecVersion);
250+
return toStore.getTypedValue(toObjectUri).get();
267251
}
268252

269253
/**
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* Copyright (c) 2024 Source Auditor Inc.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package org.spdx.library;
19+
20+
/**
21+
* @author Gary O'Neall
22+
*
23+
* Manages the conversion of classes and properties between 2 versions of an SPDX specification
24+
*/
25+
public class ModelSpecConverter {
26+
27+
String convertType(String fromType) {
28+
//TODO Implement
29+
return null;
30+
}
31+
32+
}

0 commit comments

Comments
 (0)