use of org.apache.axis2.wsdl.databinding.DefaultTypeMapper in project axis-axis2-java-core by apache.
the class ExtensionUtility method invoke.
public static void invoke(CodeGenConfiguration configuration) throws Exception {
List<XmlSchema> schemaList = new ArrayList<XmlSchema>();
// add all the schemas to the list
for (AxisService service : configuration.getAxisServices()) {
schemaList.addAll(service.getSchema());
}
// hashmap that keeps the targetnamespace and the xmlSchema object
// this is a convenience to locate the relevant schema quickly
// by looking at the target namespace
Map<String, XmlSchema> schemaMap = new HashMap<String, XmlSchema>();
populateSchemaMap(schemaMap, schemaList);
if (schemaList == null || schemaList.isEmpty()) {
// there are no types to be code generated
// However if the type mapper is left empty it will be a problem for the other
// processes. Hence the default type mapper is set to the configuration
configuration.setTypeMapper(new DefaultTypeMapper());
return;
}
// call the schema compiler
CompilerOptions options = new CompilerOptions();
// set the default options
populateDefaultOptions(options, configuration);
// set the user parameters. the user parameters get the preference over
// the default ones. But the user better know what he's doing if he
// used module specific parameters
populateUserparameters(options, configuration);
SchemaCompiler schemaCompiler = new SchemaCompiler(options);
// run the schema compiler
schemaCompiler.compile(schemaList);
// create the type mapper
// First try to take the one that is already there
TypeMapper mapper = configuration.getTypeMapper();
if (mapper == null) {
if (configuration.getOutputLanguage() != null && !configuration.getOutputLanguage().trim().equals("") && configuration.getOutputLanguage().toLowerCase().equals("c")) {
mapper = new CTypeMapper();
} else {
mapper = new JavaTypeMapper();
}
}
if (options.isWriteOutput()) {
// get the processed element map and transfer it to the type mapper
for (Map.Entry<QName, String> entry : schemaCompiler.getProcessedElementMap().entrySet()) {
mapper.addTypeMappingName(entry.getKey(), entry.getValue());
}
} else {
// get the processed model map and transfer it to the type mapper
// since the options mentiond that its not writable, it should have
// populated the model map
Map processedModelMap = schemaCompiler.getProcessedModelMap();
Iterator processedkeys = processedModelMap.keySet().iterator();
QName qNameKey;
while (processedkeys.hasNext()) {
qNameKey = (QName) processedkeys.next();
mapper.addTypeMappingObject(qNameKey, processedModelMap.get(qNameKey));
}
for (Map.Entry<QName, String> entry : schemaCompiler.getProcessedElementMap().entrySet()) {
mapper.addTypeMappingName(entry.getKey(), entry.getValue());
}
// get the ADB template from the schema compilers property bag and set the
// template
configuration.putProperty(Constants.EXTERNAL_TEMPLATE_PROPERTY_KEY, schemaCompiler.getCompilerProperties().getProperty(SchemaConstants.SchemaPropertyNames.BEAN_WRITER_TEMPLATE_KEY));
}
// replace the Axis2 schemas with the processed ones.
// otherwise it gives some problems if we try to code generate with multiple
// services with the -uw option.
// inorder to work for -uw option there must be some metadata with the schema list
Map<String, XmlSchema> loadedSchemaMap = schemaCompiler.getLoadedSchemaMap();
for (AxisService service : configuration.getAxisServices()) {
List<XmlSchema> serviceSchemaList = service.getSchema();
List<XmlSchema> schemaListToAdd = new ArrayList<XmlSchema>();
for (XmlSchema xmlSchema : serviceSchemaList) {
if (loadedSchemaMap.containsKey(xmlSchema.getTargetNamespace())) {
schemaListToAdd.add(loadedSchemaMap.get(xmlSchema.getTargetNamespace()));
} else {
schemaListToAdd.add(xmlSchema);
}
}
service.releaseSchemaList();
service.addSchema(schemaListToAdd);
}
// process the unwrapped parameters
if (!configuration.isParametersWrapped()) {
// figure out the unwrapped operations
for (AxisService axisService : configuration.getAxisServices()) {
for (Iterator<AxisOperation> operations = axisService.getOperations(); operations.hasNext(); ) {
AxisOperation op = operations.next();
if (WSDLUtil.isInputPresentForMEP(op.getMessageExchangePattern())) {
walkSchema(op.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE), mapper, schemaMap, op.getName().getLocalPart(), WSDLConstants.INPUT_PART_QNAME_SUFFIX);
}
// TODO: support for xml beans
if (configuration.getDatabindingType().equals("adb")) {
if (WSDLUtil.isOutputPresentForMEP(op.getMessageExchangePattern())) {
walkSchema(op.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE), mapper, schemaMap, op.getName().getLocalPart(), WSDLConstants.OUTPUT_PART_QNAME_SUFFIX);
}
}
}
}
}
// this is needed in unwrapping and to provide backwordCompatibility
if (!configuration.isParametersWrapped() || configuration.isBackwordCompatibilityMode()) {
for (AxisService axisService : configuration.getAxisServices()) {
AxisOperation axisOperation;
AxisMessage axisMessage;
for (Iterator<AxisOperation> operators = axisService.getOperations(); operators.hasNext(); ) {
axisOperation = operators.next();
if (WSDLUtil.isInputPresentForMEP(axisOperation.getMessageExchangePattern())) {
axisMessage = axisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
setComplexTypeName(axisMessage);
}
if (WSDLUtil.isOutputPresentForMEP(axisOperation.getMessageExchangePattern())) {
axisMessage = axisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
setComplexTypeName(axisMessage);
}
}
}
}
// set the type mapper to the config
configuration.setTypeMapper(mapper);
}
use of org.apache.axis2.wsdl.databinding.DefaultTypeMapper in project axis-axis2-java-core by apache.
the class TypeMapperExtension method engage.
/**
* @throws CodeGenerationException
*/
public void engage(CodeGenConfiguration configuration) throws CodeGenerationException {
if (configuration.getTypeMappingFile() != null) {
// a type mapping is present. try building the
// mapping from it
// if the configuration already has a mapping then take it
// the external mappings will override the currently available
// mappings
TypeMapper mapper = configuration.getTypeMapper();
// there is no mapper present - so just create a new one
if (mapper == null) {
if (configuration.getOutputLanguage() != null && !configuration.getOutputLanguage().trim().equals("") && configuration.getOutputLanguage().toLowerCase().equals("c")) {
mapper = new CTypeMapper();
} else {
mapper = new DefaultTypeMapper();
}
}
// read the file as a DOM
Document mappingDocument = buildDocument(configuration);
Element rootMappingsElement = mappingDocument.getDocumentElement();
// override the databinding framework name. If a mapping file is
// present then the databinding framework name will be overridden
// if present. If a user wants to mix types then it must be
// from the same databinding framework!
// first do a sanity check to see whether the user is trying to
// mix databinding types!
String databindingName = rootMappingsElement.getAttribute(DB_FRAMEWORK_ATTRIBUTE_NAME);
if (!databindingName.equals(configuration.getDatabindingType())) {
throw new CodeGenerationException(CodegenMessages.getMessage("extension.databindingMismatch"));
}
configuration.setDatabindingType(databindingName);
NodeList mappingList = rootMappingsElement.getElementsByTagName(MAPPING_ELEMENT_NAME);
int length = mappingList.getLength();
for (int i = 0; i < length; i++) {
Element mappingNode = (Element) mappingList.item(i);
// we know this is only one - if there are multiple then
// it is invalid
Element qNameChild = (Element) mappingNode.getElementsByTagName(QNAME_ELEMENT_NAME).item(0);
Element valueChild = (Element) mappingNode.getElementsByTagName(VALUE_ELEMENT_NAME).item(0);
// generate a Qname and add to the type mapping
mapper.addTypeMappingName(new QName(qNameChild.getAttribute(NAMESPACE_ATTRIBUTE_NAME), getTextFromElement(qNameChild)), getTextFromElement(valueChild));
}
// set the type mapper to the configurtion
configuration.setTypeMapper(mapper);
}
}
use of org.apache.axis2.wsdl.databinding.DefaultTypeMapper in project axis-axis2-java-core by apache.
the class CodeGenerationUtility method processSchemas.
/**
* @param additionalSchemas
* @throws RuntimeException
*/
public static TypeMapper processSchemas(List schemas, Element[] additionalSchemas, CodeGenConfiguration cgconfig, String typeSystemName) throws RuntimeException {
try {
// check for the imported types. Any imported types are supposed to be here also
if (schemas == null || schemas.isEmpty()) {
// processes. Hence the default type mapper is set to the configuration
return new DefaultTypeMapper();
}
SchemaTypeSystem sts;
List completeSchemaList = new ArrayList();
List topLevelSchemaList = new ArrayList();
// create the type mapper
// First try to take the one that is already there
TypeMapper mapper = cgconfig.getTypeMapper();
if (mapper == null) {
mapper = new JavaTypeMapper();
}
// change the default class name of the mapper to
// xmlbeans specific XMLObject
mapper.setDefaultMappingName(XmlObject.class.getName());
Map nameSpacesMap = new HashMap();
List axisServices = cgconfig.getAxisServices();
AxisService axisService;
for (Iterator iter = axisServices.iterator(); iter.hasNext(); ) {
axisService = (AxisService) iter.next();
nameSpacesMap.putAll(axisService.getNamespaceMap());
}
// resolving entities
for (int i = 0; i < schemas.size(); i++) {
XmlSchema schema = (XmlSchema) schemas.get(i);
XmlOptions options = new XmlOptions();
options.setLoadAdditionalNamespaces(// add the namespaces
nameSpacesMap);
XmlSchema[] allSchemas = SchemaUtil.getAllSchemas(schema);
for (int j = 0; j < allSchemas.length; j++) {
completeSchemaList.add(allSchemas[j]);
}
}
// make another list of top level schemas for passing into XMLbeans
for (int i = 0; i < schemas.size(); i++) {
XmlSchema schema = (XmlSchema) schemas.get(i);
XmlOptions options = new XmlOptions();
options.setLoadAdditionalNamespaces(// add the namespaces
nameSpacesMap);
topLevelSchemaList.add(XmlObject.Factory.parse(getSchemaAsString(schema), options));
}
XmlSchemaCollection extras = new XmlSchemaCollection();
// make the generated code work efficiently
for (int i = 0; i < additionalSchemas.length; i++) {
completeSchemaList.add(extras.read(additionalSchemas[i]));
topLevelSchemaList.add(XmlObject.Factory.parse(additionalSchemas[i], null));
}
// compile the type system
Axis2EntityResolver er = new Axis2EntityResolver();
er.setSchemas((XmlSchema[]) completeSchemaList.toArray(new XmlSchema[completeSchemaList.size()]));
er.setBaseUri(cgconfig.getBaseURI());
String xsdConfigFile = (String) cgconfig.getProperties().get(XMLBeansExtension.XSDCONFIG_OPTION);
// -Ejavaversion switch to XmlOptions to generate 1.5 compliant code
XmlOptions xmlOptions = new XmlOptions();
xmlOptions.setEntityResolver(er);
// test if javaversion property in CodeGenConfig
if (null != cgconfig.getProperty("javaversion")) {
xmlOptions.put(XmlOptions.GENERATE_JAVA_VERSION, cgconfig.getProperty("javaversion"));
}
sts = XmlBeans.compileXmlBeans(// include a unique (but random) STS name
typeSystemName, null, convertToSchemaArray(topLevelSchemaList), new Axis2BindingConfig(cgconfig.getUri2PackageNameMap(), xsdConfigFile), XmlBeans.getContextTypeLoader(), new Axis2Filer(cgconfig), xmlOptions);
// prune the generated schema type system and add the list of base64 types
cgconfig.putProperty(Constants.BASE_64_PROPERTY_KEY, findBase64Types(sts));
cgconfig.putProperty(Constants.PLAIN_BASE_64_PROPERTY_KEY, findPlainBase64Types(sts));
SchemaTypeSystem internal = XmlBeans.getBuiltinTypeSystem();
SchemaType[] schemaTypes = internal.globalTypes();
for (int j = 0; j < schemaTypes.length; j++) {
mapper.addTypeMappingName(schemaTypes[j].getName(), schemaTypes[j].getFullJavaName());
}
// get the schematypes and add the document types to the type mapper
schemaTypes = sts.documentTypes();
for (int j = 0; j < schemaTypes.length; j++) {
mapper.addTypeMappingName(schemaTypes[j].getDocumentElementName(), schemaTypes[j].getFullJavaName());
}
// process the unwrapped parameters
if (!cgconfig.isParametersWrapped()) {
// figure out the unwrapped operations
axisServices = cgconfig.getAxisServices();
for (Iterator servicesIter = axisServices.iterator(); servicesIter.hasNext(); ) {
axisService = (AxisService) servicesIter.next();
for (Iterator operations = axisService.getOperations(); operations.hasNext(); ) {
AxisOperation op = (AxisOperation) operations.next();
if (WSDLUtil.isInputPresentForMEP(op.getMessageExchangePattern())) {
AxisMessage message = op.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
if (message != null && message.getParameter(Constants.UNWRAPPED_KEY) != null) {
SchemaGlobalElement xmlbeansElement = sts.findElement(message.getElementQName());
SchemaType sType = xmlbeansElement.getType();
SchemaProperty[] elementProperties = sType.getElementProperties();
for (int i = 0; i < elementProperties.length; i++) {
SchemaProperty elementProperty = elementProperties[i];
QName partQName = WSDLUtil.getPartQName(op.getName().getLocalPart(), WSDLConstants.INPUT_PART_QNAME_SUFFIX, elementProperty.getName().getLocalPart());
// this type is based on a primitive type- use the
// primitive type name in this case
String fullJaveName = elementProperty.getType().getFullJavaName();
if (elementProperty.extendsJavaArray()) {
fullJaveName = fullJaveName.concat("[]");
}
mapper.addTypeMappingName(partQName, fullJaveName);
SchemaType primitiveType = elementProperty.getType().getPrimitiveType();
if (primitiveType != null) {
mapper.addTypeMappingStatus(partQName, Boolean.TRUE);
}
if (elementProperty.extendsJavaArray()) {
mapper.addTypeMappingStatus(partQName, Constants.ARRAY_TYPE);
}
}
}
}
if (WSDLUtil.isOutputPresentForMEP(op.getMessageExchangePattern())) {
AxisMessage message = op.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
if (message != null && message.getParameter(Constants.UNWRAPPED_KEY) != null) {
SchemaGlobalElement xmlbeansElement = sts.findElement(message.getElementQName());
SchemaType sType = xmlbeansElement.getType();
SchemaProperty[] elementProperties = sType.getElementProperties();
for (int i = 0; i < elementProperties.length; i++) {
SchemaProperty elementProperty = elementProperties[i];
QName partQName = WSDLUtil.getPartQName(op.getName().getLocalPart(), WSDLConstants.OUTPUT_PART_QNAME_SUFFIX, elementProperty.getName().getLocalPart());
// this type is based on a primitive type- use the
// primitive type name in this case
String fullJaveName = elementProperty.getType().getFullJavaName();
if (elementProperty.extendsJavaArray()) {
fullJaveName = fullJaveName.concat("[]");
}
mapper.addTypeMappingName(partQName, fullJaveName);
SchemaType primitiveType = elementProperty.getType().getPrimitiveType();
if (primitiveType != null) {
mapper.addTypeMappingStatus(partQName, Boolean.TRUE);
}
if (elementProperty.extendsJavaArray()) {
mapper.addTypeMappingStatus(partQName, Constants.ARRAY_TYPE);
}
}
}
}
}
}
}
// return mapper to be set in the config
return mapper;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
use of org.apache.axis2.wsdl.databinding.DefaultTypeMapper in project axis-axis2-java-core by apache.
the class CodeGenerationUtility method processSchemas.
/**
* @param additionalSchemas
* @throws RuntimeException
*/
public static TypeMapper processSchemas(final List<XmlSchema> schemas, Element[] additionalSchemas, CodeGenConfiguration cgconfig) throws RuntimeException {
try {
// Work around MNG-6506.
CodeGenerationUtility.class.getClassLoader().loadClass("com.sun.tools.xjc.reader.xmlschema.bindinfo.package-info");
// check for the imported types. Any imported types are supposed to be here also
if (schemas == null || schemas.isEmpty()) {
// processes. Hence the default type mapper is set to the configuration
return new DefaultTypeMapper();
}
final Map<XmlSchema, InputSource> schemaToInputSourceMap = new HashMap<>();
final Map<String, StringBuffer> publicIDToStringMap = new HashMap<String, StringBuffer>();
// create the type mapper
JavaTypeMapper mapper = new JavaTypeMapper();
String baseURI = cgconfig.getBaseURI();
if (!baseURI.endsWith("/")) {
baseURI = baseURI + "/";
}
for (int i = 0; i < schemas.size(); i++) {
XmlSchema schema = schemas.get(i);
InputSource inputSource = new InputSource(new StringReader(getSchemaAsString(schema)));
// here we have to set a proper system ID. otherwise when processing the
// included schaemas for this schema we have a problem
// it creates the system ID using this target namespace value
inputSource.setSystemId(baseURI + "xsd" + i + ".xsd");
inputSource.setPublicId(schema.getTargetNamespace());
schemaToInputSourceMap.put(schema, inputSource);
}
File outputDir = new File(cgconfig.getOutputLocation(), "src");
outputDir.mkdir();
Map<String, String> nsMap = cgconfig.getUri2PackageNameMap();
EntityResolver resolver = new EntityResolver() {
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
InputSource returnInputSource = null;
for (XmlSchema key : schemaToInputSourceMap.keySet()) {
String nsp = key.getTargetNamespace();
if (nsp != null && nsp.equals(publicId)) {
// when returning the input stream we have to always return a new
// input stream.
// sinc jaxbri internally consumes the input stream it gives an
// exception.
returnInputSource = new InputSource(new StringReader(getSchemaAsString(key)));
InputSource existingInputSource = (InputSource) schemaToInputSourceMap.get(key);
returnInputSource.setSystemId(existingInputSource.getSystemId());
returnInputSource.setPublicId(existingInputSource.getPublicId());
break;
}
}
if (returnInputSource == null) {
// then we have to find this using the file system
if (systemId != null) {
returnInputSource = new InputSource(systemId);
returnInputSource.setSystemId(systemId);
}
}
if (returnInputSource == null) {
if (publicId != null) {
if (!publicIDToStringMap.containsKey(publicId)) {
URL url = new URL(publicId);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream()));
StringBuffer stringBuffer = new StringBuffer();
String str = null;
while ((str = bufferedReader.readLine()) != null) {
stringBuffer.append(str);
}
publicIDToStringMap.put(publicId, stringBuffer);
}
String schemaString = publicIDToStringMap.get(publicId).toString();
returnInputSource = new InputSource(new StringReader(schemaString));
returnInputSource.setPublicId(publicId);
returnInputSource.setSystemId(publicId);
}
}
return returnInputSource;
}
};
Map<Object, Object> properties = cgconfig.getProperties();
String bindingFileName = (String) properties.get(BINDING_FILE_NAME);
for (XmlSchema key : schemaToInputSourceMap.keySet()) {
SchemaCompiler sc = XJC.createSchemaCompiler();
if (bindingFileName != null) {
if (bindingFileName.endsWith(".jar")) {
scanEpisodeFile(new File(bindingFileName), sc);
} else {
InputSource inputSoruce = new InputSource(new FileInputStream(bindingFileName));
inputSoruce.setSystemId(new File(bindingFileName).toURI().toString());
sc.getOptions().addBindFile(inputSoruce);
}
}
if (nsMap != null) {
for (Map.Entry<String, String> entry : nsMap.entrySet()) {
registerNamespace(sc, entry.getKey(), entry.getValue());
}
}
sc.setEntityResolver(resolver);
sc.setErrorListener(new ErrorListener() {
public void error(SAXParseException saxParseException) {
log.error(saxParseException.getMessage());
log.debug(saxParseException.getMessage(), saxParseException);
}
public void fatalError(SAXParseException saxParseException) {
log.error(saxParseException.getMessage());
log.debug(saxParseException.getMessage(), saxParseException);
}
public void warning(SAXParseException saxParseException) {
log.warn(saxParseException.getMessage());
log.debug(saxParseException.getMessage(), saxParseException);
}
public void info(SAXParseException saxParseException) {
log.info(saxParseException.getMessage());
log.debug(saxParseException.getMessage(), saxParseException);
}
});
sc.parseSchema((InputSource) schemaToInputSourceMap.get(key));
sc.getOptions().addGrammar((InputSource) schemaToInputSourceMap.get(key));
for (Object property : properties.keySet()) {
String propertyName = (String) property;
if (propertyName.startsWith("X")) {
String[] args = null;
String propertyValue = (String) properties.get(property);
if (propertyValue != null) {
args = new String[] { "-" + propertyName, propertyValue };
} else {
args = new String[] { "-" + propertyName };
}
sc.getOptions().parseArguments(args);
}
}
// Bind the XML
S2JJAXBModel jaxbModel = sc.bind();
if (jaxbModel == null) {
throw new RuntimeException("Unable to generate code using jaxbri");
}
// Emit the code artifacts
JCodeModel codeModel = jaxbModel.generateCode(null, null);
FileCodeWriter writer = new FileCodeWriter(outputDir, cgconfig.getOutputEncoding());
codeModel.build(writer);
for (Mapping mapping : jaxbModel.getMappings()) {
QName qn = mapping.getElement();
String typeName = mapping.getType().getTypeClass().fullName();
mapper.addTypeMappingName(qn, typeName);
}
// process the unwrapped parameters
if (!cgconfig.isParametersWrapped()) {
// figure out the unwrapped operations
for (AxisService axisService : cgconfig.getAxisServices()) {
for (Iterator<AxisOperation> operations = axisService.getOperations(); operations.hasNext(); ) {
AxisOperation op = operations.next();
if (WSDLUtil.isInputPresentForMEP(op.getMessageExchangePattern())) {
AxisMessage message = op.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
if (message != null && message.getParameter(Constants.UNWRAPPED_KEY) != null) {
Mapping mapping = jaxbModel.get(message.getElementQName());
for (Property elementProperty : mapping.getWrapperStyleDrilldown()) {
QName partQName = WSDLUtil.getPartQName(op.getName().getLocalPart(), WSDLConstants.INPUT_PART_QNAME_SUFFIX, elementProperty.elementName().getLocalPart());
// this type is based on a primitive type- use the
// primitive type name in this case
String fullJaveName = elementProperty.type().fullName();
if (elementProperty.type().isArray()) {
fullJaveName = fullJaveName.concat("[]");
}
mapper.addTypeMappingName(partQName, fullJaveName);
if (elementProperty.type().isPrimitive()) {
mapper.addTypeMappingStatus(partQName, Boolean.TRUE);
}
if (elementProperty.type().isArray()) {
mapper.addTypeMappingStatus(partQName, Constants.ARRAY_TYPE);
}
}
}
}
if (WSDLUtil.isOutputPresentForMEP(op.getMessageExchangePattern())) {
AxisMessage message = op.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
if (message != null && message.getParameter(Constants.UNWRAPPED_KEY) != null) {
Mapping mapping = jaxbModel.get(message.getElementQName());
for (Property elementProperty : mapping.getWrapperStyleDrilldown()) {
QName partQName = WSDLUtil.getPartQName(op.getName().getLocalPart(), WSDLConstants.OUTPUT_PART_QNAME_SUFFIX, elementProperty.elementName().getLocalPart());
// this type is based on a primitive type- use the
// primitive type name in this case
String fullJaveName = elementProperty.type().fullName();
if (elementProperty.type().isArray()) {
fullJaveName = fullJaveName.concat("[]");
}
mapper.addTypeMappingName(partQName, fullJaveName);
if (elementProperty.type().isPrimitive()) {
mapper.addTypeMappingStatus(partQName, Boolean.TRUE);
}
if (elementProperty.type().isArray()) {
mapper.addTypeMappingStatus(partQName, Constants.ARRAY_TYPE);
}
}
}
}
}
}
}
}
// Return the type mapper
return mapper;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Aggregations