use of com.google.cloud.vision.v1p3beta1.Feature in project osate2 by osate.
the class CreateErrorPropagationPaletteCommand method createPropgationCreationOperation.
/**
* Creates an operation for creating a propagation for the target.
* @param target is the target of the propagation. It should be the context which will be the parent of the propagation
* @param init function called to finish initializing the propagation. It must set the kind or the feature or PP reference.
* @return the operation or an empty optional if a classifier could not be determined.
*/
private Optional<Operation> createPropgationCreationOperation(final BusinessObjectContext target, final BiConsumer<ErrorPropagation, ErrorModelSubclause> init) {
return ErrorModelGeUtil.getClassifierSourceBoc(target).flatMap(container -> {
final AadlPackage pkg = container.getBusinessObject(NamedElement.class).map(ne -> ne.getElementRoot()).map(root -> root instanceof AadlPackage ? ((AadlPackage) root) : null).orElseThrow(() -> new AadlGraphicalEditorException("Unable to find model"));
return ErrorModelGeUtil.createErrorModelSubclausePromptAndModifyOperation(container, () -> {
if (propagationAlreadyExists(target)) {
final String propagationOrContainmentLabel = (containment ? "containment" : "propagation");
final String inputOrOutputLabel = direction == DirectionType.IN ? "intput" : "output";
MessageDialog.openError(Display.getDefault().getActiveShell(), "Unable to create " + propagationOrContainmentLabel, "Propagation already exists. A propagation point may only have one " + inputOrOutputLabel + " error " + propagationOrContainmentLabel + " defined.");
return Optional.empty();
}
return ErrorModelUiUtil.promptForTypeSet(pkg);
}, (subclause, typeSet) -> {
final ErrorPropagation newPropagation = ErrorModelFactory.eINSTANCE.createErrorPropagation();
newPropagation.setTypeSet(typeSet);
newPropagation.setNot(containment);
newPropagation.setDirection(direction);
init.accept(newPropagation, subclause);
subclause.getPropagations().add(newPropagation);
return StepResultBuilder.create().showNewBusinessObject(target, newPropagation).build();
});
});
}
use of com.google.cloud.vision.v1p3beta1.Feature in project osate2 by osate.
the class Binpack method binPackSystem.
protected AssignmentResult binPackSystem(final SystemInstance root, Expansor expansor, LowLevelBinPacker packer, final AnalysisErrorReporterManager errManager, final SystemOperationMode som) {
existsProcessorWithMIPS = false;
existsProcessorWithoutMIPS = false;
existsThreadWithReferenceProcessor = false;
existsThreadWithoutReferenceProcessor = false;
/*
* Map from AADL ComponentInstances representing threads to
* the bin packing SoftwareNode that models the thread.
*/
final Map<ComponentInstance, AADLThread> threadToSoftwareNode = new HashMap<>();
/*
* Set of thread components. This is is the keySet of
* threadToSoftwareNode.
*/
final Set<ComponentInstance> threads = threadToSoftwareNode.keySet();
/*
* Map from AADL ComponentInstances representing threads to
* the set of AADL ComponentInstances that cannot be collocated
* with it.
*/
final Map<ComponentInstance, Set<ComponentInstance>> notCollocated = new HashMap<>();
/*
* Map from AADL ComponentInstance representing processors to
* the bin packing Processor that models them.
*/
final Map<ComponentInstance, AADLProcessor> procToHardware = new HashMap<>();
/*
* Map from AADL BusInstance representing Buses to
* The bin packing Link that models them.
*/
final Map<ComponentInstance, AADLBus> busToHardware = new HashMap<>();
/*
* One site to rule them all! We don't care about the site
* architecture, so just create one site to hold everything.
* We aren't worried about power or space issues either, so
* we just set them to 100.0 because those are nice values.
* The site accepts AADL processors.
*/
final SiteArchitecture siteArchitecture = new SiteArchitecture();
AADLProcessor ap = AADLProcessor.PROTOTYPE;
final Site theSite = new Site(100.0, 100.0, new SiteGuest[] { ap });
siteArchitecture.addSite(theSite);
/*
* The hardware is fixed based on the AADL specification, so we
* use the NoExpansionExpansor to keep the hardware from being
* generated for us.
*/
expansor.setSiteArchitecture(siteArchitecture);
/*
* Populate the problem space based on the AADL specification. First
* we walk the instance model and add all the processors. Then we
* walk the instance model again to add all the threads.
*/
OutDegreeAssignmentProblem problem1 = new OutDegreeAssignmentProblem(new OutDegreeComparator(), new BandwidthComparator(), new CapacityComparator());
problem1.setErrorReporter(new BinPackErrorReporter());
final OutDegreeAssignmentProblem problem = problem1;
// Add procs
final ForAllElement addProcessors = new ForAllElement(errManager) {
@Override
public void process(Element obj) {
ComponentInstance ci = (ComponentInstance) obj;
// the createInstance method already assigns a default MIPS if none exists
double mips = GetProperties.getProcessorMIPS(ci);
// checking consistency;
existsProcessorWithMIPS |= (mips != 0);
existsProcessorWithoutMIPS |= (mips == 0);
final AADLProcessor proc = AADLProcessor.createInstance(ci);
if (proc != null) {
System.out.println("Processor cycles Per sec:" + proc.getCyclesPerSecond());
siteArchitecture.addSiteGuest(proc, theSite);
problem.getHardwareGraph().add(proc);
// add reverse mapping
procToHardware.put(ci, proc);
}
}
};
addProcessors.processPreOrderComponentInstance(root, ComponentCategory.PROCESSOR);
/*
* Get all the links
*/
final ForAllElement addBuses = new ForAllElement(errManager) {
@Override
public void process(Element obj) {
ComponentInstance bi = (ComponentInstance) obj;
final AADLBus bus = AADLBus.createInstance(bi);
busToHardware.put(bi, bus);
}
};
addBuses.processPreOrderComponentInstance(root, ComponentCategory.BUS);
/*
* create the links between processors and busses
* (i.e., process connections)
*/
for (final Iterator<ConnectionInstance> i = root.getAllConnectionInstances().iterator(); i.hasNext(); ) {
final ConnectionInstance connInst = i.next();
if (connInst.getKind() == ConnectionKind.ACCESS_CONNECTION) {
InstanceObject src = connInst.getSource();
InstanceObject dst = connInst.getDestination();
AADLBus bus = null;
AADLProcessor processor = null;
// swap if i got them in the opposite order
if (src instanceof FeatureInstance) {
InstanceObject tmp = dst;
dst = src;
src = tmp;
}
bus = busToHardware.get(src);
FeatureInstance fi = (FeatureInstance) dst;
processor = procToHardware.get(fi.getContainingComponentInstance());
if (bus != null && processor != null) {
bus.add(processor);
processor.attachToLink(bus);
}
}
}
for (Iterator<AADLBus> iBus = busToHardware.values().iterator(); iBus.hasNext(); ) {
AADLBus bus = iBus.next();
problem.addLink(bus);
siteArchitecture.addSiteGuest(bus, theSite);
}
// Add threads
final ForAllElement addThreads = new ForAllElement(errManager) {
@Override
public void process(Element obj) {
final ComponentInstance ci = (ComponentInstance) obj;
/**
* JD - check the modes according to what was
* suggested by Dave.
*/
boolean selected = true;
if (som.getCurrentModes().size() > 0) {
selected = false;
for (ModeInstance mi : ci.getInModes()) {
if (mi == som.getCurrentModes().get(0)) {
selected = true;
}
}
}
if (!selected) {
return;
}
final AADLThread thread = AADLThread.createInstance(ci);
double refmips = GetProperties.getReferenceMIPS(ci);
// validate consistency
existsThreadWithReferenceProcessor |= (refmips != 0);
existsThreadWithoutReferenceProcessor |= (refmips == 0);
problem.getSoftwareGraph().add(thread);
// logInfo(thread.getReport());
// add reverse mapping
threadToSoftwareNode.put(ci, thread);
// Process NOT_COLLOCATED property.
RecordValue disjunctFrom = GetProperties.getNotCollocated(ci);
if (disjunctFrom == null) {
return;
}
final Set<ComponentInstance> disjunctSet = new HashSet<>();
ListValue tvl = (ListValue) PropertyUtils.getRecordFieldValue(disjunctFrom, "Targets");
for (PropertyExpression ref : tvl.getOwnedListElements()) {
/*
* Add all the instances rooted at the named instance.
* For example, the thread may be declared to be disjunct
* from another process, so we really want to be disjunct
* from the other threads contained in that process.
*/
final InstanceReferenceValue rv = (InstanceReferenceValue) ref;
final ComponentInstance refCI = (ComponentInstance) rv.getReferencedInstanceObject();
disjunctSet.addAll(refCI.getAllComponentInstances());
}
if (!disjunctSet.isEmpty()) {
notCollocated.put(ci, disjunctSet);
}
}
};
addThreads.processPreOrderComponentInstance(root, ComponentCategory.THREAD);
// only some processors have mips
if (existsProcessorWithMIPS && existsProcessorWithoutMIPS) {
errManager.error(root, "Not all processors have MIPSCapacity");
return null;
}
// only some threads with reference processor
if (existsThreadWithReferenceProcessor && existsThreadWithoutReferenceProcessor) {
errManager.error(root, "Not all threads have execution time reference processor");
return null;
}
// threads and processors mips spec not consistent
if (existsProcessorWithMIPS && existsThreadWithoutReferenceProcessor) {
errManager.error(root, "There are some processors with MIPSCapacity but some threads without execution time reference processors");
return null;
}
if (existsProcessorWithoutMIPS && existsThreadWithReferenceProcessor) {
errManager.error(root, "There are some threads with execution time reference processors but not all processors have MIPSCapacity");
return null;
}
// Add thread connections (Messages)
for (final Iterator<ConnectionInstance> i = root.getAllConnectionInstances().iterator(); i.hasNext(); ) {
final ConnectionInstance connInst = i.next();
if (connInst.getKind() == ConnectionKind.PORT_CONNECTION) {
if (!(connInst.getSource() instanceof FeatureInstance && connInst.getDestination() instanceof FeatureInstance)) {
continue;
}
final FeatureInstance src = (FeatureInstance) connInst.getSource();
final FeatureInstance dst = (FeatureInstance) connInst.getDestination();
final ComponentInstance ci = src.getContainingComponentInstance();
AADLThread t1 = threadToSoftwareNode.get(ci);
AADLThread t2 = threadToSoftwareNode.get(dst.getContainingComponentInstance());
if (t1 != null && t2 != null) {
Feature srcAP = src.getFeature();
// TODO: get the property directly
Classifier cl = srcAP.getClassifier();
if (cl instanceof DataClassifier) {
DataClassifier srcDC = (DataClassifier) cl;
double dataSize = 0.0;
double threadPeriod = 0.0;
try {
dataSize = AadlContribUtils.getDataSize(srcDC, SizeUnits.BYTES);
} catch (Exception e) {
errManager.warning(connInst, "No Data Size for connection");
}
try {
threadPeriod = GetProperties.getPeriodinNS(ci);
} catch (Exception e) {
errManager.warning(connInst, "No Period for connection");
}
// Now I can create the Message
Message msg = new Message((long) dataSize, (long) threadPeriod, (long) threadPeriod, t1, t2);
System.out.println(">>>>>>>>>> Adding message (" + Long.toString((long) dataSize) + "/" + Long.toString((long) threadPeriod) + ") between " + t1.getName() + " and " + t2.getName() + " based on connection " + connInst.getName());
problem.addMessage(msg);
} else {
errManager.warning(connInst, "No Data Classifier for connection");
}
}
}
}
// Add collocation constraints
for (final Iterator<ComponentInstance> constrained = notCollocated.keySet().iterator(); constrained.hasNext(); ) {
final ComponentInstance ci = constrained.next();
final SoftwareNode sn = threadToSoftwareNode.get(ci);
final Set<ComponentInstance> disjunctFrom = notCollocated.get(ci);
for (final Iterator<ComponentInstance> dfIter = disjunctFrom.iterator(); dfIter.hasNext(); ) {
/*
* Items in the disjunctFrom set do not have to be thread
* instances because of the way we add items to it (see above).
* We are only interested in the thread instances here, in
* particular because we only create SoftwareNodes for the
* thread instances, and we don't want to get null return
* values from the threadToSoftwareNode map.
*/
final ComponentInstance ci2 = dfIter.next();
if (ci2.getCategory() == ComponentCategory.THREAD) {
final SoftwareNode sn2 = threadToSoftwareNode.get(ci2);
final SoftwareNode[] disjunction = new SoftwareNode[] { sn, sn2 };
problem.addConstraint(new Disjoint(disjunction));
}
}
}
/*
* Add Allowed_Processor_Binding and
* Allowed_Processor_Binding_Class constraints
*/
for (final Iterator<ComponentInstance> i = threads.iterator(); i.hasNext(); ) {
final ComponentInstance thr = i.next();
final SoftwareNode thrSN = threadToSoftwareNode.get(thr);
Collection<ComponentInstance> allowed = getActualProcessorBindings(thr);
if (allowed.size() == 0) {
allowed = getAllowedProcessorBindings(thr);
}
if (allowed.size() > 0) {
final Object[] allowedProcs = new Object[allowed.size()];
int idx = 0;
for (Iterator<ComponentInstance> j = allowed.iterator(); j.hasNext(); idx++) {
final ComponentInstance proc = j.next();
allowedProcs[idx] = procToHardware.get(proc);
}
problem.addConstraint(new SetConstraint(new SoftwareNode[] { thrSN }, allowedProcs));
}
}
// Try to bin pack
final NFCHoBinPacker highPacker = new NFCHoBinPacker(packer);
final boolean res = highPacker.solve(problem);
return new AssignmentResult(problem, res);
}
use of com.google.cloud.vision.v1p3beta1.Feature in project osate2 by osate.
the class AadlBaNameResolver method featureNameUniquenessCheck.
// Just the opposite of featureResolver.
private boolean featureNameUniquenessCheck(IterativeVariable itv) {
String nameToFind = itv.getName();
Feature f = Aadl2Visitors.findFeatureInComponent(_baParentContainer, nameToFind);
if (f == null) {
return true;
} else {
// Report error.
_errManager.error(itv, "duplicate local variable for " + itv.getName());
return false;
}
}
use of com.google.cloud.vision.v1p3beta1.Feature in project osate2 by osate.
the class AadlBaTypeChecker method subprogramParameterListCheck.
// This method checks the given parameter labels and matches them against the
// subprogram parameters. It resolves target/value expression semantic
// ambiguities. On error, reports error and returns false.
// Event if the subprogram call action doesn't have any parameter labels,
// the subprogram type may have and vice versa : subprogramParameterListCheck
// / is also design for these cases.
/**
* Document: AADL Behavior Annex draft
* Version : 0.94
* Type : Legality rule
* Section : D.6 Behavior Action Language
* Object : Check legality rule D.6.(L5)
* Keys : parameter list match signature subprogram call
*/
private boolean subprogramParameterListCheck(CommAction comAct, EList<ParameterLabel> callParams, Classifier subprogType) {
// Fetches sorted subprogram feature list.
List<Feature> tmp = Aadl2Utils.orderFeatures(subprogType);
List<Feature> subprogFeat = new ArrayList<Feature>(tmp.size());
for (Feature feat : tmp) {
if (feat instanceof DataAccess || feat instanceof Parameter) {
subprogFeat.add(feat);
}
}
// Preliminary checking : on error, reports error and exit early.
if (callParams.size() != subprogFeat.size()) {
String subprogramName = null;
if (comAct.getReference() != null) {
subprogramName = unparseReference(comAct.getReference());
} else {
subprogramName = unparseQualifiedNamedElement(comAct.getQualifiedName());
}
reportError(comAct, "Invalid number of argument(s) for the subprogram " + subprogramName);
return false;
}
boolean isconsistent = true;
boolean hasCheckingPassed = true;
Enum<?> currentDirRight;
ValueExpression valueExp;
ListIterator<ParameterLabel> it = callParams.listIterator();
Value v;
Target tar;
TypeHolder t1, t2;
ValueAndTypeHolder vth;
List<TypeHolder> typesFound = new ArrayList<TypeHolder>(callParams.size());
List<Enum<?>> dirRightsFound = new ArrayList<Enum<?>>(callParams.size());
List<TypeHolder> expectedTypes = new ArrayList<TypeHolder>(subprogFeat.size());
List<Enum<?>> expectedDirRight = new ArrayList<Enum<?>>(subprogFeat.size());
// driven by the subprogram signature.
for (Feature feat : subprogFeat) {
if (feat instanceof Parameter) {
Parameter param = (Parameter) feat;
currentDirRight = param.getDirection();
expectedDirRight.add(currentDirRight);
} else // DataAccess case.
{
DataAccess data = (DataAccess) feat;
currentDirRight = Aadl2Utils.getDataAccessRight(data);
expectedDirRight.add(currentDirRight);
}
valueExp = (ValueExpression) it.next();
Classifier klass = AadlBaUtils.getClassifier(feat, _baParentContainer);
// ValueExpression case.
if (currentDirRight == DirectionType.IN || currentDirRight == Aadl2Utils.DataAccessRight.read_only) {
vth = valueExpressionCheck(valueExp);
if (vth != null) {
try {
t1 = AadlBaUtils.getTypeHolder(klass);
} catch (DimensionException de) {
reportDimensionException(de);
return false;
}
t2 = vth.typeHolder;
expectedTypes.add(t1);
typesFound.add(t2);
dirRightsFound.add(DirectionType.IN);
if (!_dataChecker.conformsTo(t1, t2, true)) {
isconsistent = false;
}
} else // Value expression checking error case.
{
// Error reporting has already been done.
hasCheckingPassed = false;
}
} else if (currentDirRight != Aadl2Utils.DataAccessRight.unknown) {
v = AadlBaUtils.isOnlyOneValue(valueExp);
boolean isOnlyOneReference = false;
if (v instanceof Reference) {
Reference r = (Reference) v;
if (r.getIds().size() == 1) {
isOnlyOneReference = true;
}
}
if (// Target but not reference case.
v instanceof Target && isOnlyOneReference) {
TypeCheckRule stopOnThisRule = TypeCheckRule.DATA_ACCESS;
tar = targetCheck((Target) v, stopOnThisRule);
if (tar != null) {
try {
t1 = AadlBaUtils.getTypeHolder(klass);
t2 = AadlBaUtils.getTypeHolder(tar, _baParentContainer);
} catch (DimensionException de) {
reportDimensionException(de);
return false;
}
expectedTypes.add(t1);
typesFound.add(t2);
Enum<?> dirRightFound = AadlBaUtils.getDirectionType(tar);
if (dirRightFound == null) {
dirRightFound = AadlBaUtils.getDataAccessRight(tar);
}
dirRightsFound.add(dirRightFound);
if (!_dataChecker.conformsTo(t1, t2, true)) {
isconsistent = false;
} else {
// As checking passed and ambiguity between
// ValueExpression and Target has been resolved, it replaces
// the value expression by the target as parameter label.
it.set(tar);
}
} else // Target checking error case.
{
// Error reporting has already been done.
hasCheckingPassed = false;
}
} else // Value expression taken as a target -> warning arithmetic pointer operation.
{
// Due to target/value expression semantic ambiguity, the parsing
// phase may have introduced a semantic errors :
// If v == null :
// The parameter label has
// to be a value expression with a single value when the expected
// subprogram parameter is IN_OUT or OUT.
// If v is not instanceof Target but ValueExpression or Value
// like :
// _ IntegerConstant or ValueConstant
// _ PortFreshValue
// _ PortCountValue
// _ PortDequeueValue
// It resolves the type in order to format the warning message:
vth = valueExpressionCheck(valueExp);
if (vth != null) {
try {
t1 = AadlBaUtils.getTypeHolder(klass);
} catch (DimensionException de) {
reportDimensionException(de);
return false;
}
t2 = vth.typeHolder;
expectedTypes.add(t1);
typesFound.add(t2);
boolean inconsistentDir = false;
if (v instanceof Reference) {
Reference ref = (Reference) v;
ArrayableIdentifier refRootId = ref.getIds().get(0);
Enum<?> dirRightFound = null;
if (refRootId.getOsateRef() != null) {
dirRightFound = AadlBaUtils.getDirectionType(refRootId.getOsateRef());
}
if (dirRightFound == null && refRootId.getOsateRef() instanceof DataAccess) {
dirRightFound = Aadl2Utils.getDataAccessRight((DataAccess) refRootId.getOsateRef());
}
if (dirRightFound == DirectionType.IN || dirRightFound == Aadl2Utils.DataAccessRight.read_only) {
inconsistentDir = true;
}
} else {
inconsistentDir = true;
dirRightsFound.add(DirectionType.IN);
}
if (inconsistentDir) {
StringBuilder msg = new StringBuilder();
msg.append('\'');
msg.append(unparseNameElement(valueExp));
msg.append("\': is a read only value and it is used as a writable value");
// Reports a warning.
reportWarning(valueExp, msg.toString());
}
} else {
// Error reporting has already been done.
hasCheckingPassed = false;
}
}
} else {
reportError(valueExp, "can't fetch data access right. Set the default " + "right in memory_properties.aadl");
}
}
// Reports consistency error.
if (!isconsistent && hasCheckingPassed) {
String subprogramName = null;
if (comAct.getReference() != null) {
subprogramName = unparseReference(comAct.getReference());
} else {
subprogramName = unparseQualifiedNamedElement(comAct.getQualifiedName());
}
reportSubprogParamMatchingError(comAct, subprogramName, expectedTypes, expectedDirRight, typesFound, dirRightsFound);
}
return isconsistent && hasCheckingPassed;
}
use of com.google.cloud.vision.v1p3beta1.Feature in project osate2 by osate.
the class AadlBaUtils method getClassifier.
/**
* Returns the given Element object's classifier.
* If the Element object is a prototype, it will try to resolve it as
* follow: returns the data prototype binded classifier at first withing the
* element's parent container otherwise the constraining classifier.
* It returns {@code null} if the prototype is not defined.
* <BR><BR>
* This method support instances of:<BR>
* <BR>_Feature (port, data access, subprogram access, parameter, etc.)
* <BR>_Subcomponent (data subcomponent, subprogram subcomponent, etc.)
* <BR>_BehaviorVariable
* <BR>_IterativeVariable (for/forall's iterative variable)
* <BR>_Prototype (all excepted FeatureGroupPrototype)
* <BR>_PrototypeBinding (all excepted FeatureGroupPrototypeBinding)
* <BR>_ClassifierValue (struct or union data subcomponent)
* <BR><BR>
* If the given Element object is not one of those types, an
* UnsupportedOperationException is thrown.
*
* @param el the given Element object
* @param parentContainer the element's parent component.
* @return the given element's classifier or {@code null} if the prototype is
* not defined
* @exception UnsupportedOperationException for unsupported element
* object types.
*/
public static Classifier getClassifier(Element el, Classifier parentContainer) {
Classifier result = null;
if (el instanceof Feature) {
Feature f = (Feature) el;
if (el instanceof FeatureGroup) {
org.osate.aadl2.FeatureType ft = ((FeatureGroup) el).getFeatureType();
if (ft != null) {
if (ft instanceof FeatureGroupType) {
result = (FeatureGroupType) ft;
} else // FeatureGroupPrototype case
{
result = getClassifier((FeatureGroupPrototype) ft, parentContainer);
}
}
} else {
// Feature case.
result = f.getClassifier();
// Feature without classifier returns null.
if (result == null && f.getPrototype() != null) {
result = prototypeResolver(f.getPrototype(), parentContainer);
}
}
} else if (el instanceof Subcomponent) {
Subcomponent sub = (Subcomponent) el;
if (el instanceof SubprogramGroupSubcomponent) {
result = ((SubprogramGroupSubcomponent) el).getClassifier();
} else {
// Subcomponent case.
result = sub.getClassifier();
// Subcomponent without classifier returns null.
if (result == null && sub.getPrototype() != null) {
result = prototypeResolver(sub.getPrototype(), parentContainer);
}
}
} else if (el instanceof BehaviorVariable) {
// Local variable case (BehaviorVariable).
BehaviorVariable bv = (BehaviorVariable) el;
result = bv.getDataClassifier();
} else if (el instanceof IterativeVariable) {
// Iterative variable case.
result = ((IterativeVariable) el).getDataClassifier();
} else if (el instanceof Prototype) {
result = prototypeResolver((Prototype) el, parentContainer);
} else if (el instanceof PrototypeBinding) {
// Prototype binding case.
result = prototypeBindingResolver((PrototypeBinding) el);
} else if (el instanceof ClassifierValue) {
// struct or union member case (ClassifierValue).
result = ((ClassifierValue) el).getClassifier();
} else if (el instanceof StructUnionElement) {
return ((StructUnionElement) el).getDataClassifier();
} else {
// Reports error.
String errorMsg = "getClassifier : " + el.getClass().getSimpleName() + " is not supported yet.";
System.err.println(errorMsg);
throw new UnsupportedOperationException(errorMsg);
}
return result;
}
Aggregations