5

I have a localized Component in one of the child Publications. I would like to know the parent Component from which the current Component has been localized.

This code will be executed in an event handler. Any guidance in the TOM.Net API or a code snippet on how to achieve this scenario would be very much helpful.

1
  • Hi Rekha. Your question has received some excellent answers. However, it would be good if you could show what you have already tried, and any investigation that you have already conducted, on future questions - "Provide details. Share your research." tridion.stackexchange.com/questions/ask. Thanks, Commented Feb 27, 2014 at 8:59

6 Answers 6

4

Please use the below method to get the parent Component from which the current Component been localized. This method been already validated. Blueprint chain filter just denotes the parent component if the current component is not localized; also it list down only the items in Down direction of blueprinting hierarchy. So please use the below method which uses the UsedItemsFilter concept. Hope this fulfills your requirement.

 private Component GetParentComponent(Component component)
    {
        UsedItemsFilter usedItemFilter = new UsedItemsFilter(component.Session)
        {
            IncludeBlueprintParentItem = true,
            ItemTypes = new Tridion.ContentManager.ItemType[] { ItemType.Component },
            BaseColumns = ListBaseColumns.Id
        };
        IEnumerable<IdentifiableObject> usedItems = component.GetUsedItems(usedItemFilter);
        if (usedItems == null) return null;
        usedItems = usedItems.Where(usedItem => usedItem.Id.ItemId.Equals(component.Id.ItemId));
        if (usedItems == null) return null;
        return usedItems.FirstOrDefault() as Component;
    }
1
  • 1
    On a localized item this just returns the location where it was localized before in the chain, doesn't give me the absolute parent (which you can get from GetBluePrintChain). Commented Feb 27, 2014 at 9:34
5

It would definitely help if you just read the API documentation, but here is some sample code that should give you an idea:

[TcmExtension("ExampleEventHandlerExtension")]
public class EventHandler : TcmExtension {
  public EventHandler() {
    EventSystem.Subscribe<Component, SaveEventArgs>(ComponentSaveAction, EventPhases.Processed);
  }

  public static void ComponentSaveAction(Component subject, SaveEventArgs args, EventPhases phases) {
    // the TCMURI of the Publication from this item
    TcmUri contextRepository = subject.ContextRepository.Id;

    // the TCMURI of the Publication where this item was localized
    TcmUri owningRepository = subject.OwningRepository.Id;

    if (subject.IsLocalized) {
      BluePrintChainFilter filter = new BluePrintChainFilter(subject.Session) {
          Direction = BluePrintChainDirection.Up
        };

      // the TCMURI of the Publication where this item was created
      owningRepository = new TcmUri(subject.GetBluePrintChain(filter).Last().Id.ContextRepositoryId, ItemType.Publication);
    }

    // build TcmUri of parent Component
    // (note using ItemId of owningRepositiory as a PublicationId, 
    //  since that is a Publication TcmUri)
    TcmUri uri = new TcmUri(subject.Id.ItemId, subject.Id.ItemType, owningRepository.ItemId);

    // load parent Component
    Component parent = new Component(uri, subject.Session);
  }
}

Note I didn't test any of this, it is just an example to give you an idea of what you can use, please read the API documentation for every method shown here to see if it indeed is what you require.

If you need the same info via the Core Service see my answer to How to get the owning publication of a component via the Core Service?

update

@Josh was right, it needs to be direction Up and Last(), so updated my code accordingly.

4
  • Shouldn't the Direction be 'BluePrintChainDirection.Up' in this case? Commented Feb 26, 2014 at 14:19
  • @premkumarsubramanian I didn't test this, but reading the documentation, down sounded like the thing to go for: Blueprint chain goes down to the bottom-level child item Commented Feb 26, 2014 at 14:27
  • 1
    Hi Bart. I tried out your code as I was looking for a more efficient way of finding the root; I can confirm we need to use the BluePrintChainDirection.Up, as we are scanning upwards in the blueprint towards the root. Also, you grab the first element via 'FirstOrDefault()', however I believe we need to grab the last component in the list as I noticed they are added in descending order. I wasn't sure it would be safe to assume the last element in the list would always be the root, but I think your assumption is correct.
    – Josh Hebb
    Commented Feb 26, 2014 at 17:32
  • @JoshHebb as mentioned I didn't test this, but reading the documentation, I was expecting to use the direction Down and reading the first item to get the absolute parent. It might very well be incorrect, but choosing direction Up and reading the last item, sounds like a bit of the same to me. Anyways, its always a smart thing to just write the code and debug it to confirm you get expected results. Commented Feb 27, 2014 at 8:29
2

From CoreService you can retrieve the information.

var component = client.Read("tcm:5-25", defaultReadOptions);
var componentInOriginalContext = client.Read(component.BluePrintInfo.PrimaryBluePrintParentItem.IdRef, defaultReadOptions);

This will return the most root item from anywhere in blueprint regardless the source is shared/localized.

1
  • It is a bit overkill to create a core service connection in an event handler I would say, since you have direct access to the TOM.NET API. Commented Feb 26, 2014 at 12:52
2

I recently ran into the same problem you are experiencing so I wrote the following helper method. Hopefully this helps you out. Essnetially, I use '.getBluePrintChain' to scan up the blueprint, and then calculate the lowest publication ID which we will use to construct the 'root' component.

// Scan up the blueprint to find the root component. This method will find the
// first instance in the blueprint of a component, which we will call the root.
public Component FindRootComponent(Component component)
{
    BluePrintChainFilter filter = new BluePrintChainFilter(component.Session);
    filter.Direction = BluePrintChainDirection.Up;
    var blueprintScanUp = component.GetBluePrintChain(filter);

    // Calculate the lowest pub ID in the tree, which will be our root.
    List<int> publicationIDs = new List<int>();
    foreach (RepositoryLocalObject blueprintNode in blueprintScanUp)
    {
        publicationIDs.Add(blueprintNode.Id.PublicationId);
    }
    int rootPubID = System.Linq.Enumerable.Min(publicationIDs);

    // Construct the component to be returned.
    TcmUri returnedId = new TcmUri(component.Id.ItemId, ItemType.Component, rootPubID);
    if (!component.Session.IsExistingObject(returnedId)) return null;
    Component returnedComponent = component.Session.GetObject(returnedId) as Component;
    if (returnedComponent == null) return null;
    else return returnedComponent;
}
0

besically, you need find parent publication. because ItemId is always same in all publications("tcm:publicationID-ItemID"). Appending parent publication to ComponentId(ItemID) will solve the issue.

Below Code could help:

Component tcmComponent = (Component)engine.GetObject("tcm:x-y-z");
tcmComponent.OwningRepository
1
  • 2
    When the component is localized, the owning repository is the publication in which the component is localized and not the publication in which the component was originally created. Commented Feb 26, 2014 at 12:16
0

Component.GetBluePrintChain method with filter parameter may help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.