use of org.bimserver.plugins.renderengine.RenderEngineSettings in project BIMserver by opensourceBIM.
the class GeometryGenerator method generateGeometry.
@SuppressWarnings("unchecked")
public GenerateGeometryResult generateGeometry(RenderEnginePool renderEnginePool, final PluginManager pluginManager, final DatabaseSession databaseSession, final IfcModelInterface model, final int pid, final int rid, final boolean store, GeometryCache geometryCache) throws BimserverDatabaseException, GeometryGeneratingException {
GenerateGeometryResult generateGeometryResult = new GenerateGeometryResult();
packageMetaData = model.getPackageMetaData();
productClass = packageMetaData.getEClass("IfcProduct");
productRepresentationClass = packageMetaData.getEClass("IfcProductRepresentation");
geometryFeature = productClass.getEStructuralFeature("geometry");
representationFeature = productClass.getEStructuralFeature("Representation");
representationsFeature = productRepresentationClass.getEStructuralFeature("Representations");
if (geometryCache != null && !geometryCache.isEmpty()) {
returnCachedData(model, geometryCache, databaseSession, pid, rid);
return null;
}
long start = System.nanoTime();
String pluginName = "";
if (model.getPackageMetaData().getSchema() == Schema.IFC4) {
pluginName = "org.bimserver.ifc.step.serializer.Ifc4StepSerializerPlugin";
} else if (model.getPackageMetaData().getSchema() == Schema.IFC2X3TC1) {
pluginName = "org.bimserver.ifc.step.serializer.Ifc2x3tc1StepSerializerPlugin";
}
try {
final SerializerPlugin ifcSerializerPlugin = (SerializerPlugin) pluginManager.getPlugin(pluginName, true);
if (ifcSerializerPlugin == null) {
throw new UserException("No IFC serializer found");
}
int maxSimultanousThreads = Math.min(bimServer.getServerSettingsCache().getServerSettings().getRenderEngineProcesses(), Runtime.getRuntime().availableProcessors());
maxSimultanousThreads = 1;
final RenderEngineSettings settings = new RenderEngineSettings();
settings.setPrecision(Precision.SINGLE);
settings.setIndexFormat(IndexFormat.AUTO_DETECT);
settings.setGenerateNormals(true);
settings.setGenerateTriangles(true);
settings.setGenerateWireFrame(false);
final RenderEngineFilter renderEngineFilter = new RenderEngineFilter();
if (maxSimultanousThreads == 1) {
Runner runner = new Runner(null, renderEnginePool, databaseSession, settings, store, model, ifcSerializerPlugin, model, pid, rid, null, renderEngineFilter, generateGeometryResult);
runner.run();
} else {
Set<EClass> classes = new HashSet<>();
for (IdEObject object : model.getAllWithSubTypes(packageMetaData.getEClass("IfcProduct"))) {
IdEObject representation = (IdEObject) object.eGet(representationFeature);
if (representation != null && ((List<?>) representation.eGet(representationsFeature)).size() > 0) {
classes.add(object.eClass());
}
}
if (classes.size() == 0) {
return null;
}
classes.remove(packageMetaData.getEClass("IfcAnnotation"));
classes.remove(packageMetaData.getEClass("IfcOpeningElement"));
LOGGER.debug("Using " + maxSimultanousThreads + " processes for geometry generation");
ThreadPoolExecutor executor = new ThreadPoolExecutor(maxSimultanousThreads, maxSimultanousThreads, 24, TimeUnit.HOURS, new ArrayBlockingQueue<Runnable>(classes.size()));
final Map<IdEObject, IdEObject> bigMap = new HashMap<IdEObject, IdEObject>();
HideAllInversesObjectIDM idm = new HideAllInversesObjectIDM(CollectionUtils.singleSet(packageMetaData.getEPackage()), model.getPackageMetaData());
OidProvider oidProvider = new OidProvider() {
@Override
public long newOid(EClass eClass) {
return databaseSession.newOid(eClass);
}
};
for (final EClass eClass : classes) {
final BasicIfcModel targetModel = new BasicIfcModel(model.getPackageMetaData(), null);
ModelHelper modelHelper = new ModelHelper(bimServer.getMetaDataManager(), targetModel);
modelHelper.setOidProvider(oidProvider);
modelHelper.setObjectIDM(idm);
IdEObject newOwnerHistory = modelHelper.copyBasicObjects(model, bigMap);
for (IdEObject idEObject : model.getAll(eClass)) {
IdEObject newObject = modelHelper.copy(idEObject, false, ModelHelper.createObjectIdm(idEObject.eClass()));
modelHelper.copyDecomposes(idEObject, newOwnerHistory);
bigMap.put(newObject, idEObject);
if (packageMetaData.getEClass("IfcElement").isSuperTypeOf(eClass)) {
EStructuralFeature hasOpeningsFeature = idEObject.eClass().getEStructuralFeature("HasOpenings");
for (IdEObject ifcRelVoidsElement : ((List<IdEObject>) idEObject.eGet(hasOpeningsFeature))) {
bigMap.put(modelHelper.copy(ifcRelVoidsElement, false), ifcRelVoidsElement);
EStructuralFeature relatedOpeningElementFeature = ifcRelVoidsElement.eClass().getEStructuralFeature("RelatedOpeningElement");
IdEObject relatedOpeningElement = (IdEObject) ifcRelVoidsElement.eGet(relatedOpeningElementFeature);
if (relatedOpeningElement != null) {
bigMap.put(modelHelper.copy(relatedOpeningElement, false), relatedOpeningElement);
}
}
}
}
executor.submit(new Runner(eClass, renderEnginePool, databaseSession, settings, store, targetModel, ifcSerializerPlugin, model, pid, rid, bigMap, renderEngineFilter, generateGeometryResult));
}
executor.shutdown();
executor.awaitTermination(24, TimeUnit.HOURS);
}
long end = System.nanoTime();
LOGGER.info("Rendertime: " + ((end - start) / 1000000) + "ms, " + "Reused: " + Formatters.bytesToString(bytesSaved.get()) + ", Total: " + Formatters.bytesToString(totalBytes.get()) + ", Final: " + Formatters.bytesToString(totalBytes.get() - bytesSaved.get()));
} catch (Exception e) {
LOGGER.error("", e);
throw new GeometryGeneratingException(e);
}
return generateGeometryResult;
}
use of org.bimserver.plugins.renderengine.RenderEngineSettings in project BIMserver by opensourceBIM.
the class TestGen method start.
private void start(String[] args) {
try {
PluginManagerInterface pluginManager = LocalDevSetup.setupPluginManager(args);
DeserializerPlugin deserializerPlugin = pluginManager.getFirstDeserializer("ifc", Schema.IFC2X3TC1, true);
Deserializer deserializer = deserializerPlugin.createDeserializer(null);
deserializer.init(pluginManager.getMetaDataManager().getPackageMetaData("ifc2x3tc1"));
RenderEnginePlugin renderEnginePlugin = pluginManager.getRenderEnginePlugin("org.bimserver.ifcengine.JvmRenderEnginePlugin", true);
RenderEngine renderEngine = renderEnginePlugin.createRenderEngine(null, "ifc2x3tc1");
renderEngine.init();
Path path = Paths.get("../TestData/data/AC11-Institute-Var-2-IFC.ifc");
RenderEngineModel renderEngineModel = renderEngine.openModel(new FileInputStream(path.toFile()), Files.size(path));
RenderEngineSettings settings = new RenderEngineSettings();
settings.setPrecision(Precision.SINGLE);
settings.setIndexFormat(IndexFormat.AUTO_DETECT);
settings.setGenerateNormals(true);
settings.setGenerateTriangles(true);
settings.setGenerateWireFrame(false);
renderEngineModel.setSettings(settings);
renderEngineModel.generateGeneralGeometry();
renderEngineModel.close();
renderEngine.close();
long start = System.nanoTime();
long end = System.nanoTime();
System.out.println(((end - start) / 1000000) + " ms");
} catch (PluginException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
use of org.bimserver.plugins.renderengine.RenderEngineSettings in project BIMserver by opensourceBIM.
the class StreamingGeometryGenerator method generateGeometry.
@SuppressWarnings("unchecked")
public GenerateGeometryResult generateGeometry(long uoid, final DatabaseSession databaseSession, QueryContext queryContext) throws BimserverDatabaseException, GeometryGeneratingException {
GenerateGeometryResult generateGeometryResult = new GenerateGeometryResult();
packageMetaData = queryContext.getPackageMetaData();
productClass = packageMetaData.getEClass("IfcProduct");
geometryFeature = productClass.getEStructuralFeature("geometry");
representationFeature = productClass.getEStructuralFeature("Representation");
representationsFeature = packageMetaData.getEClass("IfcProductDefinitionShape").getEStructuralFeature("Representations");
itemsFeature = packageMetaData.getEClass("IfcShapeRepresentation").getEStructuralFeature("Items");
mappingSourceFeature = packageMetaData.getEClass("IfcMappedItem").getEStructuralFeature("MappingSource");
GregorianCalendar now = new GregorianCalendar();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
debugIdentifier = dateFormat.format(now.getTime());
long start = System.nanoTime();
String pluginName = "";
if (queryContext.getPackageMetaData().getSchema() == Schema.IFC4) {
pluginName = "org.bimserver.ifc.step.serializer.Ifc4StepStreamingSerializerPlugin";
} else if (queryContext.getPackageMetaData().getSchema() == Schema.IFC2X3TC1) {
pluginName = "org.bimserver.ifc.step.serializer.Ifc2x3tc1StepStreamingSerializerPlugin";
} else {
throw new GeometryGeneratingException("Unknown schema " + queryContext.getPackageMetaData().getSchema());
}
reuseGeometry = bimServer.getServerSettingsCache().getServerSettings().isReuseGeometry();
optimizeMappedItems = bimServer.getServerSettingsCache().getServerSettings().isOptimizeMappedItems();
report.setStart(new GregorianCalendar());
report.setIfcSchema(queryContext.getPackageMetaData().getSchema());
report.setMaxPerFile(maxObjectsPerFile);
report.setUseMappingOptimization(optimizeMappedItems);
report.setReuseGeometry(reuseGeometry);
try {
final StreamingSerializerPlugin ifcSerializerPlugin = (StreamingSerializerPlugin) bimServer.getPluginManager().getPlugin(pluginName, true);
if (ifcSerializerPlugin == null) {
throw new UserException("No IFC serializer found");
}
User user = (User) databaseSession.get(uoid, org.bimserver.database.OldQuery.getDefault());
UserSettings userSettings = user.getUserSettings();
report.setUserName(user.getName());
report.setUserUserName(user.getUsername());
RenderEnginePluginConfiguration renderEngine = null;
if (eoid != -1) {
renderEngine = databaseSession.get(eoid, OldQuery.getDefault());
} else {
renderEngine = userSettings.getDefaultRenderEngine();
}
if (renderEngine == null) {
throw new UserException("No default render engine has been selected for this user");
}
renderEngineName = renderEngine.getName();
int availableProcessors = Runtime.getRuntime().availableProcessors();
report.setAvailableProcessors(availableProcessors);
int maxSimultanousThreads = Math.min(bimServer.getServerSettingsCache().getServerSettings().getRenderEngineProcesses(), availableProcessors);
if (maxSimultanousThreads < 1) {
maxSimultanousThreads = 1;
}
final RenderEngineSettings settings = new RenderEngineSettings();
settings.setPrecision(Precision.SINGLE);
settings.setIndexFormat(IndexFormat.AUTO_DETECT);
settings.setGenerateNormals(true);
settings.setGenerateTriangles(true);
settings.setGenerateWireFrame(false);
final RenderEngineFilter renderEngineFilter = new RenderEngineFilter();
RenderEnginePool renderEnginePool = bimServer.getRenderEnginePools().getRenderEnginePool(packageMetaData.getSchema(), renderEngine.getPluginDescriptor().getPluginClassName(), new PluginConfiguration(renderEngine.getSettings()));
report.setRenderEngineName(renderEngine.getName());
report.setRenderEnginePluginVersion(renderEngine.getPluginDescriptor().getPluginBundleVersion().getVersion());
try (RenderEngine engine = renderEnginePool.borrowObject()) {
report.setRenderEngineVersion(engine.getVersion());
}
ThreadPoolExecutor executor = new ThreadPoolExecutor(maxSimultanousThreads, maxSimultanousThreads, 24, TimeUnit.HOURS, new ArrayBlockingQueue<Runnable>(10000000));
JsonQueryObjectModelConverter jsonQueryObjectModelConverter = new JsonQueryObjectModelConverter(packageMetaData);
String queryNameSpace = "validifc";
if (packageMetaData.getSchema() == Schema.IFC4) {
queryNameSpace = "ifc4stdlib";
}
Include objectPlacement = jsonQueryObjectModelConverter.getDefineFromFile(queryNameSpace + ":ObjectPlacement");
// TODO these are cached, so f'ing em up by doing this...
objectPlacement.makeDirectRecursive(new HashSet<>());
Set<EClass> classes = null;
if (queryContext.getOidCounters() != null) {
classes = queryContext.getOidCounters().keySet();
} else {
classes = packageMetaData.getEClasses();
}
for (EClass eClass : classes) {
if (packageMetaData.getEClass("IfcProduct").isSuperTypeOf(eClass)) {
Query query2 = new Query(eClass.getName() + "Main query", packageMetaData);
QueryPart queryPart2 = query2.createQueryPart();
queryPart2.addType(eClass, false);
Include representationInclude = queryPart2.createInclude();
representationInclude.addType(eClass, false);
representationInclude.addFieldDirect("Representation");
Include representationsInclude = representationInclude.createInclude();
representationsInclude.addType(packageMetaData.getEClass("IfcProductRepresentation"), true);
representationsInclude.addFieldDirect("Representations");
Include itemsInclude = representationsInclude.createInclude();
itemsInclude.addType(packageMetaData.getEClass("IfcShapeRepresentation"), false);
itemsInclude.addFieldDirect("Items");
Include mappingSourceInclude = itemsInclude.createInclude();
mappingSourceInclude.addType(packageMetaData.getEClass("IfcMappedItem"), false);
mappingSourceInclude.addFieldDirect("MappingSource");
mappingSourceInclude.addFieldDirect("MappingTarget");
Include representationMap = mappingSourceInclude.createInclude();
representationMap.addType(packageMetaData.getEClass("IfcRepresentationMap"), false);
Include targetInclude = mappingSourceInclude.createInclude();
targetInclude.addType(packageMetaData.getEClass("IfcCartesianTransformationOperator3D"), false);
targetInclude.addFieldDirect("Axis1");
targetInclude.addFieldDirect("Axis2");
targetInclude.addFieldDirect("Axis3");
targetInclude.addFieldDirect("LocalOrigin");
queryPart2.addInclude(objectPlacement);
Map<Long, Map<Long, ProductDef>> representationMapToProduct = new HashMap<>();
QueryObjectProvider queryObjectProvider2 = new QueryObjectProvider(databaseSession, bimServer, query2, Collections.singleton(queryContext.getRoid()), packageMetaData);
HashMapVirtualObject next = queryObjectProvider2.next();
while (next != null) {
if (next.eClass() == eClass) {
HashMapVirtualObject representation = next.getDirectFeature(representationFeature);
if (representation != null) {
List<HashMapVirtualObject> representations = representation.getDirectListFeature(representationsFeature);
if (representations != null) {
for (HashMapVirtualObject representationItem : representations) {
String representationIdentifier = (String) representationItem.get("RepresentationIdentifier");
if (representationIdentifier.equals("Body") || representationIdentifier.equals("Facetation")) {
List<HashMapVirtualObject> items = representationItem.getDirectListFeature(itemsFeature);
for (HashMapVirtualObject item : items) {
report.addRepresentationItem(item.eClass().getName());
HashMapVirtualObject mappingTarget = item.getDirectFeature(packageMetaData.getEReference("IfcMappedItem", "MappingTarget"));
double[] mappingMatrix = Matrix.identity();
double[] productMatrix = Matrix.identity();
if (mappingTarget != null) {
HashMapVirtualObject axis1 = mappingTarget.getDirectFeature(packageMetaData.getEReference("IfcCartesianTransformationOperator", "Axis1"));
HashMapVirtualObject axis2 = mappingTarget.getDirectFeature(packageMetaData.getEReference("IfcCartesianTransformationOperator", "Axis2"));
HashMapVirtualObject axis3 = mappingTarget.getDirectFeature(packageMetaData.getEReference("IfcCartesianTransformationOperator", "Axis3"));
HashMapVirtualObject localOrigin = mappingTarget.getDirectFeature(packageMetaData.getEReference("IfcCartesianTransformationOperator", "LocalOrigin"));
double[] a1 = null;
double[] a2 = null;
double[] a3 = null;
if (axis3 != null) {
List<Double> list = (List<Double>) axis3.get("DirectionRatios");
a3 = new double[] { list.get(0), list.get(1), list.get(2) };
} else {
a3 = new double[] { 0, 0, 1, 1 };
Vector.normalize(a3);
}
if (axis1 != null) {
List<Double> list = (List<Double>) axis1.get("DirectionRatios");
a1 = new double[] { list.get(0), list.get(1), list.get(2) };
Vector.normalize(a1);
} else {
// if (a3[0] == 1 && a3[1] == 0 && a3[2] == 0) {
a1 = new double[] { 1, 0, 0, 1 };
// } else {
// a1 = new double[]{0, 1, 0, 1};
// }
}
double[] xVec = Vector.scalarProduct(Vector.dot(a1, a3), a3);
double[] xAxis = Vector.subtract(a1, xVec);
Vector.normalize(xAxis);
if (axis2 != null) {
List<Double> list = (List<Double>) axis2.get("DirectionRatios");
a2 = new double[] { list.get(0), list.get(1), list.get(2) };
Vector.normalize(a2);
} else {
a2 = new double[] { 0, 1, 0, 1 };
}
double[] tmp = Vector.scalarProduct(Vector.dot(a2, a3), a3);
double[] yAxis = Vector.subtract(a2, tmp);
tmp = Vector.scalarProduct(Vector.dot(a2, xAxis), xAxis);
yAxis = Vector.subtract(yAxis, tmp);
Vector.normalize(yAxis);
a2 = yAxis;
a1 = xAxis;
List<Double> t = (List<Double>) localOrigin.get("Coordinates");
mappingMatrix = new double[] { a1[0], a1[1], a1[2], 0, a2[0], a2[1], a2[2], 0, a3[0], a3[1], a3[2], 0, t.get(0).doubleValue(), t.get(1).doubleValue(), t.get(2).doubleValue(), 1 };
}
HashMapVirtualObject placement = next.getDirectFeature(packageMetaData.getEReference("IfcProduct", "ObjectPlacement"));
if (placement != null) {
productMatrix = placementToMatrix(placement);
}
HashMapVirtualObject mappingSource = item.getDirectFeature(mappingSourceFeature);
if (mappingSource != null) {
Map<Long, ProductDef> map = representationMapToProduct.get(mappingSource.getOid());
if (map == null) {
map = new LinkedHashMap<>();
representationMapToProduct.put(mappingSource.getOid(), map);
}
ProductDef pd = new ProductDef(next.getOid());
pd.setObject(next);
pd.setProductMatrix(productMatrix);
pd.setMappingMatrix(mappingMatrix);
map.put(next.getOid(), pd);
}
}
}
}
}
}
}
next = queryObjectProvider2.next();
}
Set<Long> done = new HashSet<>();
for (Long repMapId : representationMapToProduct.keySet()) {
Map<Long, ProductDef> map = representationMapToProduct.get(repMapId);
if (map.size() > 1) {
Query query = new Query("Reuse query " + eClass.getName(), packageMetaData);
QueryPart queryPart = query.createQueryPart();
queryPart.addType(eClass, false);
long masterOid = map.values().iterator().next().getOid();
for (ProductDef pd : map.values()) {
done.add(pd.getOid());
if (!optimizeMappedItems) {
queryPart.addOid(pd.getOid());
} else {
pd.setMasterOid(masterOid);
}
}
if (optimizeMappedItems) {
queryPart.addOid(masterOid);
}
LOGGER.debug("Running " + map.size() + " objects in one batch because of reused geometry " + (eClass.getName()));
processX(databaseSession, queryContext, generateGeometryResult, ifcSerializerPlugin, settings, renderEngineFilter, renderEnginePool, executor, eClass, query, queryPart, true, map, map.size());
}
}
Query query3 = new Query("Remaining " + eClass.getName(), packageMetaData);
QueryPart queryPart3 = query3.createQueryPart();
queryPart3.addType(eClass, false);
Include include3 = queryPart3.createInclude();
include3.addType(eClass, false);
include3.addFieldDirect("Representation");
Include rInclude = include3.createInclude();
rInclude.addType(packageMetaData.getEClass("IfcProductRepresentation"), false);
rInclude.addFieldDirect("Representations");
Include representationsInclude2 = rInclude.createInclude();
representationsInclude2.addType(packageMetaData.getEClass("IfcShapeModel"), false);
queryObjectProvider2 = new QueryObjectProvider(databaseSession, bimServer, query3, Collections.singleton(queryContext.getRoid()), packageMetaData);
next = queryObjectProvider2.next();
while (next != null) {
if (next.eClass() == eClass && !done.contains(next.getOid())) {
HashMapVirtualObject representation = next.getDirectFeature(representationFeature);
if (representation != null) {
List<HashMapVirtualObject> list = representation.getDirectListFeature(packageMetaData.getEReference("IfcProductRepresentation", "Representations"));
boolean goForIt = goForIt(list);
if (goForIt) {
Query query = new Query("Main " + eClass.getName(), packageMetaData);
QueryPart queryPart = query.createQueryPart();
queryPart.addType(eClass, false);
int x = 1;
queryPart.addOid(next.getOid());
while (next != null && x < maxObjectsPerFile) {
next = queryObjectProvider2.next();
if (next != null) {
if (next.eClass() == eClass && !done.contains(next.getOid())) {
representation = next.getDirectFeature(representationFeature);
if (representation != null) {
list = representation.getDirectListFeature(packageMetaData.getEReference("IfcProductRepresentation", "Representations"));
boolean goForIt2 = goForIt(list);
if (goForIt2) {
queryPart.addOid(next.getOid());
x++;
}
}
}
}
}
processX(databaseSession, queryContext, generateGeometryResult, ifcSerializerPlugin, settings, renderEngineFilter, renderEnginePool, executor, eClass, query, queryPart, false, null, x);
}
}
}
next = queryObjectProvider2.next();
}
}
}
// for (Long l : counters.keySet()) {
// LOGGER.info(databaseSession.getEClassForOid(l).getName() + "(" + l + "): " + counters.get(l));
// }
allJobsPushed = true;
executor.shutdown();
executor.awaitTermination(24, TimeUnit.HOURS);
long end = System.nanoTime();
long total = totalBytes.get() - (bytesSavedByHash.get() + bytesSavedByTransformation.get() + bytesSavedByMapping.get());
LOGGER.info("Rendertime: " + Formatters.nanosToString(end - start) + ", " + "Reused (by hash): " + Formatters.bytesToString(bytesSavedByHash.get()) + ", Reused (by transformation): " + Formatters.bytesToString(bytesSavedByTransformation.get()) + ", Reused (by mapping): " + Formatters.bytesToString(bytesSavedByMapping.get()) + ", Total: " + Formatters.bytesToString(totalBytes.get()) + ", Final: " + Formatters.bytesToString(total));
} catch (Exception e) {
running = false;
LOGGER.error("", e);
report.setEnd(new GregorianCalendar());
throw new GeometryGeneratingException(e);
}
report.setEnd(new GregorianCalendar());
try {
writeDebugFile();
} catch (IOException e) {
LOGGER.debug("", e);
}
return generateGeometryResult;
}
use of org.bimserver.plugins.renderengine.RenderEngineSettings in project BIMserver by opensourceBIM.
the class OfflineGeometryGenerator method generateForAllElements.
public void generateForAllElements() {
try {
serializer.init(model, null, true);
InputStream in = new SerializerInputstream(serializer);
renderEngineModel = renderEngine.openModel(in);
final RenderEngineSettings settings = new RenderEngineSettings();
settings.setPrecision(Precision.SINGLE);
settings.setIndexFormat(IndexFormat.AUTO_DETECT);
settings.setGenerateNormals(true);
settings.setGenerateTriangles(true);
settings.setGenerateWireFrame(false);
final RenderEngineFilter renderEngineFilter = new RenderEngineFilter();
renderEngineModel.setSettings(settings);
renderEngineModel.setFilter(renderEngineFilter);
renderEngineModel.generateGeneralGeometry();
for (IfcProduct ifcProduct : model.getAllWithSubTypes(IfcProduct.class)) {
generateGeometry(ifcProduct);
}
} catch (SerializerException e) {
e.printStackTrace();
} catch (RenderEngineException e) {
e.printStackTrace();
}
}
Aggregations