/** * Generates an NSDictionary representing primary key values, both simple and compound. If values * are encrypted we try to create the correct attribute value type. Supported types are: strings, * numbers, timestamps and custom attributes with a factory method using a string argument. * * @param value the primary key value, either a single value or a collection * @param entity the entity used to gather primary key information * @param isEncrypted yes/no * @return a dictionary with primary key values */ private static NSDictionary processPrimaryKeyValue( String value, EOEntity entity, boolean isEncrypted) { NSArray pkAttributeNames = entity.primaryKeyAttributeNames(); try { pkAttributeNames = pkAttributeNames.sortedArrayUsingComparator(NSComparator.AscendingStringComparator); } catch (NSComparator.ComparisonException ex) { log.error("Unable to sort attribute names: " + ex); throw new NSForwardException(ex); } NSArray values = isEncrypted ? NSArray.componentsSeparatedByString( ERXCrypto.blowfishDecode(value).trim(), AttributeValueSeparator) : NSArray.componentsSeparatedByString(value, AttributeValueSeparator); int attrCount = pkAttributeNames.count(); NSMutableDictionary result = new NSMutableDictionary(attrCount); for (int i = 0; i < attrCount; i++) { String currentAttributeName = (String) pkAttributeNames.objectAtIndex(i); EOAttribute currentAttribute = entity.attributeNamed(currentAttributeName); Object currentValue = values.objectAtIndex(i); switch (currentAttribute.adaptorValueType()) { case 3: NSTimestampFormatter tsf = new NSTimestampFormatter(); try { currentValue = tsf.parseObject((String) currentValue); } catch (java.text.ParseException ex) { log.error("Error while trying to parse: " + currentValue); throw new NSForwardException(ex); } case 1: if (currentAttribute.valueFactoryMethodName() != null) { currentValue = currentAttribute.newValueForString((String) currentValue); } case 0: currentValue = new java.math.BigDecimal((String) currentValue); } result.setObjectForKey(currentValue, currentAttributeName); } return result; }
// ENHANCEME: Could also place a sha hash of the blowfish key in the form values so we can know if // we are using // the correct key for decryption. public static String encodeEnterpriseObjectsPrimaryKeyForUrl( NSArray eos, String separator, boolean encrypt) { // Array of objects to be encoded NSMutableArray encoded = new NSMutableArray(); // If the separator is not specified, default to the one given at class init if (separator == null) separator = entityNameSeparator(); // Add the separator if needed if (isSpecifySeparatorInURL()) encoded.addObject("sep=" + separator); int c = 1; // Iterate through the objects for (Enumeration e = eos.objectEnumerator(); e.hasMoreElements(); ) { EOEnterpriseObject eo = (EOEnterpriseObject) e.nextElement(); // Get the primary key of the object NSArray pkValues = ERXEOControlUtilities.primaryKeyArrayForObject(eo); if (pkValues == null && eo instanceof ERXGeneratesPrimaryKeyInterface) { NSDictionary pkDict = ((ERXGeneratesPrimaryKeyInterface) eo).primaryKeyDictionary(false); if (pkDict != null) pkValues = pkDict.allValues(); } if (pkValues == null) throw new RuntimeException("Primary key is null for object: " + eo); String pk = pkValues.componentsJoinedByString(AttributeValueSeparator); // Get the EncodedEntityName of the object String encodedEntityName = entityNameEncode(eo); // Add the result to the list of encoded objects encoded.addObject( encodedEntityName + separator + (encrypt ? "E" : "") + c++ + "=" + (encrypt ? ERXCrypto.blowfishEncode(pk) : pk)); } // Return the result as an url-encoded string return encoded.componentsJoinedByString("&"); }