package com.evolveum.midpoint.repo.sql;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.repo.sql.type.XMLGregorianCalendarType;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;
import org.apache.commons.lang.StringUtils;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.testng.annotations.Test;
import javax.xml.namespace.QName;
import java.io.*;
import java.util.*;
/**
* @author lazyman
*/
@ContextConfiguration(locations = {"../../../../../ctx-test.xml"})
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class PerformanceTest extends BaseSQLRepoTest {
private static final Trace LOGGER = TraceManager.getTrace(PerformanceTest.class);
private static final String[] GIVEN_NAMES = {"James", "Josephine", "Art", "Lenna", "Donette", "Simona", "Mitsue",
"Leota", "Sage", "Kris", "Minna", "Abel", "Kiley", "Graciela", "Cammy", "Mattie", "Meaghan", "Gladys", "Yuki",
"Fletcher", "Bette", "Veronika", "Willard", "Maryann", "Alisha", "Allene", "Chanel", "Ezekiel", "Willow",
"Bernardo", "Ammie", "Francine", "Ernie", "Albina", "Alishia", "Solange", "Jose", "Rozella", "Valentine",
"Kati", "Youlanda", "Dyan", "Roxane", "Lavera", "Erick", "Fatima", "Jina", "Kanisha", "Emerson"};
private static final String[] FAMILY_NAMES = {"Butt", "Darakjy", "Venere", "Paprocki", "Foller", "Morasca", "Tollner",
"Dilliard", "Wieser", "Marrier", "Amigon", "Maclead", "Caldarera", "Ruta", "Albares", "Poquette", "Garufi",
"Rim", "Whobrey", "Flosi", "Nicka", "Inouye", "Kolmetz", "Royster", "Slusarski", "Iturbide", "Caudy", "Chui",
"Kusko", "Figeroa", "Corrio", "Vocelka", "Stenseth", "Glick", "Sergi", "Shinko", "Stockham", "Ostrosky",
"Gillian", "Rulapaugh", "Schemmer", "Oldroyd", "Campain", "Perin", "Ferencz", "Saylors", "Briddick",
"Waycott", "Bowley", "Malet", "Bolognia", "Nestle", "Uyetake", "Mastella", "Klonowski", "Wenner", "Monarrez",
"Seewald", "Ahle", "Juhas", "Pugh", "Vanausdal", "Hollack", "Lindall", "Yglesias", "Buvens", "Weight",
"Morocco", "Eroman"};
private static final int ORG_COUNT = 10;
private static final int USER_PER_ORG_COUNT = 10000;
private static final int RESOURCE_COUNT = 5;
@Test(enabled = false)
public void test100Parsing() throws Exception {
long time = System.currentTimeMillis();
int COUNT = 1000;
for (int i = 0; i < COUNT; i++) {
List<PrismObject<? extends Objectable>> elements = prismContext.parserFor(new File(FOLDER_BASIC, "objects.xml")).parseObjects();
for (PrismObject obj : elements) {
prismContext.serializeObjectToString(obj, PrismContext.LANG_XML);
}
}
LOGGER.info("xxx>> time: {}", (System.currentTimeMillis() - time));
}
@Test(enabled = false)
public void test200PrepareBigXml() throws Exception {
File file = new File("./target/big-test.xml");
Writer writer = new OutputStreamWriter(new FileOutputStream(file), "utf-8");
try {
writeHeader(writer);
OrgType root = createOrgType("University", "University org. structure", "UROOT", "Bratislava", null);
root.getOrgType().add("functional");
final String OID_ORG_ROOT = root.getOid();
writeObject(root, writer);
final List<String> RESOURCE_OIDS = new ArrayList<>();
for (int i = 1; i <= RESOURCE_COUNT; i++) {
ResourceType resource = createResource(i);
RESOURCE_OIDS.add(resource.getOid());
writeObject(resource, writer);
}
for (int i = 1; i <= ORG_COUNT; i++) {
OrgType org = createOrgType("Unit " + i, "University unit " + i, "U00" + i, null, OID_ORG_ROOT);
writeObject(org, writer);
String orgOID = org.getOid();
for (int j = 1; j <= USER_PER_ORG_COUNT; j++) {
UserType user = createUserType((i - 1) * USER_PER_ORG_COUNT + j, orgOID);
for (int k = 1; k <= RESOURCE_OIDS.size(); k++) {
ShadowType shadow = createShadow(user, RESOURCE_OIDS.get(k - 1), k);
writeObject(shadow, writer);
user.getLinkRef().add(createRef(shadow.getOid(), ShadowType.COMPLEX_TYPE));
}
writeObject(user, writer);
}
}
writeFooter(writer);
} finally {
writer.close();
}
}
private ResourceType createResource(int resourceId) throws SchemaException, IOException {
PrismObject<ResourceType> prism = prismContext.parseObject(new File(FOLDER_BASIC, "resource-opendj.xml"));
ResourceType resource = new ResourceType();
resource.setupContainer(prism);
resource.setName(createPoly("Resource " + resourceId));
resource.setOid(UUID.randomUUID().toString());
return resource;
}
private ShadowType createShadow(UserType user, String resourceOid, int resourceId) throws SchemaException {
ShadowType shadow = new ShadowType();
shadow.setOid(UUID.randomUUID().toString());
final String DN = "cn=" + user.getName().getOrig() + ",ou=resource" + resourceId + ",dc=example,dc=com";
shadow.setName(createPoly(DN));
shadow.setResourceRef(createRef(resourceOid, ResourceType.COMPLEX_TYPE));
shadow.setKind(ShadowKindType.ACCOUNT);
shadow.setIntent("standardAccount");
shadow.setObjectClass(new QName("http://midpoint.evolveum.com/xml/ns/public/resource/instance/" + resourceOid,
"AccountObjectClass"));
PrismObject<ShadowType> prism = shadow.asPrismObject();
prismContext.adopt(prism);
PrismContainer attributes = prism.findOrCreateContainer(ShadowType.F_ATTRIBUTES);
PrismProperty property = attributes.findOrCreateProperty(SchemaConstants.ICFS_UID);
property.setRealValue(UUID.randomUUID().toString());
property = attributes.findOrCreateProperty(SchemaConstants.ICFS_NAME);
property.setRealValue(DN);
return shadow;
}
private String createUserName(String given, String family, int userId) {
StringBuilder sb = new StringBuilder();
sb.append(given.toLowerCase().charAt(0));
sb.append(family.toLowerCase().charAt(0));
sb.append(StringUtils.leftPad(Integer.toString(userId), 8, "0"));
return sb.toString();
}
private UserType createUserType(int userId, String orgOid) throws SchemaException {
String given = GIVEN_NAMES[new Random().nextInt(GIVEN_NAMES.length)];
String family = FAMILY_NAMES[new Random().nextInt(FAMILY_NAMES.length)];
UserType user = new UserType();
user.setName(createPoly(createUserName(given, family, userId)));
user.setGivenName(createPoly(given));
user.setFamilyName(createPoly(family));
user.setFullName(createPoly(given + " " + family));
user.setEmployeeNumber(Integer.toString(userId));
user.getParentOrgRef().add(createRef(orgOid, OrgType.COMPLEX_TYPE));
PrismObject<UserType> prism = user.asPrismObject();
prismContext.adopt(prism);
final String NS_P = "http://example.com/p";
PrismProperty property = prism.findOrCreateProperty(
new ItemPath(ObjectType.F_EXTENSION, new QName(NS_P, "weapon")));
property.setRealValue("Ak-47-" + new Random().nextInt(10));
property = prism.findOrCreateProperty(
new ItemPath(ObjectType.F_EXTENSION, new QName(NS_P, "shipName")));
property.setRealValue("smallBoat-" + new Random().nextInt(10));
property = prism.findOrCreateProperty(
new ItemPath(ObjectType.F_EXTENSION, new QName(NS_P, "loot")));
property.setRealValue(new Random().nextInt(10000));
property = prism.findOrCreateProperty(
new ItemPath(ObjectType.F_EXTENSION, new QName(NS_P, "funeralDate")));
property.setRealValue(XMLGregorianCalendarType.asXMLGregorianCalendar(new Date()));
return user;
}
private OrgType createOrgType(String name, String description, String identifier, String locality,
String parentRefOid) {
OrgType org = new OrgType();
org.setOid(UUID.randomUUID().toString());
org.setName(createPoly(name));
org.setDescription(description);
org.setIdentifier(identifier);
org.setLocality(createPoly(locality));
if (StringUtils.isNotEmpty(parentRefOid)) {
ObjectReferenceType ref = createRef(parentRefOid, OrgType.COMPLEX_TYPE);
org.getParentOrgRef().add(ref);
}
return org;
}
private ObjectReferenceType createRef(String oid, QName type) {
ObjectReferenceType ref = new ObjectReferenceType();
ref.setOid(oid);
ref.setType(type);
return ref;
}
private PolyStringType createPoly(String orig) {
PolyStringType poly = new PolyStringType();
poly.setOrig(orig);
return poly;
}
private void writeObject(ObjectType obj, Writer writer) throws IOException, SchemaException {
PrismObject prism = obj.asPrismObject();
prismContext.adopt(prism);
writer.write(prismContext.serializeObjectToString(prism, PrismContext.LANG_XML));
writer.write('\n');
}
private void writeHeader(Writer writer) throws IOException {
writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");
writer.write("<objects xmlns=\"http://midpoint.evolveum.com/xml/ns/public/common/common-3\">\n");
}
private void writeFooter(Writer writer) throws IOException {
writer.write("</objects>");
}
}