001package org.kuali.common.util.project.model;
002
003import static com.google.common.base.Preconditions.checkArgument;
004import static com.google.common.base.Preconditions.checkNotNull;
005
006import java.io.File;
007
008import org.apache.commons.lang3.StringUtils;
009import org.kuali.common.util.file.CanonicalFile;
010import org.kuali.common.util.metainf.service.MetaInfUtils;
011import org.springframework.util.ResourceUtils;
012
013public final class ProjectResource {
014
015        private final String prefix;
016        private final ProjectIdentifier project;
017        private final String path;
018
019        private ProjectResource(Builder builder) {
020                this.project = builder.project;
021                this.prefix = builder.prefix;
022                this.path = builder.path;
023        }
024
025        /**
026         * Create a {@code ProjectResource} with the prefix set to {@code classpath:}
027         */
028        public static ProjectResource create(ProjectIdentifier project, String path) {
029                return builder(project, path).build();
030        }
031
032        /**
033         * Create a {@code ProjectResource} with the corresponding prefix
034         */
035        public static ProjectResource create(String prefix, ProjectIdentifier project, String path) {
036                return builder(project, path).prefix(prefix).build();
037        }
038
039        /**
040         * Create a {@code ProjectResource} with the prefix set to {@code classpath:}
041         */
042        public static ProjectResource classpath(ProjectIdentifier project, String path) {
043                return classpath(project, path, false);
044        }
045
046        /**
047         * Create a {@code ProjectResource} with the prefix set to {@code classpath:} or {@code classpath:META-INF/}
048         */
049        public static ProjectResource classpath(ProjectIdentifier project, String path, boolean metainf) {
050                return builder(project, path).classpathPrefix(metainf).build();
051        }
052
053        /**
054         * Create a {@code ProjectResource} with the prefix set to {@code directory} and optionally further prefixed with {@code META-INF}
055         */
056        public static ProjectResource directory(File directory, ProjectIdentifier project, String path, boolean metainf) {
057                return builder(project, path).directoryPrefix(directory, metainf).build();
058        }
059
060        /**
061         * Create a {@code ProjectResource} with the prefix set to {@code directory}
062         */
063        public static ProjectResource directory(File directory, ProjectIdentifier project, String path) {
064                return directory(directory, project, path, false);
065        }
066
067        public static Builder builder(ProjectIdentifier project, String path) {
068                return new Builder(project, path);
069        }
070
071        public static class Builder {
072
073                // Required
074                private final ProjectIdentifier project;
075                private final String path;
076
077                // Optional
078                private String prefix = ResourceUtils.CLASSPATH_URL_PREFIX;
079
080                public Builder(ProjectIdentifier project, String path) {
081                        this.project = project;
082                        this.path = path;
083                }
084
085                /**
086                 * {@code classpath:}
087                 */
088                public Builder classpathPrefix() {
089                        return prefix(ResourceUtils.CLASSPATH_URL_PREFIX);
090                }
091
092                /**
093                 * {@code classpath:} or {@code classpath:META-INF/}
094                 */
095                public Builder classpathPrefix(boolean metainf) {
096                        if (metainf) {
097                                return prefix(ResourceUtils.CLASSPATH_URL_PREFIX + MetaInfUtils.METAINF_DIRECTORY_NAME + "/");
098                        } else {
099                                return classpathPrefix();
100                        }
101                }
102
103                /**
104                 * {@code /tmp/}
105                 */
106                public Builder directoryPrefix(File directory) {
107                        return directoryPrefix(directory, false);
108                }
109
110                /**
111                 * {@code /tmp/} or {@code /tmp/META-INF/}
112                 */
113                public Builder directoryPrefix(File directory, boolean metainf) {
114                        String path = new CanonicalFile(directory).getPath() + File.pathSeparator;
115                        if (metainf) {
116                                return prefix(path + MetaInfUtils.METAINF_DIRECTORY_NAME + File.pathSeparator);
117                        } else {
118                                return prefix(path);
119                        }
120                }
121
122                /**
123                 * Typically {@code classpath:}
124                 */
125                public Builder prefix(String prefix) {
126                        this.prefix = prefix;
127                        return this;
128                }
129
130                public ProjectResource build() {
131                        ProjectResource instance = new ProjectResource(this);
132                        validate(instance);
133                        return instance;
134                }
135
136                private static void validate(ProjectResource instance) {
137                        checkNotNull(instance.project, "'project' cannot be null");
138                        checkArgument(!StringUtils.isBlank(instance.path), "'path' cannot be blank");
139                        checkArgument(!StringUtils.isBlank(instance.prefix), "'prefix' cannot be blank");
140                }
141        }
142
143        public ProjectIdentifier getProject() {
144                return project;
145        }
146
147        public String getPrefix() {
148                return prefix;
149        }
150
151        public String getPath() {
152                return path;
153        }
154
155}