Skip to content

Commit

Permalink
Partly fixing MID-1969 - fixed losing namespaces in some paths/qnames…
Browse files Browse the repository at this point in the history
…. (Work in progress.)

Changed QueryConvertor to include "preliminary parsing" mode in which most XNodes are parsed without actually constructing ObjectQuery. This is invoked when parsing the source file, to eliminate unparsed XNodes as much as possible.
Also, simplifying SearchFilterType by eliminating DOM version of the filter clause.
  • Loading branch information
mederly committed Jul 14, 2014
1 parent 80f22d1 commit 2a47e8a
Show file tree
Hide file tree
Showing 24 changed files with 463 additions and 438 deletions.
Expand Up @@ -44,6 +44,7 @@
import org.w3c.dom.Element;

import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;

/**
* @author lazyman
Expand Down Expand Up @@ -111,8 +112,9 @@ public T getValue() {
// Do the most stupid thing possible. Assume string value. And there will be no definition.
value = (T) ((Element)rawElement).getTextContent();
} else if (rawElement instanceof PrimitiveXNode){
try{
value = (T) ((PrimitiveXNode) rawElement).getParsedValue(DOMUtil.XSD_STRING);
try {
QName type = rawElement.getTypeQName() != null ? rawElement.getTypeQName() : DOMUtil.XSD_STRING;
value = (T) ((PrimitiveXNode) rawElement).getParsedValueWithoutRecording(type);
} catch (SchemaException ex){
throw new IllegalStateException("Cannot fetch value from raw element. " + ex.getMessage(), ex);
}
Expand Down
Expand Up @@ -98,10 +98,7 @@ private Element serializeInternal(RootXNode rootxnode) throws SchemaException {
}
XNode subnode = rootxnode.getSubnode();
if (subnode instanceof PrimitiveXNode){
serializePrimitiveElement((PrimitiveXNode)subnode, topElement, rootElementName);

// String val = ((PrimitiveXNode) subnode).getStringValue();
// topElement.setTextContent(val);
serializePrimitiveElementOrAttribute((PrimitiveXNode) subnode, topElement, rootElementName, false);
return DOMUtil.getFirstChildElement(topElement);
}
if (!(subnode instanceof MapXNode)) {
Expand Down Expand Up @@ -152,9 +149,9 @@ private void serializeSubnode(XNode xsubnode, Element parentElement, QName eleme
} else if (xsubnode instanceof PrimitiveXNode<?>) {
PrimitiveXNode<?> xprim = (PrimitiveXNode<?>)xsubnode;
if (xprim.isAttribute()) {
serializePrimitiveAttribute(xprim, parentElement, elementName);
serializePrimitiveElementOrAttribute(xprim, parentElement, elementName, true);
} else {
serializePrimitiveElement(xprim, parentElement, elementName);
serializePrimitiveElementOrAttribute(xprim, parentElement, elementName, false);
}
} else if (xsubnode instanceof ListXNode) {
ListXNode xlist = (ListXNode)xsubnode;
Expand All @@ -168,99 +165,111 @@ private void serializeSubnode(XNode xsubnode, Element parentElement, QName eleme
}
}

private <T> void serializePrimitiveAttribute(PrimitiveXNode<T> xprim, Element parentElement, QName attributeName) {
QName typeQName = xprim.getTypeQName();
if (typeQName == null){
//TODO FIXME temporary hack..what if the attribute does not have type specified? can we assume that it is sting?
//for now enought
// typeQName = DOMUtil.XSD_STRING;
// xprim.setTypeQName(typeQName);
String value = xprim.getStringValue();
parentElement.setAttribute(attributeName.getLocalPart(), value);
return;
}
if (typeQName.equals(DOMUtil.XSD_QNAME)) {
QName value = (QName) xprim.getValue();
try {
DOMUtil.setQNameAttribute(parentElement, attributeName.getLocalPart(), value);
} catch (DOMException e) {
throw new DOMException(e.code, e.getMessage() + "; setting attribute "+attributeName.getLocalPart()+" in element "+DOMUtil.getQName(parentElement)+" to QName value "+value);
}
} else {
String value = xprim.getFormattedValue();
parentElement.setAttribute(attributeName.getLocalPart(), value);
}
}

public Element serializeXPrimitiveToElement(PrimitiveXNode<?> xprim, QName elementName) throws SchemaException {
initialize();
Element parent = DOMUtil.createElement(doc, new QName("fake","fake"));
serializePrimitiveElement(xprim, parent, elementName);
serializePrimitiveElementOrAttribute(xprim, parent, elementName, false);
return DOMUtil.getFirstChildElement(parent);
}

private void serializePrimitiveElement(PrimitiveXNode<?> xprim, Element parentElement, QName elementName) throws SchemaException {
private void serializePrimitiveElementOrAttribute(PrimitiveXNode<?> xprim, Element parentElement, QName elementOrAttributeName, boolean asAttribute) throws SchemaException {
QName typeQName = xprim.getTypeQName();
if (typeQName == null) {

// if typeQName is not explicitly specified, we try to determine it from parsed value
// TODO it should be considered whether not to set typeQName when parsing the value!
if (typeQName == null && xprim.isParsed()) {
Object v = xprim.getValue();
if (v != null) {
typeQName = XsdTypeMapper.toXsdType(v.getClass());
}
}

if (typeQName == null) {
if (com.evolveum.midpoint.prism.PrismContext.isAllowSchemalessSerialization()) {
// We cannot correctly serialize without a type. But this is needed
// sometimes. So just default to string
String stringValue = xprim.getStringValue();
if (stringValue != null) {
Element element;
try {
element = createElement(elementName);
} catch (DOMException e) {
throw new DOMException(e.code, e.getMessage() + "; creating element "+elementName+" in element "+DOMUtil.getQName(parentElement));
}
parentElement.appendChild(element);
element.setTextContent(stringValue);
// there's an ugly thing here: if serializing values that are unparsed, and if they
//
if (asAttribute) {
parentElement.setAttribute(elementOrAttributeName.getLocalPart(), stringValue);
} else {
Element element;
try {
element = createElement(elementOrAttributeName);
} catch (DOMException e) {
throw new DOMException(e.code, e.getMessage() + "; creating element "+elementOrAttributeName+" in element "+DOMUtil.getQName(parentElement));
}
parentElement.appendChild(element);
element.setTextContent(stringValue);
}
}
return;
} else {
throw new IllegalStateException("No type for primitive element "+elementName+", cannot serialize (schemaless serialization is disabled)");
}
} else if (typeQName.equals(ItemPath.XSD_TYPE)) {
ItemPath itemPath = (ItemPath)xprim.getValue();
if (itemPath != null){
XPathHolder holder = new XPathHolder(itemPath);
Element element = holder.toElement(elementName, parentElement.getOwnerDocument());
parentElement.appendChild(element);
}
} else {
Element element;
try {
element = createElement(elementName);
} catch (DOMException e) {
throw new DOMException(e.code, e.getMessage() + "; creating element "+elementName+" in element "+DOMUtil.getQName(parentElement));
}
parentElement.appendChild(element);

//TODO: refactor after suporting types, qnames and other values without ns declared...
if (xprim.isExplicitTypeDeclaration()) {
if (StringUtils.isBlank(typeQName.getNamespaceURI())) {
typeQName = XsdTypeMapper.determineQNameWithNs(typeQName);
}
if (typeQName != null) {
DOMUtil.setXsiType(element, typeQName);
}
throw new IllegalStateException("No type for primitive element "+elementOrAttributeName+", cannot serialize (schemaless serialization is disabled)");
}

if (typeQName.equals(DOMUtil.XSD_QNAME)) {
QName value = (QName) xprim.getValue();
DOMUtil.setQNameValue(element, value);
} else {
String value;
// TODO eliminate this if at all possible ... we should not provide raw value here
// if (xprim.isParsed()) {
value = xprim.getGuessedFormattedValue();
// } else {
// value = xprim.getStringValue();
// }
element.setTextContent(value);
}
}

// typeName != null after this point

if (StringUtils.isBlank(typeQName.getNamespaceURI())) {
typeQName = XsdTypeMapper.determineQNameWithNs(typeQName);
}

Element element = null;

if (typeQName.equals(ItemPath.XSD_TYPE)) {
ItemPath itemPath = (ItemPath)xprim.getValue();
if (itemPath != null) {
if (asAttribute) {
throw new UnsupportedOperationException("Serializing ItemPath as an attribute is not supported yet");
}
XPathHolder holder = new XPathHolder(itemPath);
element = holder.toElement(elementOrAttributeName, parentElement.getOwnerDocument());
parentElement.appendChild(element);
}

} else {
// not an ItemType

if (!asAttribute) {
try {
element = createElement(elementOrAttributeName);
} catch (DOMException e) {
throw new DOMException(e.code, e.getMessage() + "; creating element "+elementOrAttributeName+" in element "+DOMUtil.getQName(parentElement));
}
parentElement.appendChild(element);
}

if (typeQName.equals(DOMUtil.XSD_QNAME)) {
QName value = (QName) xprim.getParsedValueWithoutRecording(typeQName);
if (asAttribute) {
try {
DOMUtil.setQNameAttribute(parentElement, elementOrAttributeName.getLocalPart(), value);
} catch (DOMException e) {
throw new DOMException(e.code, e.getMessage() + "; setting attribute "+elementOrAttributeName.getLocalPart()+" in element "+DOMUtil.getQName(parentElement)+" to QName value "+value);
}
} else {
DOMUtil.setQNameValue(element, value);
}
} else {
// not ItemType nor QName
String value = xprim.getGuessedFormattedValue();

if (asAttribute) {
parentElement.setAttribute(elementOrAttributeName.getLocalPart(), value);
} else {
element.setTextContent(value);
}
}

}
if (!asAttribute && xprim.isExplicitTypeDeclaration()) {
DOMUtil.setXsiType(element, typeQName);
}
}

private void serializeSchema(SchemaXNode xschema, Element parentElement) {
Element schemaElement = xschema.getSchemaElement();
if (schemaElement == null){
Expand Down
Expand Up @@ -430,15 +430,15 @@ private <T extends SearchFilterType> T unmarshalSearchFilterType(MapXNode xmap,
} catch (InstantiationException|IllegalAccessException e) {
throw new SystemException("Cannot instantiate " + beanClass + ": " + e.getMessage(), e);
}
filterType.parseFromXNode(xmap);
filterType.parseFromXNode(xmap, prismContext);
return filterType;
}

private MapXNode marshalSearchFilterType(SearchFilterType value) throws SchemaException {
if (value == null) {
return null;
}
return value.serializeToXNode(prismContext);
return value.serializeToXNode();
}

private Type getTypeArgument(Type origType, String desc) {
Expand Down

0 comments on commit 2a47e8a

Please sign in to comment.