package com.evolveum.prism.xml.ns._public.query_3; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InvalidClassException; import java.io.NotSerializableException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OptionalDataException; import java.io.Serializable; import java.io.StreamCorruptedException; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.math.BigDecimal; import java.math.BigInteger; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.Calendar; import java.util.Currency; import java.util.Date; import java.util.Locale; import java.util.TimeZone; import java.util.UUID; import java.util.Map.Entry; import javax.activation.MimeType; import javax.activation.MimeTypeParseException; import javax.xml.bind.JAXBElement; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; import javax.xml.datatype.Duration; import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; import com.evolveum.midpoint.prism.PrismConstants; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.lex.dom.DomLexicalProcessor; import com.evolveum.midpoint.prism.marshaller.QueryConvertor; import com.evolveum.midpoint.prism.util.PrismUtil; import com.evolveum.midpoint.prism.xnode.MapXNode; import com.evolveum.midpoint.prism.xnode.PrimitiveXNode; import com.evolveum.midpoint.prism.xnode.RootXNode; import com.evolveum.midpoint.prism.xnode.XNode; import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.util.DebugDumpable; import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.xml.DomAwareEqualsStrategy; import com.evolveum.midpoint.util.xml.DomAwareHashCodeStrategy; import org.apache.commons.lang.builder.ToStringBuilder; import org.jetbrains.annotations.NotNull; import org.jvnet.jaxb2_commons.lang.Equals; import org.jvnet.jaxb2_commons.lang.EqualsStrategy; import org.jvnet.jaxb2_commons.lang.HashCode; import org.jvnet.jaxb2_commons.lang.HashCodeStrategy; import org.jvnet.jaxb2_commons.locator.ObjectLocator; import org.jvnet.jaxb2_commons.locator.util.LocatorUtils; import org.w3c.dom.Element; @XmlAccessorType(XmlAccessType.NONE) // we select getters/fields to expose via JAXB individually @XmlType(name = "SearchFilterType", propOrder = { // no prop order, because we serialize this class manually // BTW, the order is the following: description, filterClause }) public class SearchFilterType implements Serializable, Cloneable, Equals, HashCode, DebugDumpable { private final static long serialVersionUID = 201303040000L; @XmlElement protected String description; // this one is not exposed via JAXB protected MapXNode filterClauseXNode; // single-subnode map node (key = filter element qname, value = contents) public final static QName COMPLEX_TYPE = new QName(PrismConstants.NS_QUERY, "SearchFilterType"); public static final QName F_DESCRIPTION = new QName(PrismConstants.NS_QUERY, "description"); /** * Creates a new {@code QueryType} instance. * */ public SearchFilterType() { // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000 super(); } /** * Creates a new {@code QueryType} instance by deeply copying a given {@code QueryType} instance. * * * @param o * The instance to copy. * @throws NullPointerException * if {@code o} is {@code null}. */ public SearchFilterType(final SearchFilterType o) { // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000 super(); if (o == null) { throw new NullPointerException("Cannot create a copy of 'SearchFilterType' from 'null'."); } this.filterClauseXNode = (MapXNode) o.filterClauseXNode.clone(); } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public boolean containsFilterClause() { return filterClauseXNode != null && !filterClauseXNode.isEmpty(); } public void setFilterClauseXNode(MapXNode filterClauseXNode) { this.filterClauseXNode = filterClauseXNode; } public void setFilterClauseXNode(RootXNode filterClauseNode) { if (filterClauseNode == null) { this.filterClauseXNode = null; } else { this.filterClauseXNode = new MapXNode(); this.filterClauseXNode.put(filterClauseNode.getRootElementName(), filterClauseNode.getSubnode()); } } @Deprecated // use the version without prismContext instead public MapXNode getFilterClauseXNode(PrismContext prismContext) throws SchemaException { return getFilterClauseXNode(); } public MapXNode getFilterClauseXNode() { if (this.filterClauseXNode == null) { return null; } else { return (MapXNode) this.filterClauseXNode.clone(); } } public RootXNode getFilterClauseAsRootXNode() throws SchemaException { MapXNode clause = getFilterClauseXNode(); if (clause == null) { return null; } Entry<QName, XNode> singleEntry = clause.getSingleSubEntry("getFilterClauseAsRootXNode"); if (singleEntry == null) { return null; } return new RootXNode(singleEntry.getKey(), singleEntry.getValue()); } public Element getFilterClauseAsElement(@NotNull PrismContext prismContext) throws SchemaException { if (filterClauseXNode == null) { return null; } DomLexicalProcessor domParser = PrismUtil.getDomParser(prismContext); return domParser.serializeSingleElementMapToElement(filterClauseXNode); } public static SearchFilterType createFromXNode(XNode xnode, PrismContext prismContext) throws SchemaException { SearchFilterType filter = new SearchFilterType(); filter.parseFromXNode(xnode, prismContext); return filter; } public void parseFromXNode(XNode xnode, PrismContext prismContext) throws SchemaException { if (xnode == null || xnode.isEmpty()) { this.filterClauseXNode = null; this.description = null; } else { if (!(xnode instanceof MapXNode)) { throw new SchemaException("Cannot parse filter from "+xnode); } MapXNode xmap = (MapXNode)xnode; XNode xdesc = xmap.get(SearchFilterType.F_DESCRIPTION); if (xdesc != null) { if (xdesc instanceof PrimitiveXNode<?>) { String desc = ((PrimitiveXNode<String>)xdesc).getParsedValue(DOMUtil.XSD_STRING, String.class); setDescription(desc); } else { throw new SchemaException("Description must have a primitive value"); } } MapXNode xfilter = new MapXNode(); for (Entry<QName,XNode> entry: xmap.entrySet()) { if (!QNameUtil.match(entry.getKey(), SearchFilterType.F_DESCRIPTION) && !QNameUtil.match(entry.getKey(), new QName("condition"))) { xfilter.put(entry.getKey(), entry.getValue()); } } if (xfilter.size() > 1) { throw new SchemaException("Filter clause has more than one item: " + xfilter); } this.filterClauseXNode = xfilter; QueryConvertor.parseFilterPreliminarily(xfilter, prismContext); } } public MapXNode serializeToXNode() throws SchemaException { MapXNode xmap = getFilterClauseXNode(); if (description == null) { return xmap; } else { // we have to serialize the map in correct order (see MID-1847): description first, filter clause next MapXNode newXMap = new MapXNode(); newXMap.put(SearchFilterType.F_DESCRIPTION, new PrimitiveXNode<>(description)); if (xmap != null && !xmap.isEmpty()) { newXMap.put(xmap.getSingleSubEntry("search filter")); } return newXMap; } } /** * Generates a String representation of the contents of this type. * This is an extension method, produced by the 'ts' xjc plugin * */ @Override public String toString() { return ToStringBuilder.reflectionToString(this); } public int hashCode(ObjectLocator locator, HashCodeStrategy strategy) { int currentHashCode = 1; { MapXNode theFilter; theFilter = this.filterClauseXNode; currentHashCode = strategy.hashCode(LocatorUtils.property(locator, "filter", theFilter), currentHashCode, theFilter); } return currentHashCode; } public int hashCode() { final HashCodeStrategy strategy = DomAwareHashCodeStrategy.INSTANCE; return this.hashCode(null, strategy); } public boolean equals(ObjectLocator thisLocator, ObjectLocator thatLocator, Object object, EqualsStrategy strategy) { if (!(object instanceof SearchFilterType)) { return false; } if (this == object) { return true; } final SearchFilterType that = ((SearchFilterType) object); if (filterClauseXNode == null) { if (that.filterClauseXNode != null) return false; } else if (!filterClauseXNode.equals(that.filterClauseXNode)) return false; return true; } public boolean equals(Object object) { final EqualsStrategy strategy = DomAwareEqualsStrategy.INSTANCE; return equals(null, null, object, strategy); } /** * Creates and returns a deep copy of a given object. * * @param o * The instance to copy or {@code null}. * @return * A deep copy of {@code o} or {@code null} if {@code o} is {@code null}. */ @SuppressWarnings("unchecked") private static Object copyOf(final Object o) { // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000 try { if (o!= null) { if (o.getClass().isPrimitive()) { return o; } if (o.getClass().isArray()) { return copyOfArray(o); } // Immutable types. if (o instanceof Boolean) { return o; } if (o instanceof Byte) { return o; } if (o instanceof Character) { return o; } if (o instanceof Double) { return o; } if (o instanceof Enum) { return o; } if (o instanceof Float) { return o; } if (o instanceof Integer) { return o; } if (o instanceof Long) { return o; } if (o instanceof Short) { return o; } if (o instanceof String) { return o; } if (o instanceof BigDecimal) { return o; } if (o instanceof BigInteger) { return o; } if (o instanceof UUID) { return o; } if (o instanceof QName) { return o; } if (o instanceof Duration) { return o; } if (o instanceof Currency) { return o; } // String based types. if (o instanceof File) { return new File(o.toString()); } if (o instanceof URI) { return new URI(o.toString()); } if (o instanceof URL) { return new URL(o.toString()); } if (o instanceof MimeType) { return new MimeType(o.toString()); } // Cloneable types. if (o instanceof XMLGregorianCalendar) { return ((XMLGregorianCalendar) o).clone(); } if (o instanceof Date) { return ((Date) o).clone(); } if (o instanceof Calendar) { return ((Calendar) o).clone(); } if (o instanceof TimeZone) { return ((TimeZone) o).clone(); } if (o instanceof Locale) { return ((Locale) o).clone(); } if (o instanceof Element) { return ((Element)((Element) o).cloneNode(true)); } if (o instanceof JAXBElement) { return copyOf(((JAXBElement) o)); } try { return o.getClass().getMethod("clone", ((Class[]) null)).invoke(o, ((Object[]) null)); } catch (NoSuchMethodException e) { if (o instanceof Serializable) { return copyOf(((Serializable) o)); } // Please report this at https://apps.sourceforge.net/mantisbt/ccxjc/ throw((AssertionError) new AssertionError((("Unexpected instance during copying object '"+ o)+"'.")).initCause(e)); } catch (IllegalAccessException e) { // Please report this at https://apps.sourceforge.net/mantisbt/ccxjc/ throw((AssertionError) new AssertionError((("Unexpected instance during copying object '"+ o)+"'.")).initCause(e)); } catch (InvocationTargetException e) { // Please report this at https://apps.sourceforge.net/mantisbt/ccxjc/ throw((AssertionError) new AssertionError((("Unexpected instance during copying object '"+ o)+"'.")).initCause(e)); } catch (SecurityException e) { // Please report this at https://apps.sourceforge.net/mantisbt/ccxjc/ throw((AssertionError) new AssertionError((("Unexpected instance during copying object '"+ o)+"'.")).initCause(e)); } catch (IllegalArgumentException e) { // Please report this at https://apps.sourceforge.net/mantisbt/ccxjc/ throw((AssertionError) new AssertionError((("Unexpected instance during copying object '"+ o)+"'.")).initCause(e)); } catch (ExceptionInInitializerError e) { // Please report this at https://apps.sourceforge.net/mantisbt/ccxjc/ throw((AssertionError) new AssertionError((("Unexpected instance during copying object '"+ o)+"'.")).initCause(e)); } } return null; } catch (URISyntaxException e) { throw((AssertionError) new AssertionError((("Unexpected instance during copying object '"+ o)+"'.")).initCause(e)); } catch (MalformedURLException e) { throw((AssertionError) new AssertionError((("Unexpected instance during copying object '"+ o)+"'.")).initCause(e)); } catch (MimeTypeParseException e) { throw((AssertionError) new AssertionError((("Unexpected instance during copying object '"+ o)+"'.")).initCause(e)); } } /** * Creates and returns a deep copy of a given array. * * @param array * The array to copy or {@code null}. * @return * A deep copy of {@code array} or {@code null} if {@code array} is {@code null}. */ private static Object copyOfArray(final Object array) { // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000 if (array!= null) { if (array.getClass() == boolean[].class) { return copyOf(((boolean[]) array)); } if (array.getClass() == byte[].class) { return copyOf(((byte[]) array)); } if (array.getClass() == char[].class) { return copyOf(((char[]) array)); } if (array.getClass() == double[].class) { return copyOf(((double[]) array)); } if (array.getClass() == float[].class) { return copyOf(((float[]) array)); } if (array.getClass() == int[].class) { return copyOf(((int[]) array)); } if (array.getClass() == long[].class) { return copyOf(((long[]) array)); } if (array.getClass() == short[].class) { return copyOf(((short[]) array)); } final int len = Array.getLength(array); final Object copy = Array.newInstance(array.getClass().getComponentType(), len); for (int i = (len- 1); (i >= 0); i--) { Array.set(copy, i, copyOf(Array.get(array, i))); } return copy; } return null; } /** * Creates and returns a deep copy of a given array. * * @param array * The array to copy or {@code null}. * @return * A deep copy of {@code array} or {@code null} if {@code array} is {@code null}. */ private static boolean[] copyOf(final boolean[] array) { // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000 if (array!= null) { final boolean[] copy = ((boolean[]) Array.newInstance(array.getClass().getComponentType(), array.length)); System.arraycopy(array, 0, copy, 0, array.length); return copy; } return null; } /** * Creates and returns a deep copy of a given array. * * @param array * The array to copy or {@code null}. * @return * A deep copy of {@code array} or {@code null} if {@code array} is {@code null}. */ private static byte[] copyOf(final byte[] array) { // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000 if (array!= null) { final byte[] copy = ((byte[]) Array.newInstance(array.getClass().getComponentType(), array.length)); System.arraycopy(array, 0, copy, 0, array.length); return copy; } return null; } /** * Creates and returns a deep copy of a given array. * * @param array * The array to copy or {@code null}. * @return * A deep copy of {@code array} or {@code null} if {@code array} is {@code null}. */ private static char[] copyOf(final char[] array) { // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000 if (array!= null) { final char[] copy = ((char[]) Array.newInstance(array.getClass().getComponentType(), array.length)); System.arraycopy(array, 0, copy, 0, array.length); return copy; } return null; } /** * Creates and returns a deep copy of a given array. * * @param array * The array to copy or {@code null}. * @return * A deep copy of {@code array} or {@code null} if {@code array} is {@code null}. */ private static double[] copyOf(final double[] array) { // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000 if (array!= null) { final double[] copy = ((double[]) Array.newInstance(array.getClass().getComponentType(), array.length)); System.arraycopy(array, 0, copy, 0, array.length); return copy; } return null; } /** * Creates and returns a deep copy of a given array. * * @param array * The array to copy or {@code null}. * @return * A deep copy of {@code array} or {@code null} if {@code array} is {@code null}. */ private static float[] copyOf(final float[] array) { // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000 if (array!= null) { final float[] copy = ((float[]) Array.newInstance(array.getClass().getComponentType(), array.length)); System.arraycopy(array, 0, copy, 0, array.length); return copy; } return null; } /** * Creates and returns a deep copy of a given array. * * @param array * The array to copy or {@code null}. * @return * A deep copy of {@code array} or {@code null} if {@code array} is {@code null}. */ private static int[] copyOf(final int[] array) { // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000 if (array!= null) { final int[] copy = ((int[]) Array.newInstance(array.getClass().getComponentType(), array.length)); System.arraycopy(array, 0, copy, 0, array.length); return copy; } return null; } /** * Creates and returns a deep copy of a given array. * * @param array * The array to copy or {@code null}. * @return * A deep copy of {@code array} or {@code null} if {@code array} is {@code null}. */ private static long[] copyOf(final long[] array) { // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000 if (array!= null) { final long[] copy = ((long[]) Array.newInstance(array.getClass().getComponentType(), array.length)); System.arraycopy(array, 0, copy, 0, array.length); return copy; } return null; } /** * Creates and returns a deep copy of a given array. * * @param array * The array to copy or {@code null}. * @return * A deep copy of {@code array} or {@code null} if {@code array} is {@code null}. */ private static short[] copyOf(final short[] array) { // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000 if (array!= null) { final short[] copy = ((short[]) Array.newInstance(array.getClass().getComponentType(), array.length)); System.arraycopy(array, 0, copy, 0, array.length); return copy; } return null; } /** * Creates and returns a deep copy of a given {@code JAXBElement} instance. * * @param element * The instance to copy or {@code null}. * @return * A deep copy of {@code element} or {@code null} if {@code element} is {@code null}. */ @SuppressWarnings("unchecked") private static JAXBElement copyOf(final JAXBElement element) { // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000 if (element!= null) { final JAXBElement copy = new JAXBElement(element.getName(), element.getDeclaredType(), element.getScope(), element.getValue()); copy.setNil(element.isNil()); copy.setValue(copyOf(copy.getValue())); return copy; } return null; } /** * Creates and returns a deep copy of a given {@code Serializable}. * * @param serializable * The instance to copy or {@code null}. * @return * A deep copy of {@code serializable} or {@code null} if {@code serializable} is {@code null}. */ private static Serializable copyOf(final Serializable serializable) { // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000 if (serializable!= null) { try { final ByteArrayOutputStream byteArrayOutput = new ByteArrayOutputStream(); final ObjectOutputStream out = new ObjectOutputStream(byteArrayOutput); out.writeObject(serializable); out.close(); final ByteArrayInputStream byteArrayInput = new ByteArrayInputStream(byteArrayOutput.toByteArray()); final ObjectInputStream in = new ObjectInputStream(byteArrayInput); final Serializable copy = ((Serializable) in.readObject()); in.close(); return copy; } catch (SecurityException e) { throw((AssertionError) new AssertionError((("Unexpected instance during copying object '"+ serializable)+"'.")).initCause(e)); } catch (ClassNotFoundException e) { throw((AssertionError) new AssertionError((("Unexpected instance during copying object '"+ serializable)+"'.")).initCause(e)); } catch (InvalidClassException e) { throw((AssertionError) new AssertionError((("Unexpected instance during copying object '"+ serializable)+"'.")).initCause(e)); } catch (NotSerializableException e) { throw((AssertionError) new AssertionError((("Unexpected instance during copying object '"+ serializable)+"'.")).initCause(e)); } catch (StreamCorruptedException e) { throw((AssertionError) new AssertionError((("Unexpected instance during copying object '"+ serializable)+"'.")).initCause(e)); } catch (OptionalDataException e) { throw((AssertionError) new AssertionError((("Unexpected instance during copying object '"+ serializable)+"'.")).initCause(e)); } catch (IOException e) { throw((AssertionError) new AssertionError((("Unexpected instance during copying object '"+ serializable)+"'.")).initCause(e)); } } return null; } /** * Creates and returns a deep copy of this object. * * * @return * A deep copy of this object. */ @Override public SearchFilterType clone() { final SearchFilterType clone; try { clone = this.getClass().newInstance(); // TODO fix this using super.clone() } catch (InstantiationException|IllegalAccessException e) { throw new IllegalStateException("Couldn't instantiate " + this.getClass() + ": " + e.getMessage(), e); } clone.description = this.description; if (this.filterClauseXNode != null) { clone.filterClauseXNode = (MapXNode) this.filterClauseXNode.clone(); } return clone; } @Override public String debugDump() { return debugDump(0); } @Override public String debugDump(int indent) { StringBuilder sb = new StringBuilder(); DebugUtil.indentDebugDump(sb, indent); sb.append("SearchFilterType"); if (description != null) { sb.append("\n"); DebugUtil.debugDumpWithLabel(sb, "description", description, indent + 1); } if (filterClauseXNode != null) { sb.append("\n"); DebugUtil.debugDumpWithLabel(sb, "filterClauseXNode", (DebugDumpable) filterClauseXNode, indent + 1); } return sb.toString(); } }