<commit_before>package org.javers.core.metamodel.object;

import org.javers.common.exception.JaversException;
import org.javers.common.exception.JaversExceptionCode;
import org.javers.common.validation.Validate;
import org.javers.core.graph.ObjectAccessHook;
import org.javers.core.metamodel.type.*;
import org.javers.core.snapshot.ObjectHasher;
import org.javers.guava.MultimapType;
import org.javers.guava.MultisetType;
import org.javers.repository.jql.GlobalIdDTO;
import org.javers.repository.jql.InstanceIdDTO;
import org.javers.repository.jql.UnboundedValueObjectIdDTO;
import org.javers.repository.jql.ValueObjectIdDTO;
import org.picocontainer.PicoContainer;

/**
 * @author <NAME>
 */
public class GlobalIdFactory {

    private final TypeMapper typeMapper;
    private ObjectAccessHook objectAccessHook;
    private final GlobalIdPathParser pathParser;
    private ObjectHasher objectHasher;
    private final PicoContainer picoContainer;

    public GlobalIdFactory(TypeMapper typeMapper, ObjectAccessHook objectAccessHook, PicoContainer container) {
        this.typeMapper = typeMapper;
        this.objectAccessHook = objectAccessHook;
        this.pathParser = new GlobalIdPathParser(typeMapper);
        this.picoContainer = container;
    }

    public GlobalId createId(Object targetCdo) {
        return createId(targetCdo, null);
    }

    /**
     * @param ownerContext for bounded ValueObjects, optional
     */
    public GlobalId createId(Object targetCdo, OwnerContext ownerContext) {
        Validate.argumentsAreNotNull(targetCdo);

        targetCdo = objectAccessHook.access(targetCdo);
        ManagedType targetManagedType = typeMapper.getJaversManagedType(targetCdo.getClass());

        if (targetManagedType instanceof EntityType) {
            return InstanceId.createFromInstance(targetCdo, (EntityType) targetManagedType);
        }

        if (targetManagedType instanceof ValueObjectType && !hasOwner(ownerContext)) {
            return new UnboundedValueObjectId(targetManagedType.getName());
        }

        if (targetManagedType instanceof ValueObjectType && hasOwner(ownerContext)) {
            String pathFromRoot = createPathFromRoot(ownerContext.getOwnerId(), ownerContext.getPath());

            if (ownerContext.requiresObjectHasher()) {
                pathFromRoot += "/" + getObjectHasher().hash(targetCdo);
            }
            return new ValueObjectId(targetManagedType.getName(), getRootOwnerId(ownerContext), pathFromRoot);
        }

        throw new JaversException(JaversExceptionCode.NOT_IMPLEMENTED);
    }

    private GlobalId getRootOwnerId(OwnerContext ownerContext) {
        GlobalId rootOwnerId;
        if (ownerContext.getOwnerId() instanceof ValueObjectId){
            rootOwnerId = ((ValueObjectId)ownerContext.getOwnerId()).getOwnerId();
        } else{
            rootOwnerId = ownerContext.getOwnerId();
        }
        return rootOwnerId;
    }

    private String createPathFromRoot(GlobalId parentId, String fragment) {
        if (parentId instanceof ValueObjectId){
           return ((ValueObjectId)parentId).getFragment()+"/"+fragment;
        } else{
           return fragment;
        }
    }

    public UnboundedValueObjectId createUnboundedValueObjectId(Class valueObjectClass){
        ValueObjectType valueObject = typeMapper.getJaversManagedType(valueObjectClass, ValueObjectType.class);
        return new UnboundedValueObjectId(valueObject.getName());
    }

    public InstanceId createInstanceId(Object instance){
        Validate.argumentIsNotNull(instance);
        EntityType entityType = typeMapper.getJaversManagedType(instance.getClass(), EntityType.class);
        return createInstanceId(entityType.getIdOf(instance), entityType);
    }

    public InstanceId createInstanceId(Object localId, EntityType entity){
        return new InstanceId(entity.getName(), localId);
    }

    @Deprecated
    public ValueObjectId createValueObjectIdFromPath(GlobalId owner, String fragment){
        ManagedType ownerType = typeMapper.getJaversManagedType(owner);
        ValueObjectType valueObjectType = pathParser.parseChildValueObject(ownerType,fragment);
        return new ValueObjectId(valueObjectType.getName(), owner, fragment);
    }

    public ValueObjectId createValueObjectId(String voTypeName, GlobalId owner, String fragment){
        Validate.argumentsAreNotNull(voTypeName, owner, fragment);
        ValueObjectType valueObjectType = typeMapper.getJaversManagedType(voTypeName, ValueObjectType.class);
        return new ValueObjectId(valueObjectType.getName(), owner, fragment);
    }

    public void touchValueObjectFromPath(ManagedType ownerType, String fragment){
        pathParser.parseChildValueObject(ownerType, fragment);
    }

    public InstanceId createInstanceId(Object localId, Class entityClass){
        EntityType entity = typeMapper.getJaversManagedType(entityClass, EntityType.class);
        return createInstanceId(localId, entity);
    }

    public GlobalId createFromDto(GlobalIdDTO globalIdDTO){
        if (globalIdDTO instanceof InstanceIdDTO){
            InstanceIdDTO idDTO = (InstanceIdDTO) globalIdDTO;
            return createInstanceId(idDTO.getCdoId(), idDTO.getEntity());
        }
        if (globalIdDTO instanceof UnboundedValueObjectIdDTO){
            UnboundedValueObjectIdDTO idDTO = (UnboundedValueObjectIdDTO) globalIdDTO;
            return createUnboundedValueObjectId(idDTO.getVoClass());
        }
        if (globalIdDTO instanceof ValueObjectIdDTO){
            ValueObjectIdDTO idDTO = (ValueObjectIdDTO) globalIdDTO;
            GlobalId ownerId = createFromDto(idDTO.getOwnerIdDTO());
            return createValueObjectIdFromPath(ownerId, idDTO.getPath());
        }
        throw new RuntimeException("type " + globalIdDTO.getClass() + " is not implemented");
    }

    /**
     * If item is Primitive or Value - returns it,
     * if item is Entity or ValueObject - returns its globalId,
     * if item is already instance of GlobalId - returns it.
     */
    public Object dehydrate(Object item, JaversType targetType, OwnerContext context){
        if (item == null) {
            return null;
        }
        if (!(item instanceof GlobalId) && targetType instanceof ManagedType) {
            return createId(item, context);
        } else {
            return item;
        }
    }

    //pico can't resolve cycles
    private ObjectHasher getObjectHasher(){
        if (objectHasher != null){
            return objectHasher;
        }
        synchronized (this) {
            objectHasher = picoContainer.getComponent(ObjectHasher.class);
            return objectHasher;
        }
    }

    private boolean hasOwner(OwnerContext context) {
        return context != null && context.getOwnerId() != null;
    }
}
<commit_msg>Issue #565 - fix for using a proxy when querying by Instance<commit_after>package org.javers.core.metamodel.object;

import org.javers.common.exception.JaversException;
import org.javers.common.exception.JaversExceptionCode;
import org.javers.common.validation.Validate;
import org.javers.core.graph.ObjectAccessHook;
import org.javers.core.metamodel.type.*;
import org.javers.core.snapshot.ObjectHasher;
import org.javers.guava.MultimapType;
import org.javers.guava.MultisetType;
import org.javers.repository.jql.GlobalIdDTO;
import org.javers.repository.jql.InstanceIdDTO;
import org.javers.repository.jql.UnboundedValueObjectIdDTO;
import org.javers.repository.jql.ValueObjectIdDTO;
import org.picocontainer.PicoContainer;

/**
 * @author <NAME>
 */
public class GlobalIdFactory {

    private final TypeMapper typeMapper;
    private ObjectAccessHook objectAccessHook;
    private final GlobalIdPathParser pathParser;
    private ObjectHasher objectHasher;
    private final PicoContainer picoContainer;

    public GlobalIdFactory(TypeMapper typeMapper, ObjectAccessHook objectAccessHook, PicoContainer container) {
        this.typeMapper = typeMapper;
        this.objectAccessHook = objectAccessHook;
        this.pathParser = new GlobalIdPathParser(typeMapper);
        this.picoContainer = container;
    }

    public GlobalId createId(Object targetCdo) {
        return createId(targetCdo, null);
    }

    /**
     * @param ownerContext for bounded ValueObjects, optional
     */
    public GlobalId createId(Object targetCdo, OwnerContext ownerContext) {
        Validate.argumentsAreNotNull(targetCdo);

        targetCdo = objectAccessHook.access(targetCdo);
        ManagedType targetManagedType = typeMapper.getJaversManagedType(targetCdo.getClass());

        if (targetManagedType instanceof EntityType) {
            return InstanceId.createFromInstance(targetCdo, (EntityType) targetManagedType);
        }

        if (targetManagedType instanceof ValueObjectType && !hasOwner(ownerContext)) {
            return new UnboundedValueObjectId(targetManagedType.getName());
        }

        if (targetManagedType instanceof ValueObjectType && hasOwner(ownerContext)) {
            String pathFromRoot = createPathFromRoot(ownerContext.getOwnerId(), ownerContext.getPath());

            if (ownerContext.requiresObjectHasher()) {
                pathFromRoot += "/" + getObjectHasher().hash(targetCdo);
            }
            return new ValueObjectId(targetManagedType.getName(), getRootOwnerId(ownerContext), pathFromRoot);
        }

        throw new JaversException(JaversExceptionCode.NOT_IMPLEMENTED);
    }

    private GlobalId getRootOwnerId(OwnerContext ownerContext) {
        GlobalId rootOwnerId;
        if (ownerContext.getOwnerId() instanceof ValueObjectId){
            rootOwnerId = ((ValueObjectId)ownerContext.getOwnerId()).getOwnerId();
        } else{
            rootOwnerId = ownerContext.getOwnerId();
        }
        return rootOwnerId;
    }

    private String createPathFromRoot(GlobalId parentId, String fragment) {
        if (parentId instanceof ValueObjectId){
           return ((ValueObjectId)parentId).getFragment()+"/"+fragment;
        } else{
           return fragment;
        }
    }

    public UnboundedValueObjectId createUnboundedValueObjectId(Class valueObjectClass){
        ValueObjectType valueObject = typeMapper.getJaversManagedType(valueObjectClass, ValueObjectType.class);
        return new UnboundedValueObjectId(valueObject.getName());
    }

    public InstanceId createInstanceId(Object instance){
        Validate.argumentIsNotNull(instance);
		
		instance = objectAccessHook.access(instance);
        EntityType entityType = typeMapper.getJaversManagedType(instance.getClass(), EntityType.class);
        return createInstanceId(entityType.getIdOf(instance), entityType);
    }

    public InstanceId createInstanceId(Object localId, EntityType entity){
        return new InstanceId(entity.getName(), localId);
    }

    @Deprecated
    public ValueObjectId createValueObjectIdFromPath(GlobalId owner, String fragment){
        ManagedType ownerType = typeMapper.getJaversManagedType(owner);
        ValueObjectType valueObjectType = pathParser.parseChildValueObject(ownerType,fragment);
        return new ValueObjectId(valueObjectType.getName(), owner, fragment);
    }

    public ValueObjectId createValueObjectId(String voTypeName, GlobalId owner, String fragment){
        Validate.argumentsAreNotNull(voTypeName, owner, fragment);
        ValueObjectType valueObjectType = typeMapper.getJaversManagedType(voTypeName, ValueObjectType.class);
        return new ValueObjectId(valueObjectType.getName(), owner, fragment);
    }

    public void touchValueObjectFromPath(ManagedType ownerType, String fragment){
        pathParser.parseChildValueObject(ownerType, fragment);
    }

    public InstanceId createInstanceId(Object localId, Class entityClass){
        EntityType entity = typeMapper.getJaversManagedType(entityClass, EntityType.class);
        return createInstanceId(localId, entity);
    }

    public GlobalId createFromDto(GlobalIdDTO globalIdDTO){
        if (globalIdDTO instanceof InstanceIdDTO){
            InstanceIdDTO idDTO = (InstanceIdDTO) globalIdDTO;
            return createInstanceId(idDTO.getCdoId(), idDTO.getEntity());
        }
        if (globalIdDTO instanceof UnboundedValueObjectIdDTO){
            UnboundedValueObjectIdDTO idDTO = (UnboundedValueObjectIdDTO) globalIdDTO;
            return createUnboundedValueObjectId(idDTO.getVoClass());
        }
        if (globalIdDTO instanceof ValueObjectIdDTO){
            ValueObjectIdDTO idDTO = (ValueObjectIdDTO) globalIdDTO;
            GlobalId ownerId = createFromDto(idDTO.getOwnerIdDTO());
            return createValueObjectIdFromPath(ownerId, idDTO.getPath());
        }
        throw new RuntimeException("type " + globalIdDTO.getClass() + " is not implemented");
    }

    /**
     * If item is Primitive or Value - returns it,
     * if item is Entity or ValueObject - returns its globalId,
     * if item is already instance of GlobalId - returns it.
     */
    public Object dehydrate(Object item, JaversType targetType, OwnerContext context){
        if (item == null) {
            return null;
        }
        if (!(item instanceof GlobalId) && targetType instanceof ManagedType) {
            return createId(item, context);
        } else {
            return item;
        }
    }

    //pico can't resolve cycles
    private ObjectHasher getObjectHasher(){
        if (objectHasher != null){
            return objectHasher;
        }
        synchronized (this) {
            objectHasher = picoContainer.getComponent(ObjectHasher.class);
            return objectHasher;
        }
    }

    private boolean hasOwner(OwnerContext context) {
        return context != null && context.getOwnerId() != null;
    }
}

{'fraction_non_alphanumeric': 0.08256947475629274, 'fraction_numerical': 0.00021824530772588389, 'mean_word_length': 3.425949774629749, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3636664', 'n_tokens_mistral': 3641, 'n_tokens_neox': 3632, 'n_words': 768}