final SAXEvent firstEvent = deferred.peek();
if(!(firstEvent instanceof StartElement)) {
throw new SAXException("Unbalanced SAX Events");
}
final StartElement start = ((StartElement)firstEvent);
if(start.namespaceURI == null || !start.namespaceURI.equals(Configuration.NS) || !start.localName.equals(principalType.getElementName())) {
throw new SAXException("First element does not match ending '" + principalType.getElementName() + "' element");
}
//if needed, update old style id to new style id
final AttributesImpl attrs = new AttributesImpl(migrateIdAttribute(start.attributes, principalType));
//check if there is a name collision, i.e. another principal with the same name
final SecurityManager sm = broker.getBrokerPool().getSecurityManager();
final String principalName = findName();
final Principal existingPrincipleByName = principalName != null ? principalType.getPrincipal(sm, principalName) : null;
final int newId;
if(existingPrincipleByName != null) {
//use id of existing principal which has the same name
newId = existingPrincipleByName.getId();
} else {
//check if there is an id collision, i.e. another principal with the same id
final Integer id = Integer.valueOf(attrs.getValue(ID_ATTR));
final Principal existingPrincipalById = principalType.getPrincipal(sm, id);
if(existingPrincipalById != null) {
//pre-allocate a new id, so as not to collide with the existing principal
if(isValidating()) {
try {
principalType.preAllocateId(sm, preAllocatedId);
} catch(final PermissionDeniedException | EXistException e) {
throw new SAXException("Unable to pre-allocate principle id for " + principalType.getElementName() + ": " + principalName, e);
}
}
newId = preAllocatedId.getId();
if(!isValidating()) {
preAllocatedId.clear();
}
} else {
newId = id; //use the provided id as it is currently unallocated
}
}
//update attributes of the principal in deferred
attrs.setValue(attrs.getIndex(ID_ATTR), String.valueOf(newId));
final StartElement prevPrincipalStart = (StartElement)deferred.poll();
deferred.addFirst(new StartElement(prevPrincipalStart.namespaceURI, prevPrincipalStart.localName, prevPrincipalStart.qname, attrs));
}