Search This Blog

Tuesday, April 21, 2015

What's in that Sandbox (UDF)

Opening up a sandbox that was exported after creating a UDF, you should find:

mdssys
persdef
xliffBundles

folders.

In the mdssys folder you will find:

sandbox/active_mdsSandboxMetadata.xml which contains the basic info on the sandbox, including the name you gave it when you created it, and the date and time, which you should have put into the name of the sandbox, like this:

Client_yyyyMMdd_HHmm

In the persdef folder you will find:

oracle/iam/ui/common/model/user/entity/mdssys/cust/site/site/UserEO.xml.xml which contains the definition of the UserEO object.  Grep on "Attribute Name" to get a list of all of the UserEO elements in the sandbox.  Your new ones should be there.

oracle/iam/ui/common/model/user/view/mdssys/cust/site/site/UserVO.xml.xml  which contains the definition of the UserVO object.  Grep on "ViewAttribute Name" to get a list of all of the UserVO elements in the sandbox.  Your new ones should be there.

In the xliffBundles folder you will find oracle/iam/ui/runtime/BizEditorBundle.xlf which contains the ADF mappings for all of the UI components.  Grep on user.entity.userEO to see all of the UserEO elements.  Your new objects should be there.

Tuesday, April 14, 2015

ICF DBAT Connector Trusted Recon

I originally posted this on the Oracle Community site but I thought I would add it here:

--- START OF POST ---

My colleague and I have written a Database Tables ICF connector and this is an update regarding doing multiple trusted recons.

The data is written to a staging table as events rather than what normally you would think of as a summary table (USR is a good example of a summary table). There are about a dozen events. Only one event is valid to trigger a Create User task, carrying with it about 20 of the user's initial data fields, and such I program the Last Name, OIM Organization Name, OIM User Type, and OIM Employee Type into the attribute map when I pass it to the ResultsHandler.

For an update only recon profiles and update tasks. I originally did not believe that I would need to pass in the Last Name, OIM Organization Name, OIM User Type, and OIM Employee Type parameters into the Resource Object since it only does updates. Since it never creates a user (no match=do nothing), there should be no need for these parameters in the Resource Object. But when I run the Recon I got an error: The profile might be corrupt and could possibly cause reconciliation failure:: xxxxx xxxxxx xxxxxx xxxxxx missing mappings for: [ACT_KEY, USR_LAST_NAME, USR_TYPE, USR_EMP_TYPE] and I get an error XL_SP_ReconBlkUsrRqdcValdnMtch while processing batch ID xxx One or more parameters passed as null

The resolution is this: Any trusted recon must map to these four parameters even if they are not provided in the lookup or the scheduled job. For an update only job you just leave them blank.


--- END OF POST ---

Since I wrote this (in 2013) I did also start putting the 3 normally fixed values of Organization Name, Xellerate Type, and Role, spelled exactly that way, into the RO, the PD, and the Lookup.XX.UM.ReconAttrMap.Trusted.Defaults lookup, instead of trying to generate them inside the connector.  This is only needed in the lookup for a recon that can do a create.  Otherwise, as stated above, put them into the RO and PD and leave them off of the lookup.  Of course Last Name is normally provided in a lookup, but if not then use the same process, put Last Name into the RO and PD and leave unmapped for UPDATES.

The names OIM Organization Name, OIM User Type, and OIM Employee Type are not the correct names, they were just made up.

Thursday, April 9, 2015

Constructing the Shuffle Algorithm

I recently needed to perform a shuffle operation on a set.  Shuffling seems very easy, but it actually can be difficult and fraught with errors.  Here's some info on how I went from the start to the finish of the development of my shuffle algorithm.

Like shuffling a deck of cards, a shuffle operation does not change the frequency of the values found in the set or list.  The shuffle operation can apply to a set or a list.  Recalling that a set consists of only unique values (no repeats) and a list consists of values and so, it can contain duplicates.  No matter what the source, the algorithm is the same.

The algorithm requires a random number generator (I will use Java):

Random random=new Random(System.currentTimeMillis());
int ranvalue=0;
int ranloc=0;
for(ranloc=0; ranloc<1000; ranloc++) {
  ranvalue=random.nextInt(1000);
}

I always set up a number generator as I show above, to properly seed the generator and then "spin" it 1000 times to get the random number generator properly set up.

Here is the basic starting setup and algorithm.
List<String> sourceList = new ArrayList<String>();
populate sourceList from the source.
List<String> shuffleList = new ArrayList<String>();
add the values from the sourceList to the shuffleList in a shuffled order.

This method:
shuffleList.addAll(sourceList)
would not be a good idea, the data are copied in the same order.

Using this method:

int numSource=sourceList.size();
for(ranloc=0; ranloc<numSource; ranloc++) {
  ranvalue=random.nextInt(numSource);
  shuffleList.add(sourceList.get(ranvalue);
}

This method would randomize the values, but depending on the size of the source list, there is a high likelyhood of the shuffleList containing the source data in different frequencies, as there is a high probablility of the random.nextInt call returning the same value in two calls. This method is flawed.

You could add a list of used values:

int numSource=sourceList.size();
List<Integer> usedLocations=new ArrayList<Integer>();
Integer usedLocation=null;
for(ranloc=0; ranloc<numSource; ranloc++) {
  ranvalue=random.nextInt(numSource);
  usedLocation=new Integer(ranvalue);
  while(usedLocations.contains(usedLocation) {
    ranvalue=random.nextInt(numSource);
    usedLocation=new Integer(ranvalue);
  }
  shuffleList.add(sourceList.get(ranvalue);
  usedLocations.add(usedLocation);
}

This will work, but can get into a very long spin of the while loop as the shuffleList fills up, looking for that one value that has not been filled in.

The better way is to use a use and delete method:

int numSource=sourceList.size();
List<Integer> unusedLocations=new ArrayList<Integer>();
Integer usedLocation=null;
int numLocations=numSource;
for(ranloc=0; ranloc<numSource; ranloc++) {
  usedLocation=new Integer(ranloc);
  unusedLocations.add(usedLocation);
}
for(ranloc=0; ranloc<numSource; ranloc++) {
  ranvalue=random.nextInt(numLocations);
  usedLocation=unusedLocations.get(ranvalue);
  ranvalue=usedLocations.intValue();
  shuffleList.add(sourceList.get(ranvalue);
  usedLocations.remove(usedLocation);
  numLocations=unusedLocations.size();
}

This method works properly and has a good speed.
Happy Shuffling!