/** * Returns a new descriptor eqiuvalent to this+D. Remember, composition is not commutative for all * attributes, and may not exist for some. To compose, remember to call * {@linkDescriptor#isComposable() isComposable} first and try both <code>A.compose (B)</code> and * <code>B.compose (A)</code>. * * @param D The Descriptor to compose with this Descriptor. * @param scope The attribute scope and mapping. * @return A new Descriptor that is equivalent to the composition of this and the argument D. * @throws BadDataException if the compose semantics are not correct. * @throws UncomposableException this instance of the descriptor cannot be composed. Check * isComposable! */ public Descriptor compose(Descriptor D, EvaluationParameters.ScopeRules scope) throws BadDataException, UncomposableException { DescAggregate temp = (DescAggregate) this.clone(); // Unify Descriptions and Spans temp.span = temp.span.union(D.getFrameSpan()); if (D.getClass().equals(DescSingle.class)) { if (idList.contains(D.getID())) throw new BadDataException("Attempting to compose the same descriptor multiple times"); else temp.idList.add(D.getID()); } else { // First, check to see if there are any dup ID numbers Iterator iterA = idList.iterator(); Iterator iterB = ((TreeSet) D.getID()).iterator(); Comparable A = (Comparable) iterA.next(); Comparable B = (Comparable) iterB.next(); /// difference will be negative iff A < B, and positive iff A > B. // I wish java had operator overloading. I really do. double difference = A.compareTo(B); while (iterA.hasNext() && iterB.hasNext() && (difference != 0)) { while ((difference < 0) && (iterA.hasNext() && iterB.hasNext())) { A = (Comparable) iterA.next(); difference = A.compareTo(B); } while ((difference > 0) && (iterA.hasNext() && iterB.hasNext())) { B = (Comparable) iterB.next(); difference = A.compareTo(B); } } if (difference == 0) // If there was a dup ID num, return 0 throw new BadDataException("Attempting to compose the same descriptor multiple times"); temp.idList.addAll(((DescAggregate) D).idList); } // Unify Attributes String errMsg = null; for (Iterator iter = scope.getInScopeAttributesFor(temp); iter.hasNext(); ) { String currAttrName = (String) iter.next(); int i = temp.getAttributeIndex(currAttrName, scope.getMap()); try { temp.attributes[i] = Attribute.compose( this.span, this.getAttribute(currAttrName, scope.getMap()), D.span, D.getAttribute(currAttrName, scope.getMap())); } catch (UncomposableException ux) { if (errMsg == null) { errMsg = ux.getMessage(); } else { errMsg += "\n" + ux.getMessage(); } } } if (errMsg != null) System.err.println(errMsg + "\n fix your .epf"); return temp; }
/** * Serializes an {@link MBeanFeatureInfo} to an {@link ObjectOutputStream}. * * @serialData For compatibility reasons, an object of this class is serialized as follows. * <ul> * The method {@link ObjectOutputStream#defaultWriteObject defaultWriteObject()} is called * first to serialize the object except the field {@code descriptor} which is declared as * transient. The field {@code descriptor} is serialized as follows: * <ul> * <li>If {@code descriptor} is an instance of the class {@link ImmutableDescriptor}, the * method {@link ObjectOutputStream#write write(int val)} is called to write a byte * with the value {@code 1}, then the method {@link ObjectOutputStream#writeObject * writeObject(Object obj)} is called twice to serialize the field names and the field * values of the {@code descriptor}, respectively as a {@code String[]} and an {@code * Object[]}; * <li>Otherwise, the method {@link ObjectOutputStream#write write(int val)} is called to * write a byte with the value {@code 0}, then the method {@link * ObjectOutputStream#writeObject writeObject(Object obj)} is called to serialize * directly the field {@code descriptor}. * </ul> * </ul> * * @since 1.6 */ private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); if (descriptor != null && descriptor.getClass() == ImmutableDescriptor.class) { out.write(1); final String[] names = descriptor.getFieldNames(); out.writeObject(names); out.writeObject(descriptor.getFieldValues(names)); } else { out.write(0); out.writeObject(descriptor); } }