/*
* Aipo is a groupware program developed by TOWN, Inc.
* Copyright (C) 2004-2015 TOWN, Inc.
* http://www.aipo.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.aimluck.eip.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import org.apache.jetspeed.modules.actions.portlets.PortletFilter;
import org.apache.jetspeed.om.profile.IdentityElement;
import org.apache.jetspeed.om.profile.Layout;
import org.apache.jetspeed.om.profile.Parameter;
import org.apache.jetspeed.om.profile.Portlets;
import org.apache.jetspeed.om.registry.PortletEntry;
import org.apache.jetspeed.om.registry.PortletInfoEntry;
import org.apache.jetspeed.om.registry.RegistryEntry;
import org.apache.jetspeed.om.registry.base.BaseCategory;
import org.apache.jetspeed.om.registry.base.BasePortletEntry;
import org.apache.jetspeed.om.security.JetspeedUser;
import org.apache.jetspeed.portal.Portlet;
import org.apache.jetspeed.portal.PortletControl;
import org.apache.jetspeed.portal.PortletSet;
import org.apache.jetspeed.services.JetspeedSecurity;
import org.apache.jetspeed.services.Registry;
import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
import org.apache.jetspeed.services.logging.JetspeedLogger;
import org.apache.jetspeed.services.resources.JetspeedResources;
import org.apache.jetspeed.services.rundata.JetspeedRunData;
import org.apache.jetspeed.services.rundata.JetspeedRunDataService;
import org.apache.jetspeed.services.security.PortalResource;
import org.apache.jetspeed.util.PortletSessionState;
import org.apache.jetspeed.util.ServiceUtil;
import org.apache.turbine.services.rundata.RunDataService;
import org.apache.turbine.util.RunData;
import org.apache.velocity.context.Context;
import com.aimluck.eip.common.ALApplication;
import com.aimluck.eip.http.HttpServletRequestLocator;
import com.aimluck.eip.orm.query.ResultList;
import com.aimluck.eip.services.portal.ALPortalApplicationService;
import com.aimluck.eip.services.social.ALApplicationService;
import com.aimluck.eip.services.social.model.ALApplicationGetRequest;
import com.aimluck.eip.services.social.model.ALApplicationGetRequest.Status;
/**
* 伝言メモの一覧を処理するクラスです。
*
*/
public class CustomizeUtils {
public static final String UI_PORTLETS_SELECTED = "portletsSelected";
private static final String HIDE_EMPTY_CATEGORIES =
"customizer.hide.empty.categories";
public static final String FILTER_FIELDS = "filter_fields";
public static final String FILTER_VALUES = "filter_values";
public static final String REFERENCES_REMOVED = "references-removed";
/**
* Static initialization of the logger for this class
*/
private static final JetspeedLogger logger = JetspeedLogFactoryService
.getLogger(CustomizeUtils.class.getName());
public static boolean isEditable(RunData data, PortletEntry entry,
String mediaType) {
if (JetspeedSecurity.checkPermission(
(JetspeedUser) data.getUser(),
new PortalResource(entry),
JetspeedSecurity.PERMISSION_VIEW)
&& ((!entry.isHidden())
&& (!entry.getType().equals(PortletEntry.TYPE_ABSTRACT)) && entry
.hasMediaType(mediaType))
&& !entry.getSecurityRef().getParent().equals("admin-view")) {
return true;
}
return false;
}
// Create a list of all available portlets
@SuppressWarnings("unchecked")
public static List<PortletEntry> buildPortletList(RunData data,
String mediaType, List<PortletEntry> allPortlets) {
HttpServletRequest request = HttpServletRequestLocator.get();
List<PortletEntry> list = null;
if (request != null) {
try {
list = (List<PortletEntry>) request.getAttribute("portlets.list");
} catch (Throwable ignore) {
//
}
}
if (list != null) {
return list;
}
list = new ArrayList<PortletEntry>();
Iterator<?> i = Registry.get(Registry.PORTLET).listEntryNames();
while (i.hasNext()) {
PortletEntry entry =
(PortletEntry) Registry.getEntry(Registry.PORTLET, (String) i.next());
// Iterator medias;
// Make a master portlet list, we will eventually us this to build a
// category list
allPortlets.add(entry);
// MODIFIED: Selection now takes care of the specified mediatype!
if (JetspeedSecurity.checkPermission(
(JetspeedUser) data.getUser(),
new PortalResource(entry),
JetspeedSecurity.PERMISSION_VIEW)
&& ((!entry.isHidden())
&& (!entry.getType().equals(PortletEntry.TYPE_ABSTRACT)) && entry
.hasMediaType(mediaType))
&& ALPortalApplicationService.isActive(entry.getName())
&& isAdminUserView(entry, data)
&& !entry.getSecurityRef().getParent().equals("admin-view")) {
list.add(entry);
}
}
ResultList<ALApplication> resultList =
ALApplicationService.getList(new ALApplicationGetRequest()
.withStatus(ALApplicationGetRequest.Status.ACTIVE));
for (ALApplication app : resultList) {
BasePortletEntry entry = new BasePortletEntry();
entry.setTitle(app.getTitle().getValue());
entry.setDescription(app.getDescription().getValue());
entry.setName("GadgetsTemplate::" + app.getAppId().getValue());
entry.setParent("GadgetsTemplate");
entry.addParameter("aid", app.getAppId().getValue());
entry.addParameter("url", app.getUrl().getValue());
list.add(entry);
}
String[] filterFields =
(String[]) PortletSessionState.getAttribute(data, FILTER_FIELDS);
String[] filterValues =
(String[]) PortletSessionState.getAttribute(data, FILTER_VALUES);
list = PortletFilter.filterPortlets(list, filterFields, filterValues);
Collections.sort(list, new Comparator<PortletEntry>() {
@Override
public int compare(PortletEntry o1, PortletEntry o2) {
String t1 =
((o1).getTitle() != null) ? (o1).getTitle().toLowerCase() : (o1)
.getName()
.toLowerCase();
String t2 =
((o2).getTitle() != null) ? (o2).getTitle().toLowerCase() : (o2)
.getName()
.toLowerCase();
return t1.compareTo(t2);
}
});
// this is used only by maintainUserSelection - which does not need the
// portlet list to be regenrated
if (request != null) {
request.setAttribute("portlets.list", list);
}
return list;
}
// Create a list of all available portlets and all applications
@SuppressWarnings("unchecked")
public static List<PortletEntry> buildPortletListWithStatus(RunData data,
String mediaType, List<PortletEntry> allPortlets, Status status) {
HttpServletRequest request = HttpServletRequestLocator.get();
List<PortletEntry> list = null;
if (request != null) {
try {
list = (List<PortletEntry>) request.getAttribute("portlets.list");
} catch (Throwable ignore) {
//
}
}
if (list != null) {
return list;
}
list = new ArrayList<PortletEntry>();
Iterator<?> i = Registry.get(Registry.PORTLET).listEntryNames();
while (i.hasNext()) {
PortletEntry entry =
(PortletEntry) Registry.getEntry(Registry.PORTLET, (String) i.next());
entry.setType("active");
// Iterator medias;
// Make a master portlet list, we will eventually us this to build a
// category list
allPortlets.add(entry);
// MODIFIED: Selection now takes care of the specified mediatype!
if (JetspeedSecurity.checkPermission(
(JetspeedUser) data.getUser(),
new PortalResource(entry),
JetspeedSecurity.PERMISSION_VIEW)
&& ((!entry.isHidden())
&& (!entry.getType().equals(PortletEntry.TYPE_ABSTRACT)) && entry
.hasMediaType(mediaType))
&& ALPortalApplicationService.isActive(entry.getName())
&& isAdminUserView(entry, data)
&& !entry.getSecurityRef().getParent().equals("admin-view")
&& !status.equals(ALApplicationGetRequest.Status.INACTIVE)) {
list.add(entry);
}
}
ResultList<ALApplication> appList =
ALApplicationService.getList(new ALApplicationGetRequest()
.withStatus(status));
for (ALApplication app : appList) {
BasePortletEntry entry = new BasePortletEntry();
entry.setTitle(app.getTitle().getValue());
entry.setDescription(app.getDescription().getValue());
entry.setName("GadgetsTemplate::" + app.getAppId().getValue());
entry.setParent("GadgetsTemplate");
entry.setType((app.getStatus() == 1) ? "active" : "inactive");
list.add(entry);
}
String[] filterFields =
(String[]) PortletSessionState.getAttribute(data, FILTER_FIELDS);
String[] filterValues =
(String[]) PortletSessionState.getAttribute(data, FILTER_VALUES);
list = PortletFilter.filterPortlets(list, filterFields, filterValues);
Collections.sort(list, new Comparator<PortletEntry>() {
@Override
public int compare(PortletEntry o1, PortletEntry o2) {
String t1 =
((o1).getTitle() != null) ? (o1).getTitle().toLowerCase() : (o1)
.getName()
.toLowerCase();
String t2 =
((o2).getTitle() != null) ? (o2).getTitle().toLowerCase() : (o2)
.getName()
.toLowerCase();
return t1.compareTo(t2);
}
});
// this is used only by maintainUserSelection - which does not need the
// portlet list to be regenrated
if (request != null) {
request.setAttribute("portlets.list", list);
}
return list;
}
// Create a list of all portlets
@SuppressWarnings("unchecked")
public static List<PortletEntry> buildAllPortletList(RunData data,
String mediaType, List<PortletEntry> allPortlets) {
HttpServletRequest request = HttpServletRequestLocator.get();
List<PortletEntry> list = null;
if (request != null) {
try {
list = (List<PortletEntry>) request.getAttribute("portlets.list");
} catch (Throwable ignore) {
//
}
}
if (list != null) {
return list;
}
list = new ArrayList<PortletEntry>();
Iterator<?> i = Registry.get(Registry.PORTLET).listEntryNames();
while (i.hasNext()) {
PortletEntry entry =
(PortletEntry) Registry.getEntry(Registry.PORTLET, (String) i.next());
// Iterator medias;
// Make a master portlet list, we will eventually us this to build a
// category list
allPortlets.add(entry);
// MODIFIED: Selection now takes care of the specified mediatype!
if (JetspeedSecurity.checkPermission(
(JetspeedUser) data.getUser(),
new PortalResource(entry),
JetspeedSecurity.PERMISSION_VIEW)
&& ((!entry.getType().equals(PortletEntry.TYPE_ABSTRACT)) && entry
.hasMediaType(mediaType))
&& (entry.getSecurityRef() != null && !entry
.getSecurityRef()
.getParent()
.equals("admin-view"))) {
list.add(entry);
}
}
ResultList<ALApplication> resultList =
ALApplicationService.getList(new ALApplicationGetRequest()
.withStatus(ALApplicationGetRequest.Status.ACTIVE));
for (ALApplication app : resultList) {
BasePortletEntry entry = new BasePortletEntry();
entry.setTitle(app.getTitle().getValue());
entry.setDescription(app.getDescription().getValue());
entry.setName("GadgetsTemplate::" + app.getAppId().getValue());
entry.setParent("GadgetsTemplate");
entry.addParameter("aid", app.getAppId().getValue());
entry.addParameter("url", app.getUrl().getValue());
list.add(entry);
}
String[] filterFields =
(String[]) PortletSessionState.getAttribute(data, FILTER_FIELDS);
String[] filterValues =
(String[]) PortletSessionState.getAttribute(data, FILTER_VALUES);
list = PortletFilter.filterPortlets(list, filterFields, filterValues);
Collections.sort(list, new Comparator<PortletEntry>() {
@Override
public int compare(PortletEntry o1, PortletEntry o2) {
String t1 =
((o1).getTitle() != null) ? (o1).getTitle().toLowerCase() : (o1)
.getName()
.toLowerCase();
String t2 =
((o2).getTitle() != null) ? (o2).getTitle().toLowerCase() : (o2)
.getName()
.toLowerCase();
return t1.compareTo(t2);
}
});
// this is used only by maintainUserSelection - which does not need the
// portlet list to be regenrated
if (request != null) {
request.setAttribute("portlets.list", list);
}
return list;
}
@SuppressWarnings("unchecked")
public static Map<String, PortletEntry> getUserSelections(RunData data) {
HttpServletRequest request = HttpServletRequestLocator.get();
Map<String, PortletEntry> userSelections = null;
if (request != null) {
userSelections =
(Map<String, PortletEntry>) request.getAttribute("portlets.selections");
}
if (userSelections == null) {
userSelections = new HashMap<String, PortletEntry>();
}
if (request != null) {
request.setAttribute("portlets.selections", userSelections);
}
return userSelections;
}
public static List<PortletInfoEntry> buildInfoList(RunData data,
String regName, String mediaType) {
List<PortletInfoEntry> list = new ArrayList<PortletInfoEntry>();
Iterator<?> i = Registry.get(regName).listEntryNames();
while (i.hasNext()) {
PortletInfoEntry entry =
(PortletInfoEntry) Registry.getEntry(regName, (String) i.next());
// MODIFIED: Selection now takes care of the specified mediatype!
if (JetspeedSecurity.checkPermission(
(JetspeedUser) data.getUser(),
new PortalResource(entry),
JetspeedSecurity.PERMISSION_CUSTOMIZE)
&& ((!entry.isHidden()) && entry.hasMediaType(mediaType))) {
list.add(entry);
}
}
Collections.sort(list, new Comparator<RegistryEntry>() {
@Override
public int compare(RegistryEntry o1, RegistryEntry o2) {
String t1 =
((o1).getTitle() != null) ? (o1).getTitle() : (o1).getName();
String t2 =
((o2).getTitle() != null) ? (o2).getTitle() : (o2).getName();
return t1.compareTo(t2);
}
});
return list;
}
public static List<RegistryEntry> buildList(RunData data, String regName) {
List<RegistryEntry> list = new ArrayList<RegistryEntry>();
Iterator<?> i = Registry.get(regName).listEntryNames();
while (i.hasNext()) {
RegistryEntry entry = Registry.getEntry(regName, (String) i.next());
if (JetspeedSecurity.checkPermission(
(JetspeedUser) data.getUser(),
new PortalResource(entry),
JetspeedSecurity.PERMISSION_CUSTOMIZE)
&& (!entry.isHidden())) {
list.add(entry);
}
}
Collections.sort(list, new Comparator<RegistryEntry>() {
@Override
public int compare(RegistryEntry o1, RegistryEntry o2) {
String t1 =
((o1).getTitle() != null) ? (o1).getTitle() : (o1).getName();
String t2 =
((o2).getTitle() != null) ? (o2).getTitle() : (o2).getName();
return t1.compareTo(t2);
}
});
return list;
}
/**
* Builds a list of all portlet categories
*
* @param RunData
* current requests RunData object
* @param List
* portlets All available portlets
*/
public static List<BaseCategory> buildCategoryList(RunData data,
String mediaType, List<PortletEntry> portlets) {
boolean hideEmpties =
JetspeedResources.getBoolean(HIDE_EMPTY_CATEGORIES, true);
TreeMap<String, BaseCategory> catMap = new TreeMap<String, BaseCategory>();
Iterator<PortletEntry> pItr = portlets.iterator();
while (pItr.hasNext()) {
PortletEntry entry = pItr.next();
if (hideEmpties) {
if (JetspeedSecurity.checkPermission(
(JetspeedUser) data.getUser(),
new PortalResource(entry),
JetspeedSecurity.PERMISSION_VIEW)
&& ((!entry.isHidden())
&& (!entry.getType().equals(PortletEntry.TYPE_ABSTRACT)) && entry
.hasMediaType(mediaType))) {
Iterator<?> cItr = entry.listCategories();
while (cItr.hasNext()) {
BaseCategory cat = (BaseCategory) cItr.next();
catMap.put(cat.getName(), cat);
}
}
} else {
Iterator<?> cItr = entry.listCategories();
while (cItr.hasNext()) {
BaseCategory cat = (BaseCategory) cItr.next();
catMap.put(cat.getName(), cat);
}
}
}
// BaseCategory allCat = new BaseCategory();
// allCat.setName("All Portlets");
// catMap.put(allCat.getName(), allCat);
return new ArrayList<BaseCategory>(catMap.values());
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static List<?>[] buildColumns(Portlets set, int colNum) {
// normalize the constraints and calculate max num of rows needed
Iterator<?> iterator = set.getEntriesIterator();
int row = 0;
int col = 0;
int rowNum = 0;
while (iterator.hasNext()) {
IdentityElement identityElement = (IdentityElement) iterator.next();
Layout layout = identityElement.getLayout();
if (layout != null) {
for (int p = 0; p < layout.getParameterCount(); p++) {
Parameter prop = layout.getParameter(p);
try {
if (prop.getName().equals("row")) {
row = Integer.parseInt(prop.getValue());
if (row > rowNum) {
rowNum = row;
}
} else if (prop.getName().equals("column")) {
col = Integer.parseInt(prop.getValue());
if (col > colNum) {
prop.setValue(String.valueOf(col % colNum));
}
}
} catch (Exception e) {
// ignore any malformed layout properties
}
}
}
}
int sCount = set.getEntryCount() + set.getPortletsCount();
row = (sCount / colNum) + 1;
if (row > rowNum) {
rowNum = row;
}
if (logger.isDebugEnabled()) {
logger.debug("Controller customize colNum: "
+ colNum
+ " rowNum: "
+ rowNum);
}
// initialize the result position table and the work list
List[] table = new List[colNum];
List filler = Collections.nCopies(rowNum + 1, null);
for (int i = 0; i < colNum; i++) {
table[i] = new ArrayList();
table[i].addAll(filler);
}
List<IdentityElement> work = new ArrayList<IdentityElement>();
// position the constrained elements and keep a reference to the
// others
for (int i = 0; i < set.getEntryCount(); i++) {
addElement(set.getEntry(i), table, work, colNum);
}
// Add references
for (int i = 0; i < set.getReferenceCount(); i++) {
addElement(set.getReference(i), table, work, colNum);
}
// insert the unconstrained elements in the table
Iterator<IdentityElement> i = work.iterator();
for (row = 0; row < rowNum; row++) {
for (col = 0; i.hasNext() && (col < colNum); col++) {
if (table[col].get(row) == null) {
if (logger.isDebugEnabled()) {
logger.debug("Set portlet at col " + col + " row " + row);
}
table[col].set(row, i.next());
}
}
}
// now cleanup any remaining null elements
for (int j = 0; j < table.length; j++) {
if (logger.isDebugEnabled()) {
logger.debug("Column " + j);
}
i = table[j].iterator();
while (i.hasNext()) {
Object obj = i.next();
if (logger.isDebugEnabled()) {
logger.debug("Element " + obj);
}
if (obj == null) {
i.remove();
}
}
}
return table;
}
/**
* Add an element to the "table" or "work" objects. If the element is
* unconstrained, and the position is within the number of columns, then the
* element is added to "table". Othewise the element is added to "work"
*
* @param element
* to add
* @param table
* of positioned elements
* @param work
* list of un-positioned elements
* @param columnCount
* Number of colum
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
protected static void addElement(IdentityElement element, List[] table,
List<IdentityElement> work, int columnCount) {
Layout layout = element.getLayout();
int row = -1;
int col = -1;
if (layout != null) {
try {
for (int p = 0; p < layout.getParameterCount(); p++) {
Parameter prop = layout.getParameter(p);
if (prop.getName().equals("row")) {
row = Integer.parseInt(prop.getValue());
} else if (prop.getName().equals("column")) {
col = Integer.parseInt(prop.getValue());
}
}
} catch (Exception e) {
// ignore any malformed layout properties
}
}
if (logger.isDebugEnabled()) {
logger.debug("Constraints col " + col + " row " + row);
}
if ((row >= 0) && (col >= 0) && (col < columnCount)) {
table[col].add(row, element);
} else {
if (layout != null) {
// We got here because the column, as defined in the layout,
// is greater then the numner of columns. This usually
// happens when the number of column has been decreased.
// Delete the offending layout. It may be recreated with
// the correct values.
element.setLayout(null);
layout = null;
}
work.add(element);
}
}
/**
* 管理者ユーザーのみ表示可能アプリ
*
* @param entry
* @param data
* @return
*/
public static boolean isAdminUserView(PortletEntry entry, RunData data) {
if (data != null) {
JetspeedRunData jdata = (JetspeedRunData) data;
if (jdata.getUserId() != null
&& entry != null
&& entry.getSecurityRef() != null
&& entry.getSecurityRef().getParent() != null
&& entry.getSecurityRef().getParent().equals("admin-user-view")) {
return ALEipUtils.isAdmin(data) ? true : false;
}
}
return true;
}
/**
* 管理者ユーザーのみ表示可能アプリ
*
* @param entry
* @param data
* @return
*/
public static boolean isAdminUserView(String portletName, RunData data) {
PortletEntry entry = null;
try {
entry = (PortletEntry) Registry.getEntry(Registry.PORTLET, portletName);
} catch (Exception e) {
logger.error("CustomizeUtils.isAdminUserView", e);
}
return isAdminUserView(entry, data);
}
/**
* 管理者ユーザーのみ表示可能アプリ
*
* @param entry
* @param data
* @return
*/
public static boolean isAdminUserView(PortletEntry entry) {
JetspeedRunData jData = null;
try {
JetspeedRunDataService jrds =
(JetspeedRunDataService) ServiceUtil
.getServiceByName(RunDataService.SERVICE_NAME);
jData = jrds.getCurrentRunData();
} catch (Exception e) {
logger.error("CustomizeUtils.isAdminUserView", e);
}
return isAdminUserView(entry, jData);
}
public static List<?>[] buildCustomizeColumns(RunData rundata,
Context context, Portlets portlets) {
HttpServletRequest request = HttpServletRequestLocator.get();
List<?>[] columns = null;
if (request != null) {
columns = (List[]) request.getAttribute("customize-columns");
}
String controllerName = portlets.getController().getName();
int colNum = 2;
if (controllerName.startsWith("One")) {
colNum = 1;
} else if (controllerName.startsWith("Three")) {
colNum = 3;
}
Portlets set = portlets;
if (logger.isDebugEnabled()) {
logger.debug("MultiCol: columns "
+ Arrays.toString(columns)
+ " set "
+ set);
}
if ((columns != null) && (columns.length == colNum)) {
int eCount = 0;
for (int i = 0; i < columns.length; i++) {
eCount += columns[i].size();
}
if (logger.isDebugEnabled()) {
logger.debug("MultiCol: eCount "
+ eCount
+ " setCount"
+ set.getEntryCount()
+ set.getPortletsCount());
}
if (eCount != set.getEntryCount() + set.getPortletsCount()) {
if (logger.isDebugEnabled()) {
logger.debug("MultiCol: rebuilding columns ");
}
columns = CustomizeUtils.buildColumns(set, colNum);
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("MultiCol: rebuilding columns ");
}
columns = CustomizeUtils.buildColumns(set, colNum);
}
if (request != null) {
request.setAttribute("customize-columns", columns);
}
return columns;
}
public static Portlet getCustomizePortlet(RunData rundata, String peid) {
JetspeedRunData jdata = (JetspeedRunData) rundata;
Portlet found = null;
Stack<Portlet> sets = new Stack<Portlet>();
sets.push(jdata.getCustomizedProfile().getRootSet());
while ((found == null) && (sets.size() > 0)) {
PortletSet set = (PortletSet) sets.pop();
if (set.getID().equals(peid)) {
found = set;
} else {
Enumeration<?> en = set.getPortlets();
while ((found == null) && en.hasMoreElements()) {
Portlet p = (Portlet) en.nextElement();
// unstack the controls to find the real PortletSets
Portlet real = p;
while (real instanceof PortletControl) {
real = ((PortletControl) p).getPortlet();
}
if (real instanceof PortletSet) {
if (real.getID().equals(peid)) {
found = real;
} else {
// we'll explore this set afterwards
sets.push(real);
}
} else if (p.getID().equals(peid)) {
found = p;
}
}
}
}
return found;
}
}