Creating a JTable just gets to create a DefaultTableModel - java

I'm new programming and I'm having many problems... I was just trying to create a JTable to export it afterwards to an excel. The code I'm using is:
<%# page import="java.sql.*" %>
<%# page import = "java.util.Properties"%>
<%# page import = "java.util.ArrayList"%>
<%# page import = "java.io.*" %>
<%# page import = "java.util.Iterator" %>
<%# page import = "javax.swing.*" %>
<%# page import = "java.awt.*" %>
<%# page import = "javax.swing.table.*" %>
<%# page import = "javax.swing.JScrollPane" %>
DefaultTableModel model = new DefaultTableModel();
for(int col=1; col<=numberOfColumns; col++)
{
columnName = rsMetaData.getColumnName(col);
model.addColumn(columnName);
}
while (rs.next())
{
Object [] fila = new Object[numberOfColumns];
for (int i=0;i<numberOfColumns;i++)
fila[i] = rs.getObject(i+1);
model.addRow(fila);
}
JTable tabla = new JTable(model);
If I bug the code I'm able to see that I have information in the different lines and columns, but nothing appears in tabla... I've been searching in several websites and it's the only structure I've found that I more or less undesrtood. In some of those webs kept going with the code with sentences like that:
JScrollPane scrollpane = new JScrollPane(tabla);
but I'm not able to go further with the tabla problem...

Related

JSP Repository is not iniatlized

I am trying to initalize my repository inside on of my JSP's. I have imported it above the code but yet it still says it is not initilized.
The code below is the top of the page.
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%# page import="java.util.List" %>
<%# page import="java.util.ArrayList" %>
<%# page import="co2103.hw2.domain.TestResults" %>
<%# page import="co2103.hw2.repositories.TestResultsRepository" %>
<%# page import="org.springframework.beans.factory.annotation.Autowired" %>
<% TestResultsRepository TRRepo; <! DECLARED HERE
int size = 100;
for (int i = 0; i< size; i++) {
List<String> list = TRRepo.findAllById(i); <! SAYS HERE THAT IT IS NOT INITALIZED
}
System.out.println("List initalized!");
%>
Does anyone know how to fix this? I am new to programming Java so any help would be very appreciated.
TEST RESULTS REPOSITORY CLASS
public interface TestResultsRepository extends CrudRepository<TestResults, String> {
String findAllById(int id);
}

c:forEach doesn't print map contents in JSP

Disclaimer: I've spent today researching this simple problem inside and out all across stachoverflow and beyond so please bear with me.
I have the following code on JSP:
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%#page import="com.contrast.db.Manager"%>
<%#page import="java.sql.Connection"%>
<%#page import="java.util.Map"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
Integer age = Integer.valueOf(request.getParameter("age"));
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Test</title>
</head>
<body>
<%
Manager db = new Manager();
Connection conn = db.getConnection();
if (null == conn) {
out.println("Connection to MySQL failed");
} else {
out.println("Connection to MySQL succeeded");
}
Map<String, Integer> namesAndAge = db.findByAge(age);
%>
<h1>List of users older then <% out.println(age); %></h1>
<% out.println(namesAndAge); %>
<c:forEach items="${namesAndAge}" var="entry">
Key = ${entry.key}, value = ${entry.value}<br>
</c:forEach>
</body>
</html>
This code for intents and purposes should print out the contents of the HashMap returned by db.findByAge(age) but it doesn't
Understandably one could assume that HashMap could be empty, but it's not (please see screen shot below)
As you can see the HashMap is not empty but is not working
Any ideas what am I missing?
On the scriplets you declare objects, while in EL expressions what are referenced are attributes in a context (pageContext, request, session or application).
change this line:
Map<String, Integer> namesAndAge = db.findByAge(age);
For this:
request.setAttribute("namesAndAge", db.findByAge(age));

how to open a jasper report exporting to pdf in a new window

I have been exporting jasper report to pdf but it opens in the same window which is a problem to me because if i want to go to previous page i cant be able to go to previous page so i thought of opening pdf page in a new window but i dont have any idea of how to open it in a new window.
sample1.jsp
<%# page import="java.io.*"%>
<%# page import="java.sql.Connection"%>
<%# page import="java.sql.DriverManager"%>
<%# page import="java.util.HashMap"%>
<%# page import="java.util.Map"%>
<%# page import="net.sf.jasperreports.engine.*"%>
<%# page import="net.sf.jasperreports.engine.*" %>
<%# page import="java.text.SimpleDateFormat" %>
<%# page import="java.text.ParseException" %>
<%# page import="java.io.File" %>
<%# page import="java.io.FileInputStream" %>
<%# page import="java.io.FileNotFoundException" %>
<%# page import="java.io.InputStream" %>
<%# page import="java.sql.Connection" %>
<%# page import="java.sql.DriverManager" %>
<%# page import="java.sql.SQLException" %>
<%# page import="java.io.FileOutputStream" %>
<%# page import="java.io.ByteArrayOutputStream" %>
<%# page import="java.io.OutputStream" %>
<%# page import="java.util.HashMap" %>
<%# page import="java.util.Map" %>
<%# page import="net.sf.jasperreports.engine.util.*" %>
<%# page import="net.sf.jasperreports.engine.export.*" %>
<%#page import = "net.sf.jasperreports.engine.design.JRDesignQuery"%>
<%#page import = "net.sf.jasperreports.engine.xml.JRXmlLoader"%>
<%#page import = "net.sf.jasperreports.engine.design.JasperDesign"%>
<%#page import = "net.sf.jasperreports.view.JasperViewer"%>
<%#page import = "net.sf.jasperreports.engine.JRException"%>
<%#page import = "net.sf.jasperreports.engine.JRResultSetDataSource"%>
<%#page import = "net.sf.jasperreports.engine.JasperCompileManager"%>
<%#page import = "net.sf.jasperreports.engine.JasperExportManager"%>
<%#page import = "net.sf.jasperreports.engine.JasperFillManager"%>
<%#page import = "net.sf.jasperreports.engine.JasperPrint"%>
<%#page import = "net.sf.jasperreports.engine.JasperReport"%>
<%#page import = "net.sf.jasperreports.engine.data.JRCsvDataSource"%>
<%#page import = "net.sf.jasperreports.engine.export.ooxml.JRDocxExporter"%>
<%#page import = "net.sf.jasperreports.engine.export.JRPdfExporter"%>
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<%
Connection conn = null;
String cate=(String)session.getAttribute("cat");
String stat=(String)session.getAttribute("sta");
String dayy=(String)session.getAttribute("da");
String monthh=(String)session.getAttribute("mon");
String yearr=(String)session.getAttribute("yea");
String dayy1=(String)session.getAttribute("da1");
String monthh1=(String)session.getAttribute("mon1");
String yearr1=(String)session.getAttribute("yea1");
System.out.println("2 is:"+cate);
System.out.println("4 is:"+stat);
System.out.println("5 is:"+dayy);
System.out.println("6 is:"+monthh);
System.out.println("7 is:"+yearr);
System.out.println("8 is:"+dayy1);
System.out.println("9 is:"+monthh1);
System.out.println("10 is:"+yearr1);
try
{
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/marketing_database","root","root");
String sql="select * from lead where Status='" + stat.replaceAll("\\'","''") + "'";
sql+=" AND Category='" + cate.replaceAll("\\'","''") + "'";
sql+=" AND DATE(Lead_Date)>='" + yearr + "-" + monthh + "-" + dayy + "'";
sql+=" AND DATE(Lead_Date)<='" + yearr1 + "-" + monthh1 + "-" + dayy1 + "'";
String jrxmlFile ="D:/dev/tools/jasper files/report3.jrxml";
InputStream input = new FileInputStream(new File(jrxmlFile));
JasperDesign jasperDesign = JRXmlLoader.load(input);
System.out.println("Compiling Report Designs");
JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
System.out.println("Creating JasperPrint Object");
HashMap<String,Object> map = new HashMap<String,Object>();
map.put("sql",sql);
byte[] bytes = JasperRunManager.runReportToPdf(jasperReport, map, conn);
response.setContentType("application/pdf");
response.setContentLength(bytes.length);
ServletOutputStream outStream = response.getOutputStream();
outStream.write(bytes, 0, bytes.length);
outStream.flush();
outStream.close();
}
catch(Exception e)
{e.printStackTrace();}
%>
</body>
</html>
view.jsp
<script type="text/javascript">
function setAction(nPage){
document.forms[0].action = nPage;
}
</script>
</head>
<body>
<form>
<%
String category=request.getParameter("category");
session.setAttribute("cat",category);
String status=request.getParameter("status");
session.setAttribute("sta",status);
System.out.println("status is:"+status);
String day=request.getParameter("day");
session.setAttribute("da",day);
String month=request.getParameter("month");
session.setAttribute("mon",month);
String year=request.getParameter("year");
session.setAttribute("yea",year);
String day1=request.getParameter("day1");
session.setAttribute("da1",day1);
String month1=request.getParameter("month1");
session.setAttribute("mon1",month1);
String year1=request.getParameter("year1");
session.setAttribute("yea1",year1);
%>
<select onchange="setAction(this.value)">
<option value=''> Make a selection </option>
<option value='sample1.jsp'> PDF</option>
<option value='XLS_LEAD.jsp'> XLS </option>
<option value='DOC_LEAD.jsp'> DOC </option>
<option value='XLSX_LEAD.jsp'> XLSX </option>
</select>
<br/>
<input type="submit" value="Submit">
</form>
</body>
Considering your view.jsp
I can see that you already have put all variables into the session you are only using the form to select to which page you need to go.
You can do something like this...
<script type="text/javascript">
function generateReport() {
var e = document.getElementById("idOfYourSelectYouNeedToAddedIt");
var strPage = e.options[e.selectedIndex].value;
window.open(strPage);
return false; //This make you stay on this page;
//return true; //Set the action tag in the form to the page you like to go to!
}
</script>
<form name="myForm" onsubmit="return generateReport()">
<select id = "idOfYourSelectYouNeedToAddedIt">
<option value=''> Make a selection </option>
..... the other option values
</form>
Note if you like to go to another page you can simple add action tag to your form tag and return true in the generateReport() function
example
<form name="myForm" action="thisIsWhereILikeToGo.jsp" onsubmit="return generateReport()">
Note: You should remove the onchange="setAction(this.value) code, it has no use anymore and consider checking that strPage is not empty, no selection...

how to update large information in excel to oracle database using jsp or servlet or java

in my project i have a excel sheet which contains the marks,id,credits in large number... i need to upload into database from excel file.... iam using apache poi to read and update but iam getting error...
DB_Connection.java
package DB;
import java.sql.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DB_Connection
{
// private String datasize;
private Connection con;
public DB_Connection()
{
try
{
String conUrl="jdbc:oracle:thin:#localhost:1521:xe";
String userName="SYSTEM";
String pass="raje";
Class.forName("oracle.jdbc.driver.OracleDriver");
con=DriverManager.getConnection(conUrl,userName,pass);
}
catch(Exception s)
{
System.out.println(s);
}
}
public Connection getConn()
{
return con;
}
public void setConn(Connection con)
{
this.con = con;
}
}
readExcel.jsp:
<%#page language="java" import="java.sql.*" contentType="text/html" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<%# page import ="java.util.Date" %>
<%# page import ="java.io.*" %>
<%# page import ="java.io.FileNotFoundException" %>
<%# page import ="java.io.IOException" %>
<%# page import ="java.util.Iterator" %>
<%# page import ="java.util.ArrayList" %>
<%# page import ="org.apache.poi.hssf.usermodel.HSSFCell" %>
<%# page import ="org.apache.poi.hssf.usermodel.HSSFRow" %>
<%# page import ="org.apache.poi.hssf.usermodel.HSSFSheet" %>
<%# page import ="org.apache.poi.hssf.usermodel.HSSFWorkbook" %>
<%# page import ="org.apache.poi.poifs.filesystem.POIFSFileSystem" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<jsp:useBean id="connection" class="DB.DB_Connection" scope="application">
<jsp:setProperty name="connection" property="*"/>
</jsp:useBean>
<%!
Connection con;
PreparedStatement ps=null;
public static ArrayList readExcelFile(String fileName)
{
/** --Define a ArrayList
--Holds ArrayList Of Cells
*/
ArrayList cellArrayListHolder = new ArrayList();
try{
/** Creating Input Stream**/
FileInputStream myInput = new FileInputStream(fileName);
// System.out.print("myInput");
/** Create a POIFSFileSystem object**/
POIFSFileSystem myFileSystem = new POIFSFileSystem(myInput);
/** Create a workbook using the File System**/
HSSFWorkbook myWorkBook = new HSSFWorkbook(myFileSystem);
/** Get the first sheet from workbook**/
HSSFSheet mySheet = myWorkBook.getSheetAt(0);
/** We now need something to iterate through the cells.**/
Iterator rowIter = mySheet.rowIterator();
while(rowIter.hasNext())
{
HSSFRow myRow = (HSSFRow) rowIter.next();
Iterator cellIter = myRow.cellIterator();
ArrayList cellStoreArrayList=new ArrayList();
while(cellIter.hasNext())
{
HSSFCell myCell = (HSSFCell) cellIter.next();
cellStoreArrayList.add(myCell);
}
cellArrayListHolder.add(cellStoreArrayList);
}
}
catch (Exception e)
{
e.printStackTrace();
}
return cellArrayListHolder;
}%>
<%
String fileName="C://Documents and Settings//raje//Desktop//JGRESULTS1.xls";
ArrayList dataHolder=readExcelFile(fileName);
//Print the data read
//printCellDataToConsole(dataHolder);
con= connection.getConn();
ps=con.prepareStatement("insert into sample2 values(?,?,?,?)");
int count=1;
ArrayList cellStoreArrayList=null;
//For inserting into database
for (int i=1;i < dataHolder.size(); i++)
{
cellStoreArrayList=(ArrayList)dataHolder.get(i);
ps.setString(1,((HSSFCell)cellStoreArrayList.get(0)).toString());
ps.setString(2,((HSSFCell)cellStoreArrayList.get(1)).toString());
ps.setString(3,((HSSFCell)cellStoreArrayList.get(2)).toString());
ps.setString(4,((HSSFCell)cellStoreArrayList.get(3)).toString());
count= ps.executeUpdate();
System.out.print(((HSSFCell)cellStoreArrayList.get(3)).toString() + "\t");
}
count++;
//For checking data is inserted or not?
if(count>0)
{ %>
Following details from Excel file have been inserted in student table of database
<table>
<tr>
<th>Student's Name</th>
<th>Class</th>
<th>external</th>
<th>credits</th>
</tr>
<% for (int i=1;i < dataHolder.size(); i++) {
cell StoreArrayList=(ArrayList)dataHolder.get(i);%>
<tr>
<td><%=((HSSFCell)cellStoreArrayList.get(0)).toString() %></td>
<td><%=((HSSFCell)cellStoreArrayList.get(1)).toString() %></td>
<td><%=((HSSFCell)cellStoreArrayList.get(2)).toString() %></td>
<td><%=((HSSFCell)cellStoreArrayList.get(3)).toString() %></td>
</tr>
<%}
}
else
{%>
<% out.print("not successfull");
} %>
</table>
</body>
</html>
output:
type Exception report
message
description The server encountered an internal error () that prevented it from fulfilling this request.
exception
org.apache.jasper.JasperException: An exception occurred processing JSP page /readExcel.jsp at line 98
95: {
96: cellStoreArrayList=(ArrayList)dataHolder.get(i);
97: ps.setString(1,((HSSFCell)cellStoreArrayList.get(0)).toString());
98: ps.setString(2,((HSSFCell)cellStoreArrayList.get(1)).toString());
99: ps.setString(3,((HSSFCell)cellStoreArrayList.get(2)).toString());
100: ps.setString(4,((HSSFCell)cellStoreArrayList.get(3)).toString());
101: count= ps.executeUpdate();
Stacktrace:
org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:553)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:457)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:333)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:3 93)
root cause
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
java.util.ArrayList.RangeCheck(ArrayList.java:547)
java.util.ArrayList.get(ArrayList.java:322)
org.apache.jsp.readExcel_jsp._jspService(readExcel_jsp.java:175)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:419)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:333)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
You'll get more and better help if you actually post the error.
This code is a mess. It's doing too much:
POI to read and parse spreadsheets
JSP to display
JDBC to persist
I'd recommend decomposing it into pieces as separate classes that you can develop, test, and put aside.
No one should be writing JSPs with scriptlets. That's a discredited 1999 style. Better to learn JSTL and add some servlets.
UPDATE:
Here's the cause:
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
java.util.ArrayList.RangeCheck(ArrayList.java:547)
You've assumed that an array element is present, but the JVM disagrees with you.
Here's the essence of what you did wrong:
List<String> values = new ArrayList<String>();
values.add("element one");
System.out.println(values.size()); // this will print 1
System.out.println(values.get(100)); // there's only one element in the list, but you tried to access 100.
Error! Figure out where your code did something like this and you'll have it.
From looking at your code and the stack trace it looks like you are getting an IndexOutOfBoundsException because the row of cells in the cellStoreArrayList is only of length 1. I would recommend looking at your spreadsheet to ensure that every row you are reading in has 4 columns since this constraint is hardcoded.
On a related note, if you are going to hardcode array indices you should surround it in some kind of exception catching mechanism.
As someone pointed out: what you do is a very bad practice...
However, the current problem is most likely, that the row you are trying to read a cell from is not long enough, so the (note: array backed ) list runs out of bounds.
To be prepared for this situation, I'd do it this way:
cellStoreArrayList=(ArrayList)dataHolder.get(i);
for(int i=1;i<4;i++) { // I'd use a loop even for fixed number of iterations, I vigorously hate duplication
if(cellStoreArrayList.size()>=i) { // check for row to be long enough --> no ArrayOutOfBounds anymore HSSFCell cell = (HSSFCell)cellStoreArrayList.get(i-1);
if(cell!=null) { // check for null: no NullPointerException anymore...
ps.setString(i,cell.toString());
}
else {
ps.setString(i,"");
}
//ps.setString(i,cell==null?"":cell.toString()); //this is good too, but a bit probably less readable
}
}
Notes:
use generics! the List could have had a <HSSFCell> generic type, eliminating the need for a cast, and solving quite some possibilities for mistakes and errors
don't store the name fo the implementation in the variable name! cellStoreArrayList = bad! cellStoreList = good

applet (jfreechart) in jsp

I tried created below jsp.. but it is just keep on loading not showing any result... any help on optimizing this jsp Or let me know if this code is correct and it will show an applet on the browser.
As the code shows I am taking dynamic value from database and want to show them in pie chart on browser.
<%# page import="java.util.*" %>
<%# page import="java.sql.*" %>
<%# page import="java.sql.Connection" %>
<%# page import="java.text.SimpleDateFormat" %>
<%# page import= "javax.swing.*" %>
<%# page import= "java.awt.*" %>
<%# page import="java.awt.image.*" %>
<%# page import="org.jfree.chart.*" %>
<%# page import="org.jfree.chart.axis.*" %>
<%# page import="org.jfree.chart.entity.*" %>
<%# page import="org.jfree.chart.labels.*" %>
<%# page import="org.jfree.chart.plot.*" %>
<%# page import="org.jfree.chart.renderer.category.*" %>
<%# page import="org.jfree.chart.urls.*" %>
<%# page import="org.jfree.data.category.*" %>
<%# page import="org.jfree.data.general.*" %>
<%# page import= "org.jfree.chart.title.TextTitle" %>
<%# page import= "org.jfree.data.general.DefaultPieDataset" %>
<%# page import="org.jfree.ui.*" %>
<html>
<head>
</head>
<body>
<%
ResultSet rs = null;
Connection con =null;
Statement st=null;
try
{
String queryactive1 = null;
String queryactive2= null;
String queryactive3 = null;
String queryactive4 = null;
String queryactive5 = null;
String queryactive6 = null;
String queryactive7 = null;
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
con= DriverManager.getConnection("jdbc:sqlserver://newine:3468;instanceName=MSSQL2005","eGActiveDB_762","eGActiveDB_762");
st = con.createStatement();
%>
<p style="text-align:center"><B><u>Pie Chart Showing Case Count</u></B></p>
<%
queryactive1="SELECT count(a.case_id)as case_count , b.owner from EGPL_CASE a Right Outer Join (Select distinct OWNER from EGPL_CASE where owner in (1047,1213)) b on b.owner =a.owner and a.when_created BETWEEN '2011-01-01 00:00:00' AND '2011-01-01 1:59:59' group by b.OWNER order by b.owner";
rs=st.executeQuery(queryactive1);
rs.absolute(2);
int ravi_case=rs.getInt("case_count");
rs.absolute(4);
int pradeep_case=rs.getInt("case_count");
%>
<%
JPanel panel = new JPanel(new GridLayout(2, 2));
DefaultPieDataset dataset = new DefaultPieDataset();
DefaultPieDataset dataset1 = new DefaultPieDataset();
dataset.setValue("January "+ravi_case, ravi_case);
dataset1.setValue("January "+pradeep_case,pradeep_case);
JFreeChart chart1 = ChartFactory.createPieChart("Ravi Case", dataset, false, false, false);
JFreeChart chart2 = ChartFactory.createPieChart("Pradeep Case", dataset1, false, false, false);
panel.add(new ChartPanel(chart1));
panel.add(new ChartPanel(chart2));
panel.setPreferredSize(new Dimension(800, 600));
%>
<p style="text-align:center"><B><u>BAr Chart</u></B></p>
<%
}
catch(Exception e)
{
String error = e.toString();
e.printStackTrace();
%>
Error is : <%=error%>
<%
}
finally{
rs = null;
st = null;
con = null;
}
%>
</body>
</html>
No, it's not correct at all. An applet is a Java program, packaged in a jar file, that the browser downloads and executes in the client browser.
A JSP is some dynamically composed page that executes on the server, and outputs HTML which is rendered in the client browser.
If this code would display a JPanel (which id doesn't : it just constructs one), the panel would be displayed on the server screen, where the code is executed.
Finally, a JSP should not contain Java code for decades, but should use the JSTL and other custom tags. Read How to avoid Java code in JSP files?.
Read the Java tutorial about applets, try to create an applet displaying a graph with purely static data and embed it into a static HTML page, then make a JSP that contains the same code as the static JSP to embed the applet, and finally think of a way for the applet to communicate with the server to get the data allowing it to display the graph.

Categories

Resources