001/*
002 * (C) Copyright 2006-2007 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Nuxeo - initial API and implementation
018 *
019 * $Id: JOOoConvertPluginImpl.java 18651 2007-05-13 20:28:53Z sfermigier $
020 */
021
022package org.nuxeo.ecm.directory;
023
024import java.util.List;
025
026/**
027 * Reference that uses the matching reference of the target directory to actually do the job.
028 *
029 * @author ogrisel
030 */
031public class InverseReference extends AbstractReference {
032
033    /**
034     * Indicates if the target directory can be updated from the current reference
035     *
036     * @since 5.7
037     */
038    protected boolean readOnly = false;
039
040    protected String dualReferenceName;
041
042    protected Reference dualReference;
043
044    public InverseReference(InverseReferenceDescriptor referenceDescriptor) {
045        super(referenceDescriptor.getFieldName(), referenceDescriptor.getDirectory());
046        dualReferenceName = referenceDescriptor.getDualReferenceName();
047        readOnly = referenceDescriptor.isReadOnly();
048    }
049
050    public void setReadOnly(boolean readOnly) {
051        this.readOnly = readOnly;
052    }
053
054    public boolean isReadOnly() {
055        return readOnly;
056    }
057
058    protected void checkDualReference() throws DirectoryException {
059        if (dualReference == null) {
060            List<Reference> references = getTargetDirectory().getReferences(dualReferenceName);
061            if (references.size() == 0) {
062                dualReference = null;
063            } else if (references.size() == 1) {
064                dualReference = references.get(0);
065            } else {
066                for (Reference ref : references) {
067                    if (ref instanceof InverseReference) {
068                        continue;
069                    } else if (sourceDirectoryName.equals(ref.getTargetDirectory().getName())
070                            && targetDirectoryName.equals(ref.getSourceDirectory().getName())) {
071                        if (dualReference == null) {
072                            dualReference = ref;
073                        } else {
074                            throw new DirectoryException(
075                                    "More than one reference: could not find reference " + dualReferenceName);
076                        }
077                    }
078                }
079            }
080        }
081        if (dualReference == null) {
082            throw new DirectoryException("could not find reference " + dualReferenceName);
083        }
084        if (dualReference instanceof InverseReference) {
085            throw new DirectoryException(String.format("InverseReference %s cannot refer to InverseReference %s",
086                    getFieldName(), dualReferenceName));
087        }
088    }
089
090    @Override
091    public void addLinks(String sourceId, List<String> targetIds) throws DirectoryException {
092        if (readOnly) {
093            return;
094        }
095        checkDualReference();
096        dualReference.addLinks(targetIds, sourceId);
097    }
098
099    @Override
100    public void addLinks(List<String> sourceIds, String targetId) throws DirectoryException {
101        if (readOnly) {
102            return;
103        }
104        checkDualReference();
105        dualReference.addLinks(targetId, sourceIds);
106    }
107
108    @Override
109    public void removeLinksForTarget(String targetId) throws DirectoryException {
110        if (readOnly) {
111            return;
112        }
113        checkDualReference();
114        dualReference.removeLinksForSource(targetId);
115    }
116
117    @Override
118    public void removeLinksForTarget(String targetId, Session session) throws DirectoryException {
119        if (readOnly) {
120            return;
121        }
122        checkDualReference();
123        dualReference.removeLinksForSource(targetId, session);
124    }
125
126    @Override
127    public void removeLinksForSource(String sourceId) throws DirectoryException {
128        if (readOnly) {
129            return;
130        }
131        checkDualReference();
132        dualReference.removeLinksForTarget(sourceId);
133    }
134
135    @Override
136    public void removeLinksForSource(String sourceId, Session session) throws DirectoryException {
137        if (readOnly) {
138            return;
139        }
140        checkDualReference();
141        dualReference.removeLinksForTarget(sourceId, session);
142    }
143
144    @Override
145    public List<String> getSourceIdsForTarget(String targetId) throws DirectoryException {
146        checkDualReference();
147        return dualReference.getTargetIdsForSource(targetId);
148    }
149
150    @Override
151    public List<String> getTargetIdsForSource(String sourceId) throws DirectoryException {
152        checkDualReference();
153        return dualReference.getSourceIdsForTarget(sourceId);
154    }
155
156    @Override
157    public void setTargetIdsForSource(String sourceId, List<String> targetIds) throws DirectoryException {
158        if (readOnly) {
159            return;
160        }
161        checkDualReference();
162        dualReference.setSourceIdsForTarget(sourceId, targetIds);
163    }
164
165    @Override
166    public void setTargetIdsForSource(String sourceId, List<String> targetIds, Session session)
167            throws DirectoryException {
168        if (readOnly) {
169            return;
170        }
171        checkDualReference();
172        dualReference.setSourceIdsForTarget(sourceId, targetIds, session);
173    }
174
175    @Override
176    public void setSourceIdsForTarget(String targetId, List<String> sourceIds) throws DirectoryException {
177        if (readOnly) {
178            return;
179        }
180        checkDualReference();
181        dualReference.setTargetIdsForSource(targetId, sourceIds);
182    }
183
184    @Override
185    public void setSourceIdsForTarget(String targetId, List<String> sourceIds, Session session)
186            throws DirectoryException {
187        if (readOnly) {
188            return;
189        }
190        checkDualReference();
191        dualReference.setTargetIdsForSource(targetId, sourceIds, session);
192    }
193
194    @Override
195    public void addLinks(String sourceId, List<String> targetIds, Session session) throws DirectoryException {
196        if (readOnly) {
197            return;
198        }
199        checkDualReference();
200        dualReference.addLinks(targetIds, sourceId, session);
201    }
202
203    @Override
204    public void addLinks(List<String> sourceIds, String targetId, Session session) throws DirectoryException {
205        if (readOnly) {
206            return;
207        }
208        checkDualReference();
209        dualReference.addLinks(targetId, sourceIds, session);
210    }
211}