001/*
002 *  Copyright 2010 Anyware Services
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 */
016package org.ametys.web.alias;
017
018import java.util.Calendar;
019import java.util.Date;
020import java.util.GregorianCalendar;
021
022import javax.jcr.Node;
023import javax.jcr.RepositoryException;
024
025import org.apache.commons.lang.StringUtils;
026
027import org.ametys.plugins.repository.AmetysObject;
028import org.ametys.plugins.repository.AmetysRepositoryException;
029import org.ametys.plugins.repository.MovableAmetysObject;
030import org.ametys.plugins.repository.RepositoryConstants;
031import org.ametys.plugins.repository.jcr.SimpleAmetysObject;
032import org.ametys.web.repository.page.jcr.DefaultZoneItemFactory;
033
034
035/**
036 * A {@link DefaultAlias} is a URL redirection to an existing page or a module URL
037 */
038public class DefaultAlias extends SimpleAmetysObject<DefaultAliasFactory> implements Alias, MovableAmetysObject
039{
040    /** Constant for origin metadata. */
041    public static final String METADATA_CREATED_AT = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":createdAt";
042    /** Constant for origin metadata. */
043    public static final String METADATA_URL = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":url";
044    /** Constant for target metadata. */
045    public static final String METADATA_TARGET = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":target";
046    /** Constant for type metadata. */
047    public static final String METADATA_TYPE = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":type";
048    /** Constant for period metadata. */
049    public static final String METADATA_EXPIRATION_DATE = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":expirationDate";
050    
051    /**
052     * Creates a {@link DefaultAlias}.
053     * 
054     * @param node the node backing this {@link AmetysObject}.
055     * @param parentPath the parent path in the Ametys hierarchy.
056     * @param factory the {@link DefaultZoneItemFactory} which creates the AmetysObject.
057     */
058    public DefaultAlias(Node node, String parentPath, DefaultAliasFactory factory)
059    {
060        super(node, parentPath, factory);
061    }
062    
063    @Override
064    public String getUrl() throws AmetysRepositoryException
065    {
066        try
067        {
068            return getNode().getProperty(METADATA_URL).getString();
069        }
070        catch (RepositoryException e)
071        {
072            throw new AmetysRepositoryException("Unable to get origin property", e);
073        }
074    }
075    
076    @Override
077    public void setUrl(String url) throws AmetysRepositoryException
078    {
079        try
080        {
081            getNode().setProperty(METADATA_URL, url);
082        }
083        catch (RepositoryException e)
084        {
085            throw new AmetysRepositoryException("Unable to set origin property", e);
086        }
087    }
088    
089    @Override
090    public String getTarget () throws AmetysRepositoryException
091    {
092        try
093        {
094            return getNode().getProperty(METADATA_TARGET).getString();
095        }
096        catch (RepositoryException e)
097        {
098            throw new AmetysRepositoryException("Unable to get target property", e);
099        }
100    }
101    
102    @Override
103    public void setTarget(String url) throws AmetysRepositoryException
104    {
105        try
106        {
107            getNode().setProperty(METADATA_TARGET, url);
108        }
109        catch (RepositoryException e)
110        {
111            throw new AmetysRepositoryException("Unable to set origin property", e);
112        }
113    }
114    
115    
116    @Override
117    public Date getExpirationDate() throws AmetysRepositoryException
118    {
119        try
120        {
121            if (getNode().hasProperty(METADATA_EXPIRATION_DATE))
122            {
123                return getNode().getProperty(METADATA_EXPIRATION_DATE).getDate().getTime();
124            }
125            return null;
126        }
127        catch (RepositoryException e)
128        {
129            throw new AmetysRepositoryException("Unable to get expiration date property", e);
130        }
131    }
132    
133    @Override
134    public void removeExpirationDate ()
135    {
136        try
137        {
138            if (getNode().hasProperty(METADATA_EXPIRATION_DATE))
139            {
140                getNode().getProperty(METADATA_EXPIRATION_DATE).remove();
141            }
142        }
143        catch (RepositoryException e)
144        {
145            throw new AmetysRepositoryException("Unable to get type property", e);
146        }
147    }
148    @Override
149    public void setExpirationDate(Date date) throws AmetysRepositoryException
150    {
151        try
152        {
153            Calendar calendar = new GregorianCalendar();
154            calendar.setTime(date);
155            getNode().setProperty(METADATA_EXPIRATION_DATE, calendar);
156        }
157        catch (RepositoryException e)
158        {
159            throw new AmetysRepositoryException("Unable to set expiration date property", e);
160        }
161    }
162    
163    @Override
164    public TargetType getType() throws AmetysRepositoryException
165    {
166        try
167        {
168            return TargetType.valueOf(getNode().getProperty(METADATA_TYPE).getString());
169        }
170        catch (RepositoryException e)
171        {
172            throw new AmetysRepositoryException("Unable to get type property", e);
173        }
174    }
175    
176    @Override
177    public void setType(TargetType type) throws AmetysRepositoryException
178    {
179        try
180        {
181            getNode().setProperty(METADATA_TYPE, type.name());
182        }
183        catch (RepositoryException e)
184        {
185            throw new AmetysRepositoryException("Unable to set type property", e);
186        }
187    }
188    
189    @Override
190    public Date getCreationDate() throws AmetysRepositoryException
191    {
192        try
193        {
194            return getNode().getProperty(METADATA_CREATED_AT).getDate().getTime();
195        }
196        catch (RepositoryException e)
197        {
198            throw new AmetysRepositoryException("Unable to get date property", e);
199        }
200    }
201    
202    @Override
203    public void setCreationDate(Date date) throws AmetysRepositoryException
204    {
205        try
206        {
207            Calendar calendar = new GregorianCalendar();
208            calendar.setTime(date);
209            getNode().setProperty(METADATA_CREATED_AT, calendar);
210        }
211        catch (RepositoryException e)
212        {
213            throw new AmetysRepositoryException("Unable to set type property", e);
214        }
215        
216    }
217    
218    @Override
219    public void orderBefore(AmetysObject siblingObject) throws AmetysRepositoryException
220    {
221        if (siblingObject instanceof DefaultAlias)
222        {
223            DefaultAlias sibling = (DefaultAlias) siblingObject;
224            sibling.getPath();
225            Node node = getNode();
226            String siblingPath = "";
227            try
228            {
229                siblingPath = sibling.getNode().getPath();
230                if (siblingPath.contains("/"))
231                {
232                    siblingPath = StringUtils.substringAfterLast(siblingPath, "/");
233                }
234                String path = node.getPath();
235                if (path.contains("/"))
236                {
237                    path = StringUtils.substringAfterLast(path, "/");
238                }
239                node.getParent().orderBefore(path, siblingPath);
240            }
241            catch (RepositoryException e)
242            {
243                throw new AmetysRepositoryException(String.format("Unable to order alias '%s' before alias '%s'", this, siblingPath), e);
244            }
245        }
246        else
247        {
248            throw new AmetysRepositoryException("An alias can only be moved before another alias.");
249        }
250    }
251    
252    @Override
253    public boolean canMoveTo(AmetysObject newParent) throws AmetysRepositoryException
254    {
255        return getParent().equals(newParent);
256    }
257    
258    @Override
259    public void moveTo(AmetysObject newParent, boolean renameIfExist) throws AmetysRepositoryException
260    {
261        if (getParent().equals(newParent))
262        {
263            try
264            {
265                // Just order current node to the end.
266                Node node = getNode();
267                String path = node.getPath();
268                if (path.contains("/"))
269                {
270                    path = StringUtils.substringAfterLast(path, "/");
271                }
272                node.getParent().orderBefore(path, null);
273            }
274            catch (RepositoryException e)
275            {
276                throw new AmetysRepositoryException(String.format("Unable to move alias '%s' outside the root alias node.", this), e);
277            }
278        }
279        else
280        {
281            throw new AmetysRepositoryException("An alias can only be moved before another alias.");
282        }
283    }
284
285}