Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.viaoa.util.OAJaxb Maven / Gradle / Ivy
package com.viaoa.util;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Queue;
import java.util.Stack;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.bind.SchemaOutputResolver;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.Marshaller.Listener;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlID;
import javax.xml.namespace.QName;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.internal.identitymaps.QueueableWeakCacheKey;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.MOXySystemProperties;
import com.viaoa.annotation.OAProperty;
import com.viaoa.ds.OASelect;
import com.viaoa.hub.Hub;
import com.viaoa.object.OACascade;
import com.viaoa.object.OALinkInfo;
import com.viaoa.object.OAObject;
import com.viaoa.object.OAObjectCacheDelegate;
import com.viaoa.object.OAObjectInfo;
import com.viaoa.object.OAObjectInfoDelegate;
import com.viaoa.object.OAObjectKey;
import com.viaoa.object.OAObjectPropertyDelegate;
import com.viaoa.object.OAPropertyInfo;
import com.viaoa.object.OAThreadLocalDelegate;
/**
* Uses JAXB & Moxy to automate how OAObjects, and Hubs are converted to/from XML & Json.
* Java+OAobject+Hub <-> XML or JSON
*
* OAObject references have extra methods and annotations so that they work with JAXB.
*
* Allows for controlling which references are included. Designed to handle "deep" graphs without circular references.
*
* There are added methods and annotations to OAObject link properties for JAXB to work. These methods are named "*Jaxb*".
*
* One Links -
* 0: getEmployee will be annotated with @XmlTransient so that it is ignored by jaxb
* * only one of the following will be used when writing XML, others will return a null. All will be defined in xsd. Other systems will need to be able to use/process each.
* 1: getJaxbEmployee will return the xml for the full object, if shouldInclude=true and if the object is not already in the graph.
* 2: getJaxbRefEmployee - used only if the refence object has already been included, uses an @XmlIDREF.
* 3: getJaxbEmployeeId - used when the full object is not needed (shouldIncludeProperty=false, and it is not already in the graph.
*
* Many (Hub) Linkes -
* 0: getEmployees will be annotated with @XmlTransient so that it is ignored by jaxb
* 1: getJaxbEmployees will return a list of the stations that are not already in the graph.
* 2: getJaxbRefEmployees will return a list of the stations that are already in the graph.
* when the xml/json is unmarshelled, the Hub will have the combined objects.
*
* Example:
OAJaxb jaxb = new OAJaxb<>(Company.class);
jaxb.setUseReferences(false);
jaxb.setIncludeGuids(false);
jaxb.addPropertyPath(CompanyPP.clients().products().pp);
jaxb.addPropertyPath(CompanyPP.locations().buyers().pp);
jsonOutput = jaxb.convertToJSON(hub);
*
*
* @author vvia
*/
public class OAJaxb {
private OACascade cascade;
private JAXBContext context;
private Class clazz;
// each object in the tree
private Stack stackObject;
// stack of link objects from marshalling, that can be used to know the propertyPath
private Stack stackMarshalLinkInfo;
// keeps hsCurrent for objs in stack
private Stack> stackHashSet;
// keeps a list of refs for the current object hub properties
private Stack>> stackHmRefsOnly;
// list of link properties for the current object that have responded with SendRefType.object
// so that the other oaObj.getJaxb methods for the property will not be used.
private HashSet hsCurrentLinkObjectsSent;
// keeps track objects in a Hub that are already in the output (obj graph)
private HashMap> hmCurrentRefsOnly;
private boolean bIsMarshelling;
private boolean bUseReferences = true;
private static HashMap, JAXBContext> hmJAXBContext = new HashMap<>();
private ArrayList alPropertyPath = new ArrayList<>();
public OAJaxb(Class c) {
this.clazz = c;
}
public int getStackSize() {
if (stackObject == null) return 0;
return stackObject.size();
}
public void addPropertyPath(String pp) {
alPropertyPath.add(pp);
}
public void clearPropertyPaths() {
alPropertyPath.clear();
}
private boolean bIncludeGuids;
public boolean getIncludeGuids() {
return bIncludeGuids;
}
public void setIncludeGuids(boolean b) {
this.bIncludeGuids = b;
}
/**
* Flag to know if references are permitted (default: true). References are used when
* an object is already in graph, and the reference will point to this object.
* If set to false, then an object that is included more then once will be repeated, causing
* duplicates for the object.
*
* Note: if false and a circular reference is detected, then a referece will be used anyway to
* avoid exception.
*/
public boolean getUseReferences() {
return this.bUseReferences;
}
public void setUseReferences(boolean b) {
this.bUseReferences = b;
}
/**
* Get the context for this.clazz
*/
public JAXBContext getJAXBContext() throws Exception {
if (context == null) {
/* Note: we are currently following the jaxb spec, where Id/RefId are treated as String.
The JAXB spec says that XmlId must always be type string
MOXY allows it to be otherwise, by doing one of the following:
A: set system property at startup. Has to before MOXySystemProperties is initialized, since it will store at classload
System.setProperty(MOXySystemProperties.XML_ID_EXTENSION, "true");
B: add this annotation of Id property
@org.eclipse.persistence.oxm.annotations.XmlIDExtension
https://www.eclipse.org/eclipselink/api/2.7/org/eclipse/persistence/jaxb/MOXySystemProperties.html
https://stackoverflow.com/questions/29564627/does-moxy-support-non-string-xmlid-in-version-2-6-0
*/
context = hmJAXBContext.get(clazz);
if (context == null) {
// MOXY
HashMap hm = new HashMap<>();
// hm.put(MOXySystemProperties.XML_ID_EXTENSION, Boolean.TRUE); // ?????? dont think this is needed right now
// create using Moxy Factory
context = JAXBContextFactory.createContext(new Class[] {HubWrapper.class, clazz}, hm);
boolean bx = (context instanceof org.eclipse.persistence.jaxb.JAXBContext);
// default way for creating
// context = JAXBContext.newInstance(HubWrapper.class, clazz);
hmJAXBContext.put((Class) clazz, context);
}
}
return context;
}
protected void reset() {
cascade = new OACascade();
stackObject = new Stack<>();
stackHashSet = new Stack<>();
hsCurrentLinkObjectsSent = null;
stackHmRefsOnly = new Stack<>();
hmCurrentRefsOnly = null;
stackMarshalLinkInfo = new Stack();
}
public void createXsdFile(final String directoryName) throws Exception {
getJAXBContext().generateSchema(new SchemaOutputResolver() {
@Override
public Result createOutput(String namespaceURI, String suggestedFileName) throws IOException {
String dn;
if (OAString.isNotEmpty(directoryName)) dn = OAString.convertFileName(directoryName + "/");
else dn = "";
File file = new File(dn + suggestedFileName);
StreamResult result = new StreamResult(file);
result.setSystemId(file.toURI().toURL().toString());
return result;
}
});
}
public boolean isMarshelling() {
return bIsMarshelling;
}
public String convertToXML(TYPE obj) throws Exception {
String s = convert(obj, true);
return s;
}
public String convertToJSON(TYPE obj) throws Exception {
String s = convert(obj, false);
return s;
}
/**
* Convert OAObject to XML or JSON.
* @param bToXML if true then XML, else JSON
*/
public String convert(TYPE obj, boolean bToXML) throws Exception {
try {
reset();
OAThreadLocalDelegate.setOAJaxb(this);
bIsMarshelling = true;
return _convert(obj, bToXML);
}
finally {
bIsMarshelling = false;
OAThreadLocalDelegate.setOAJaxb(null);
}
}
protected String _convert(TYPE obj, boolean bToXML) throws Exception {
Marshaller marshaller = getJAXBContext().createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setListener(new OAJaxbListener());
if (!bToXML) {
// Output JSON - Based on Object Graph
marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
marshaller.setProperty(MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
}
StringWriter stringWriter = new StringWriter();
marshaller.marshal(obj, stringWriter);
String result = stringWriter.toString();
return result;
}
/*qqqqqqqqqqqqqqqqqq
public String testJackson(TYPE obj) throws Exception {
JacksonXmlModule xmlModule = new JacksonXmlModule();
xmlModule.setDefaultUseWrapper(false); // XmlElementWrapper is included in method annotations
ObjectMapper objectMapper = new XmlMapper(xmlModule);
objectMapper.registerModule(new JaxbAnnotationModule());
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
objectMapper.enable(MapperFeature.USE_WRAPPER_NAME_AS_PROPERTY_NAME); // did not allow inside name to be a duplicate
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
/ *
AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(objectMapper.getTypeFactory());
objectMapper.setAnnotationIntrospector(introspector);
* /
String xml = objectMapper.writeValueAsString(obj);
return xml;
}
*/
public String convertToXML(Hub hub, String rootName) throws Exception {
String s = convert(hub, rootName, true);
return s;
}
public String convertToJSON(Hub hub) throws Exception {
String s = convert(hub, null, false);
return s;
}
public String convert(Hub hub, String rootName, boolean bToXML) throws Exception {
try {
reset();
OAThreadLocalDelegate.setOAJaxb(this);
bIsMarshelling = true;
for (OAObject obj : hub) {
// put root objects in list of cascade so that inner references to them will be used
cascade.wasCascaded(obj, true);
}
return _convert(hub, rootName, bToXML);
}
finally {
bIsMarshelling = false;
OAThreadLocalDelegate.setOAJaxb(null);
}
}
protected String _convert(Hub hub, String rootName, boolean bToXML) throws Exception {
Object obj;
if (!bToXML || OAString.isEmpty(rootName)) {
obj = hub;
}
else {
HubWrapper wrapper = new HubWrapper(hub);
JAXBElement jaxbElement = new JAXBElement(new QName(rootName), HubWrapper.class, wrapper);
obj = jaxbElement;
}
Marshaller marshaller = getJAXBContext().createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setListener(new OAJaxbListener());
if (!bToXML) {
marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
marshaller.setProperty(MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
}
StringWriter stringWriter = new StringWriter();
marshaller.marshal(obj, stringWriter);
String result = stringWriter.toString();
return result;
}
public TYPE convertFromXML(String xml) throws Exception {
OAThreadLocalDelegate.setLoading(true);
OAThreadLocalDelegate.setOAJaxb(this);
try {
Unmarshaller unmarshaller = getJAXBContext().createUnmarshaller();
StringReader reader = new StringReader(xml);
TYPE objx = (TYPE) unmarshaller.unmarshal(reader);
return objx;
}
finally {
OAThreadLocalDelegate.setLoading(false);
OAThreadLocalDelegate.setOAJaxb(null);
}
}
public TYPE convertFromJSON(String json) throws Exception {
OAThreadLocalDelegate.setLoading(true); ///qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq not always loading qqqqqqqqqqqqqqq
OAThreadLocalDelegate.setOAJaxb(this);
try {
Unmarshaller unmarshaller = getJAXBContext().createUnmarshaller();
unmarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
unmarshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
unmarshaller.setProperty(MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
StringReader reader = new StringReader(json);
TYPE objx = (TYPE) unmarshaller.unmarshal(reader);
return objx;
}
finally {
OAThreadLocalDelegate.setLoading(false);
OAThreadLocalDelegate.setOAJaxb(null);
}
}
public Hub convertHubFromXML(String xml) throws Exception {
OAThreadLocalDelegate.setLoading(true);
OAThreadLocalDelegate.setOAJaxb(this);
try {
Unmarshaller unmarshaller = getJAXBContext().createUnmarshaller();
StreamSource streamSource = new StreamSource(new StringReader(xml));
//qqqqqq need to setLoading
/*was
JAXBElement hubWrapper = unmarshaller.unmarshal(streamSource, HubWrapper.class);
*/
//qqqqqqqqqqqqqqqqqq get code from convertHubFromJSON ... call preload
//qqqqqqqqqqqqqq test this with XML
JAXBElement ele = unmarshaller.unmarshal(streamSource, clazz);
List lst = (List) ele.getValue();
Hub hub = new Hub(clazz);
for (Object obj : lst) {
hub.add((TYPE) obj);
}
return hub;
}
finally {
OAThreadLocalDelegate.setLoading(false);
OAThreadLocalDelegate.setOAJaxb(null);
}
}
public Hub convertHubFromJSON(String xml) throws Exception {
//qqqqqqqqq this needs to be an option, since POST will need to not use isLoading==true
//qqq OAThreadLocalDelegate.setLoading(true);
OAThreadLocalDelegate.setOAJaxb(this);
try {
Unmarshaller unmarshaller = getJAXBContext().createUnmarshaller();
unmarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
unmarshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
unmarshaller.setProperty(MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
StreamSource streamSource = new StreamSource(new StringReader(xml));
//qqqqqqqqqqq needs to check for boundaries on what's allowed to be changed qqqqqqq
preload(xml); //qqqqqqqqqqqqqqqqqq
JAXBElement ele = unmarshaller.unmarshal(streamSource, clazz);
// JAXBElement hubWrapper = unmarshaller.unmarshal(streamSource, HubWrapper.class);
List lst = (List) ele.getValue();
Hub hub = new Hub(clazz);
for (Object obj : lst) {
hub.add((TYPE) obj);
}
return hub;
}
finally {
//qqqq OAThreadLocalDelegate.setLoading(false);
OAThreadLocalDelegate.setOAJaxb(null);
}
}
// create nodes using preprocessor
private static class Node {
OALinkInfo li;
String pp = "";
Class clazz;
Object id;
OAPropertyInfo piId;
public Node(Class c) {
this.clazz = c;
}
}
//qqqqqqqqqqqqq need to create a warning listener qqqqqqqqqqq otherwise it's silent
/** used from preload data, by static oaObject.jaxbCreate(), to get the next oaObject */
public OAObject getNextUnmarshalObject(Class clazz) {
if (clazz == null) return null;
if (queuePreloadNode == null || queuePreloadNode.isEmpty()) return null;
Node node = queuePreloadNode.peek();
if (!node.clazz.equals(clazz)) return null;
queuePreloadNode.remove();
Object id = node.id;
if (id == null) return null;
OAObjectKey objKey = new OAObjectKey(id);
Object ref = OAObjectCacheDelegate.get(clazz, objKey);
if (ref instanceof OAObject) {
return (OAObject) ref;
}
OASelect sel = new OASelect(clazz);
sel.select(node.piId.getName() + " = ?", new Object[] {id} );
ref = sel.next();
if (ref instanceof OAObject) {
return (OAObject) ref;
}
return null;
}
// used by preload to know the order of objects that will be needed.
private Queue queuePreloadNode;
/**
* Need to find all of the Object IDs, so that jaxb createObject can then find the
* correct oaObj to update.
*/
protected void preload(final String sz) {
final JsonParser parser = Json.createParser(new StringReader(sz));
final Stack stack = new Stack();
Class clazz = this.clazz;
Node node = new Node(clazz);
stack.push(node);
queuePreloadNode = new ArrayDeque<>();
queuePreloadNode.add(node);
String key = null;
String value = null;
while (parser.hasNext()) {
final Event event = parser.next();
if (event == Event.START_OBJECT) {
if (key != null) {
// find next clazz
OAObjectInfo oi = OAObjectInfoDelegate.getOAObjectInfo(clazz);
OALinkInfo li = oi.getLinkInfo(key);
if (li != null) {
clazz = li.getToClass();
Node prev = node;
node = new Node(clazz);
node.li = li;
if (OAString.isNotEmpty(prev.pp)) node.pp = prev.pp + ".";
node.pp += li.getName();
stack.push(node);
queuePreloadNode.add(node);
}
}
}
else if (event == Event.END_OBJECT) {
node = stack.pop();
key = null;
if (stack.isEmpty()) {
clazz = this.clazz;
node = new Node(clazz);
stack.push(node);
queuePreloadNode.add(node);
}
else {
node = stack.peek();
clazz = node.clazz;
}
}
else if (event == Event.KEY_NAME) {
key = parser.getString();
}
else if (event == Event.VALUE_STRING || event == Event.VALUE_NUMBER) {
value = parser.getString();
OAObjectInfo oi = OAObjectInfoDelegate.getOAObjectInfo(clazz);
OAPropertyInfo pi = oi.getPropertyInfo(key);
if (pi != null && pi.getId()) {
value = parser.getString();
node = stack.peek();
Object objx = OAConv.convert(pi.getClassType(), value);
node.id = objx;
node.piId = pi;
}
}
}
parser.close();
}
public String getCurrentMarshalPropertyPath() {
String pp = "";
if (stackMarshalLinkInfo != null) {
OALinkInfo liPrev = null;
for (OALinkInfo li : stackMarshalLinkInfo) {
if (li == liPrev) continue; // recursive
if (pp.length() > 0) pp += ".";
pp += li.getName();
liPrev = li;
}
}
return pp;
}
private OAObject lastGetSendRefObject;
private String lastGetSendRefPropertyName;
//qqqqqqqqqqqq
// options: send first level, send owned
public boolean isInStack(OAObject obj) {
if (stackObject == null) return false;
for (Object objx : stackObject) {
if (obj == objx) return true;
}
return false;
}
/**
* Used by OAObject when serializing
*/
public SendRefType getSendRefType(final OAObject objThis, final String propertyName) {
lastGetSendRefObject = objThis;
lastGetSendRefPropertyName = propertyName;
boolean bIsNeeded = true;
boolean bMatchedPP = false;
if (alPropertyPath.size() > 0) {
bIsNeeded = false;
String ppCurrent = getCurrentMarshalPropertyPath();
ppCurrent = OAString.concat(ppCurrent, propertyName, ".").toLowerCase();
boolean bFound = false;
for (String pp : alPropertyPath) {
if (pp.toLowerCase().indexOf(ppCurrent) == 0) {
bIsNeeded = true;
bMatchedPP = true;
break;
}
}
}
final OAObjectInfo oi = OAObjectInfoDelegate.getOAObjectInfo(objThis);
final OALinkInfo li = oi.getLinkInfo(propertyName);
if (li == null) return SendRefType.notNeeded;
Object objx = OAObjectPropertyDelegate.getProperty(objThis, propertyName, true, true);
if (!bIsNeeded && !shouldIncludeProperty(objThis, propertyName, false)) {
if (li.getType() == li.MANY) {
// if (objx instanceof Hub && ((Hub) objx).size() == 0) return SendRefType.object;
return SendRefType.notNeeded;
}
else {
if (objx instanceof OANotExist || objx == null) {
return SendRefType.object; // send null
}
if (bUseReferences) {
if (cascade.wasCascaded((OAObject) objx, false)) {
if (hsCurrentLinkObjectsSent != null && hsCurrentLinkObjectsSent.contains(propertyName.toUpperCase())) {
return SendRefType.notNeeded;
}
return SendRefType.ref;
}
}
return SendRefType.id;
}
}
if (objx instanceof OANotExist) {
if (li.getType() == li.ONE) {
return SendRefType.object; // send null
}
else {
return SendRefType.object; // send hub
}
}
if (objx instanceof OAObjectKey) {
objx = li.getValue(objThis);
}
if (objx instanceof OAObject) {
if (!bUseReferences) {
if (!isInStack((OAObject) objx)) {
if (shouldIncludeProperty(objThis, propertyName, true)) {
if (hsCurrentLinkObjectsSent == null) hsCurrentLinkObjectsSent = new HashSet<>();
hsCurrentLinkObjectsSent.add(propertyName.toUpperCase());
return SendRefType.object;
}
return SendRefType.id;
}
}
if (cascade != null) {
if (cascade.wasCascaded((OAObject) objx, false)) {
if (hsCurrentLinkObjectsSent != null && hsCurrentLinkObjectsSent.contains(propertyName.toUpperCase())) {
return SendRefType.notNeeded;
}
return SendRefType.ref;
}
}
if (shouldIncludeProperty(objThis, propertyName, true)) {
if (hsCurrentLinkObjectsSent == null) hsCurrentLinkObjectsSent = new HashSet<>();
hsCurrentLinkObjectsSent.add(propertyName.toUpperCase());
return SendRefType.object;
}
}
if (hsCurrentLinkObjectsSent != null && hsCurrentLinkObjectsSent.contains(propertyName.toUpperCase())) {
return SendRefType.notNeeded;
}
if (objx == null) return SendRefType.notNeeded;
return SendRefType.id;
}
/**
* Used by OAObject when serializing
*/
public boolean isAlreadyIncluded(OAObject obj) {
if (cascade != null) {
if (cascade.wasCascaded(obj, false)) {
return true;
}
}
return false;
}
/**
* Internally used by OAObject jaxb methods to keep track of a hub property refs that need to be sent, from method getJaxbRef[Name]s
*/
public ArrayList getRefsOnlyList(String prop) {
if (prop == null) return null;
if (hmCurrentRefsOnly == null) return null;
ArrayList list = hmCurrentRefsOnly.get(prop.toUpperCase());
return list;
}
public void setRefsOnlyList(String prop, ArrayList list) {
if (prop == null || list == null) return;
if (hmCurrentRefsOnly == null) hmCurrentRefsOnly = new HashMap<>();
hmCurrentRefsOnly.put(prop.toUpperCase(), list);
}
/**
* call back used to determine is an object reference should be included. If false (default) then only the Id is included.
* @param objThis
* @param propertyName
* @return
*/
public boolean shouldIncludeProperty(final OAObject objThis, final String propertyName, final boolean bDefaultValue) {
return bDefaultValue;
}
class OAJaxbListener extends Listener {
private final HashSet hsDummy = new HashSet<>();
private final HashMap> hmDummy = new HashMap<>();
@Override
public void beforeMarshal(Object source) {
stackObject.push(source);
if (lastGetSendRefObject != null && source instanceof OAObject) {
OAObjectInfo oi = OAObjectInfoDelegate.getOAObjectInfo(lastGetSendRefObject);
OALinkInfo li = oi.getLinkInfo(lastGetSendRefPropertyName);
if (li != null) {
stackMarshalLinkInfo.push(li);
}
}
stackHashSet.push(hsCurrentLinkObjectsSent != null ? hsCurrentLinkObjectsSent : hsDummy);
hsCurrentLinkObjectsSent = null;
stackHmRefsOnly.push(hmCurrentRefsOnly != null ? hmCurrentRefsOnly : hmDummy);
hmCurrentRefsOnly = null;
if (source instanceof OAObject) {
cascade.wasCascaded((OAObject) source, true);
}
else if (source instanceof Hub) {
cascade.wasCascaded((Hub) source, true);
}
}
@Override
public void afterMarshal(Object source) {
if (stackMarshalLinkInfo.isEmpty()) {
lastGetSendRefObject = null;
lastGetSendRefPropertyName = null;
}
else {
stackMarshalLinkInfo.pop();
}
stackObject.pop();
hsCurrentLinkObjectsSent = stackHashSet.pop();
if (hsCurrentLinkObjectsSent == hsDummy) hsCurrentLinkObjectsSent = null;
hmCurrentRefsOnly = stackHmRefsOnly.pop();
if (hmCurrentRefsOnly == hmDummy) hmCurrentRefsOnly = null;
}
}
public enum SendRefType {
notNeeded, object, ref, id;
}
public void setValidateSchema(String fname) {
/*qqqqq todo:
SchemaFactory sf = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI );
Schema schema = sf.newSchema(new File("schema1.xsd"));
m.setSchema(schema);
*/
}
public boolean willBeIncludedLater(OAObject oaObj) {
if (oaObj == null) return false;
if (cascade.wasCascaded(oaObj, false)) return false; // already included
OAObjectInfo oi = OAObjectInfoDelegate.getOAObjectInfo(oaObj);
OALinkInfo li = oi.getOwnedByOne();
if (li == null) {
return false;
}
Object objx = OAObjectPropertyDelegate.getProperty(oaObj, li.getName(), false, true);
if (objx == null) return false;
if (!(objx instanceof OAObject)) return false;
if (cascade.wasCascaded((OAObject) objx, false)) return false;
// parent has not yet been written
// now need to find if a parent is already include
if (isAnyOwnerAlreadyIncluded((OAObject) objx)) return true;
return false;
}
private boolean isAnyOwnerAlreadyIncluded(OAObject oaObj) {
if (oaObj == null) return false;
OAObjectInfo oi = OAObjectInfoDelegate.getOAObjectInfo(oaObj);
OALinkInfo li = oi.getOwnedByOne();
if (li == null) return false;
Object objx = OAObjectPropertyDelegate.getProperty(oaObj, li.getName(), false, true);
if (objx == null) return false;
if (cascade.wasCascaded((OAObject)objx, false)) return true;
return isAnyOwnerAlreadyIncluded((OAObject)objx);
}
//qqqqqqqqqqqqqqqqqqqqqqqq TEST with XML data ......qqqqqqqqqqqq it might need to HubWrapper qqqqqqqqqqqqqqqqqqqqq
}
/**
* Wraps a Hub so that it can be used as a root element.
*/
class HubWrapper {
private List list;
public HubWrapper() {
}
public HubWrapper(List lst) {
this.list = lst;
}
@XmlAnyElement(lax=true)
public List getList() {
if (list == null) list = new ArrayList();
return list;
}
}