001/*
002 * Copyright 2012-2018 the original author or authors.
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
017package org.springframework.boot.origin;
018
019import org.springframework.core.io.Resource;
020import org.springframework.util.ObjectUtils;
021
022/**
023 * {@link Origin} for an item loaded from a text resource. Provides access to the original
024 * {@link Resource} that loaded the text and a {@link Location} within it.
025 *
026 * @author Madhura Bhave
027 * @author Phillip Webb
028 * @since 2.0.0
029 */
030public class TextResourceOrigin implements Origin {
031
032        private final Resource resource;
033
034        private final Location location;
035
036        public TextResourceOrigin(Resource resource, Location location) {
037                this.resource = resource;
038                this.location = location;
039        }
040
041        /**
042         * Return the resource where the property originated.
043         * @return the text resource or {@code null}
044         */
045        public Resource getResource() {
046                return this.resource;
047        }
048
049        /**
050         * Return the location of the property within the source (if known).
051         * @return the location or {@code null}
052         */
053        public Location getLocation() {
054                return this.location;
055        }
056
057        @Override
058        public boolean equals(Object obj) {
059                if (this == obj) {
060                        return true;
061                }
062                if (obj == null) {
063                        return false;
064                }
065                if (obj instanceof TextResourceOrigin) {
066                        TextResourceOrigin other = (TextResourceOrigin) obj;
067                        boolean result = true;
068                        result = result && ObjectUtils.nullSafeEquals(this.resource, other.resource);
069                        result = result && ObjectUtils.nullSafeEquals(this.location, other.location);
070                        return result;
071                }
072                return super.equals(obj);
073        }
074
075        @Override
076        public int hashCode() {
077                int result = 1;
078                result = 31 * result + ObjectUtils.nullSafeHashCode(this.resource);
079                result = 31 * result + ObjectUtils.nullSafeHashCode(this.location);
080                return result;
081        }
082
083        @Override
084        public String toString() {
085                StringBuilder result = new StringBuilder();
086                result.append((this.resource != null) ? this.resource.getDescription()
087                                : "unknown resource [?]");
088                if (this.location != null) {
089                        result.append(":").append(this.location);
090                }
091                return result.toString();
092        }
093
094        /**
095         * A location (line and column number) within the resource.
096         */
097        public static final class Location {
098
099                private final int line;
100
101                private final int column;
102
103                /**
104                 * Create a new {@link Location} instance.
105                 * @param line the line number (zero indexed)
106                 * @param column the column number (zero indexed)
107                 */
108                public Location(int line, int column) {
109                        this.line = line;
110                        this.column = column;
111                }
112
113                /**
114                 * Return the line of the text resource where the property originated.
115                 * @return the line number (zero indexed)
116                 */
117                public int getLine() {
118                        return this.line;
119                }
120
121                /**
122                 * Return the column of the text resource where the property originated.
123                 * @return the column number (zero indexed)
124                 */
125                public int getColumn() {
126                        return this.column;
127                }
128
129                @Override
130                public boolean equals(Object obj) {
131                        if (this == obj) {
132                                return true;
133                        }
134                        if (obj == null || getClass() != obj.getClass()) {
135                                return false;
136                        }
137                        Location other = (Location) obj;
138                        boolean result = true;
139                        result = result && this.line == other.line;
140                        result = result && this.column == other.column;
141                        return result;
142                }
143
144                @Override
145                public int hashCode() {
146                        return (31 * this.line) + this.column;
147                }
148
149                @Override
150                public String toString() {
151                        return (this.line + 1) + ":" + (this.column + 1);
152                }
153
154        }
155
156}