001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.lar;
016    
017    import aQute.bnd.annotation.ProviderType;
018    
019    import com.liferay.portal.kernel.util.CharPool;
020    import com.liferay.portal.kernel.util.StringBundler;
021    import com.liferay.portal.kernel.util.StringPool;
022    import com.liferay.portal.kernel.util.Validator;
023    import com.liferay.portal.model.StagedGroupedModel;
024    import com.liferay.portal.model.StagedModel;
025    import com.liferay.portal.util.PortletKeys;
026    
027    import java.io.Serializable;
028    
029    /**
030     * Provides utility methods for generating paths for entities being serialized
031     * with the portal's export/import framework.
032     *
033     * @author Mate Thurzo
034     * @author Daniel Kocsis
035     * @since  6.2
036     */
037    @ProviderType
038    public class ExportImportPathUtil {
039    
040            /**
041             * The company prefix used in generating paths.
042             */
043            public static final String PATH_PREFIX_COMPANY = "company";
044    
045            /**
046             * The group prefix used in generating paths.
047             */
048            public static final String PATH_PREFIX_GROUP = "group";
049    
050            /**
051             * @deprecated As of 7.0.0
052             */
053            @Deprecated
054            public static final String PATH_PREFIX_LAYOUT = "layout";
055    
056            /**
057             * The portlet prefix used in generating paths.
058             */
059            public static final String PATH_PREFIX_PORTLET = "portlet";
060    
061            /**
062             * The service prefix used in generating paths.
063             */
064            public static final String PATH_PREFIX_SERVICE = "service";
065    
066            public static String getCompanyModelPath(
067                    long companyId, String className, long classPK) {
068    
069                    return getModelPath(
070                            PATH_PREFIX_COMPANY, companyId, className, classPK, null);
071            }
072    
073            /**
074             * Returns the expando-specific path for the entity path. The entity path
075             * must include an XML file.
076             *
077             * <p>
078             * For example, if you had the entity path of
079             * <code>/group/10184/com.liferay.portlet.dynamicdatamapping.model.DDMStructure/10951.xml</code>,
080             * the returned expando-specific path would be the following:
081             * </p>
082             *
083             * <p>
084             * <pre>
085             * <code>
086             * /group/10184/com.liferay.portlet.dynamicdatamapping.model.DDMStructure/10951-expando.xml
087             * </code>
088             * </pre>
089             * </p>
090             *
091             * @param  path the previously generated entity path
092             * @return the expando-specific path for the entity path
093             */
094            public static String getExpandoPath(String path) {
095                    if (!Validator.isFilePath(path, false)) {
096                            throw new IllegalArgumentException(
097                                    path + " is located outside of the LAR");
098                    }
099    
100                    int pos = path.lastIndexOf(_FILE_EXTENSION_XML);
101    
102                    if (pos == -1) {
103                            throw new IllegalArgumentException(path + " is not an XML file");
104                    }
105    
106                    return path.substring(0, pos).concat("-expando").concat(
107                            path.substring(pos));
108            }
109    
110            /**
111             * @deprecated As of 7.0.0, replaced by {@link #getModelPath(StagedModel)}
112             */
113            @Deprecated
114            public static String getLayoutPath(
115                    PortletDataContext portletDataContext, long plid) {
116    
117                    StringBundler sb = new StringBundler(5);
118    
119                    sb.append(getRootPath(portletDataContext));
120                    sb.append(StringPool.FORWARD_SLASH);
121                    sb.append(PATH_PREFIX_LAYOUT);
122                    sb.append(StringPool.FORWARD_SLASH);
123                    sb.append(plid);
124                    sb.append(_FILE_EXTENSION_XML);
125    
126                    return sb.toString();
127            }
128    
129            /**
130             * Returns a model path based on the group ID, class name, and class PK.
131             *
132             * <p>
133             * For example, a model path would resemble the following:
134             * </p>
135             *
136             * <p>
137             * <pre>
138             * <code>
139             * /group/"groupId"/"className"/"classPK".xml
140             * </code>
141             * </pre>
142             * </p>
143             *
144             * @param  groupId the group ID of the entity's group
145             * @param  className the entity's class name
146             * @param  classPK the primary key of the entity
147             * @return a model path based on the parameters
148             */
149            public static String getModelPath(
150                    long groupId, String className, long classPK) {
151    
152                    return getModelPath(
153                            PATH_PREFIX_GROUP, groupId, className, classPK, null);
154            }
155    
156            /**
157             * Returns a model path based on the group ID, class name, and class PK,
158             * where the group ID is queried from the portlet data context. This method
159             * uses the source group ID from the context.
160             *
161             * <p>
162             * For example, a model path would resemble the following:
163             * </p>
164             *
165             * <p>
166             * <pre>
167             * <code>
168             * /group/"queried groupId"/"className"/"classPK".xml
169             * </code>
170             * </pre>
171             * </p>
172             *
173             * @param  portletDataContext the context of the current export/import
174             *         process
175             * @param  className the entity's class name
176             * @param  classPK the primary key of the entity
177             * @return a model path based on the parameters
178             * @see    PortletDataContext#getSourceGroupId()
179             */
180            public static String getModelPath(
181                    PortletDataContext portletDataContext, String className, long classPK) {
182    
183                    return getModelPath(portletDataContext, className, classPK, null);
184            }
185    
186            /**
187             * Returns a model path for the named file related to the entity, having the
188             * class name and class PK. The dependent object's file name is appended to
189             * the generated prefix.
190             *
191             * <p>
192             * For example, a model path would resemble the following:
193             * </p>
194             *
195             * <p>
196             * <pre>
197             * <code>
198             * /group/"queried groupId"/"className"/"classPK"/"dependentFileName"
199             * </code>
200             * </pre>
201             * </p>
202             *
203             * @param  portletDataContext the context of the current export/import
204             *         process
205             * @param  className the related entity's class name
206             * @param  classPK the primary key of the related entity
207             * @param  dependentFileName the dependent object's file name
208             * @return a model path for the entity's dependent object
209             */
210            public static String getModelPath(
211                    PortletDataContext portletDataContext, String className, long classPK,
212                    String dependentFileName) {
213    
214                    return getModelPath(
215                            PATH_PREFIX_GROUP, portletDataContext.getSourceGroupId(), className,
216                            classPK, dependentFileName);
217            }
218    
219            /**
220             * Returns a model path for the staged model. The group ID, class name, and
221             * class PK are queried from the staged model to generate the path.
222             *
223             * <p>
224             * For example, a model path would resemble the following:
225             * </p>
226             *
227             * <p>
228             * <pre>
229             * <code>
230             * /group/"queried groupId"/"queried className"/"queried classPK".xml
231             * </code>
232             * </pre>
233             * </p>
234             *
235             * @param  stagedModel the staged model the path is needed for
236             * @return a model path for the staged model
237             * @see    StagedModel
238             */
239            public static String getModelPath(StagedModel stagedModel) {
240                    return getModelPath(stagedModel, null);
241            }
242    
243            /**
244             * Returns a model path for the named file related to the staged model.
245             *
246             * <p>
247             * This method is useful, for example, for generating the path for an image
248             * related to a web content article. The staged model's attributes are used
249             * to generate the first part of the path; then the dependent object's file
250             * name is attached to the end of the path.
251             * </p>
252             *
253             * <p>
254             * For example, a model path would resemble the following:
255             * </p>
256             *
257             * <p>
258             * <pre>
259             * <code>
260             * /group/"queried groupId"/"queried className"/"queried classPK"/"dependentFileName"
261             * </code>
262             * </pre>
263             * </p>
264             *
265             * @param  stagedModel the staged model the path is needed for
266             * @param  dependentFileName the dependent object's file name
267             * @return a model path for the staged model's dependent object
268             */
269            public static String getModelPath(
270                    StagedModel stagedModel, String dependentFileName) {
271    
272                    StagedModelType stagedModelType = stagedModel.getStagedModelType();
273    
274                    if (stagedModel instanceof StagedGroupedModel) {
275                            StagedGroupedModel stagedGroupedModel =
276                                    (StagedGroupedModel)stagedModel;
277    
278                            return getModelPath(
279                                    PATH_PREFIX_GROUP, stagedGroupedModel.getGroupId(),
280                                    stagedModelType.getClassName(), stagedModel.getPrimaryKeyObj(),
281                                    dependentFileName);
282                    }
283                    else {
284                            return getModelPath(
285                                    PATH_PREFIX_COMPANY, stagedModel.getCompanyId(),
286                                    stagedModelType.getClassName(), stagedModel.getPrimaryKeyObj(),
287                                    dependentFileName);
288                    }
289            }
290    
291            /**
292             * Returns a portlet path for the portlet ID.
293             *
294             * <p>
295             * For example, a portlet path would resemble the following:
296             * </p>
297             *
298             * <p>
299             * <pre>
300             * <code>
301             * /group/"queried groupId"/portlet/"portletId"
302             * </code>
303             * </pre>
304             * </p>
305             *
306             * @param  portletDataContext the context of the current export/import
307             *         process
308             * @param  portletId the portlet ID the path is being generated for
309             * @return a portlet path for the portlet ID
310             */
311            public static String getPortletPath(
312                    PortletDataContext portletDataContext, String portletId) {
313    
314                    StringBundler sb = new StringBundler(5);
315    
316                    sb.append(getRootPath(portletDataContext));
317                    sb.append(StringPool.FORWARD_SLASH);
318                    sb.append(PATH_PREFIX_PORTLET);
319                    sb.append(StringPool.FORWARD_SLASH);
320                    sb.append(portletId);
321    
322                    return sb.toString();
323            }
324    
325            public static String getPortletPreferencesPath(
326                    PortletDataContext portletDataContext, String portletId, long ownerId,
327                    int ownerType, long plid) {
328    
329                    StringBundler sb = new StringBundler(8);
330    
331                    sb.append(getPortletPath(portletDataContext, portletId));
332                    sb.append("/preferences/");
333                    sb.append(getOwnerTypePath(ownerType));
334                    sb.append(ownerId);
335                    sb.append(CharPool.FORWARD_SLASH);
336                    sb.append(plid);
337                    sb.append(CharPool.FORWARD_SLASH);
338                    sb.append("portlet-preferences.xml");
339    
340                    return sb.toString();
341            }
342    
343            /**
344             * Returns a root path, or fragment, of the model path based on the scope
345             * group ID from the portlet data context.
346             *
347             * <p>
348             * For example, a root path would resemble the following:
349             * </p>
350             *
351             * <p>
352             * <pre>
353             * <code>
354             * /group/"queried groupId"
355             * </code>
356             * </pre>
357             * </p>
358             *
359             * @param  portletDataContext the context of the current export/import
360             *         process
361             * @return a root path, or fragment, of the model path
362             * @see    PortletDataContext#getScopeGroupId()
363             * @see    #getSourceRootPath(PortletDataContext)
364             */
365            public static String getRootPath(PortletDataContext portletDataContext) {
366                    return getRootPath(
367                            PATH_PREFIX_GROUP, portletDataContext.getScopeGroupId());
368            }
369    
370            public static String getServicePortletPreferencesPath(
371                    PortletDataContext portletDataContext, String serviceName, long ownerId,
372                    int ownerType) {
373    
374                    StringBundler sb = new StringBundler(9);
375    
376                    sb.append(getRootPath(portletDataContext));
377                    sb.append(StringPool.FORWARD_SLASH);
378                    sb.append(PATH_PREFIX_SERVICE);
379                    sb.append(StringPool.FORWARD_SLASH);
380                    sb.append(serviceName);
381                    sb.append(getOwnerTypePath(ownerType));
382                    sb.append(ownerId);
383                    sb.append(CharPool.FORWARD_SLASH);
384                    sb.append("portlet-preferences.xml");
385    
386                    return sb.toString();
387            }
388    
389            /**
390             * @deprecated As of 7.0.0, replaced by {@link
391             *             #getModelPath(PortletDataContext, String, long)}
392             */
393            @Deprecated
394            public static String getSourceLayoutPath(
395                    PortletDataContext portletDataContext, long layoutId) {
396    
397                    StringBundler sb = new StringBundler(5);
398    
399                    sb.append(getSourceRootPath(portletDataContext));
400                    sb.append(StringPool.FORWARD_SLASH);
401                    sb.append(PATH_PREFIX_LAYOUT);
402                    sb.append(StringPool.FORWARD_SLASH);
403                    sb.append(layoutId);
404    
405                    return sb.toString();
406            }
407    
408            /**
409             * @deprecated As of 7.0.0, with no direct replacement
410             */
411            @Deprecated
412            public static String getSourcePortletPath(
413                    PortletDataContext portletDataContext, String portletId) {
414    
415                    StringBundler sb = new StringBundler(5);
416    
417                    sb.append(getSourceRootPath(portletDataContext));
418                    sb.append(StringPool.FORWARD_SLASH);
419                    sb.append(PATH_PREFIX_PORTLET);
420                    sb.append(StringPool.FORWARD_SLASH);
421                    sb.append(portletId);
422    
423                    return sb.toString();
424            }
425    
426            /**
427             * Returns a source root path, or fragment, of the model path. This method
428             * is called by the {@link #getRootPath(PortletDataContext)} method. The
429             * fragment is generated with the source group ID from the portlet data
430             * context. This helper method is useful during the import process.
431             *
432             * <p>
433             * For example, a source root path would resemble the following:
434             * </p>
435             *
436             * <p>
437             * <pre>
438             * <code>
439             * /group/"queried groupId"
440             * </code>
441             * </pre>
442             * </p>
443             *
444             * @param  portletDataContext the context of the current export/import
445             *         process
446             * @return a path fragment
447             * @see    PortletDataContext#getSourceGroupId()
448             */
449            public static String getSourceRootPath(
450                    PortletDataContext portletDataContext) {
451    
452                    return getRootPath(
453                            PATH_PREFIX_GROUP, portletDataContext.getSourceGroupId());
454            }
455    
456            protected static String getModelPath(
457                    String pathPrefix, long pathPrimaryKey, String className,
458                    Serializable primaryKeyObj, String dependentFileName) {
459    
460                    StringBundler sb = new StringBundler(7);
461    
462                    sb.append(getRootPath(pathPrefix, pathPrimaryKey));
463                    sb.append(StringPool.FORWARD_SLASH);
464                    sb.append(className);
465                    sb.append(StringPool.FORWARD_SLASH);
466                    sb.append(primaryKeyObj.toString());
467    
468                    if (dependentFileName == null) {
469                            sb.append(_FILE_EXTENSION_XML);
470                    }
471                    else {
472                            sb.append(StringPool.FORWARD_SLASH);
473                            sb.append(dependentFileName);
474                    }
475    
476                    return sb.toString();
477            }
478    
479            protected static String getOwnerTypePath(int ownerType) {
480                    if (ownerType == PortletKeys.PREFS_OWNER_TYPE_ARCHIVED) {
481                            return "archived/";
482                    }
483                    else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) {
484                            return "company/";
485                    }
486                    else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) {
487                            return "group/";
488                    }
489                    else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_LAYOUT) {
490                            return "layout/";
491                    }
492                    else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_USER) {
493                            return "user/";
494                    }
495                    else {
496                            return StringPool.BLANK;
497                    }
498            }
499    
500            protected static String getRootPath(
501                    String pathPrefix, long pathPrimaryKey) {
502    
503                    StringBundler sb = new StringBundler(4);
504    
505                    sb.append(StringPool.FORWARD_SLASH);
506                    sb.append(pathPrefix);
507                    sb.append(StringPool.FORWARD_SLASH);
508                    sb.append(pathPrimaryKey);
509    
510                    return sb.toString();
511            }
512    
513            private static final String _FILE_EXTENSION_XML = ".xml";
514    
515    }