001package org.hl7.fhir.dstu3.model;
002
003/*-
004 * #%L
005 * org.hl7.fhir.dstu3
006 * %%
007 * Copyright (C) 2014 - 2019 Health Level 7
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 * 
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 * 
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023
024/*
025  Copyright (c) 2011+, HL7, Inc.
026  All rights reserved.
027  
028  Redistribution and use in source and binary forms, with or without modification, 
029  are permitted provided that the following conditions are met:
030  
031   * Redistributions of source code must retain the above copyright notice, this 
032     list of conditions and the following disclaimer.
033   * Redistributions in binary form must reproduce the above copyright notice, 
034     this list of conditions and the following disclaimer in the documentation 
035     and/or other materials provided with the distribution.
036   * Neither the name of HL7 nor the names of its contributors may be used to 
037     endorse or promote products derived from this software without specific 
038     prior written permission.
039  
040  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
041  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
042  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
043  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
044  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
045  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
046  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
047  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
048  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
049  POSSIBILITY OF SUCH DAMAGE.
050  
051*/
052
053// Generated on Fri, Mar 16, 2018 15:21+1100 for FHIR v3.0.x
054import java.util.ArrayList;
055import java.util.Date;
056import java.util.List;
057
058import org.hl7.fhir.exceptions.FHIRException;
059import org.hl7.fhir.instance.model.api.IBaseMetaType;
060import org.hl7.fhir.utilities.Utilities;
061
062import ca.uhn.fhir.model.api.annotation.Child;
063import ca.uhn.fhir.model.api.annotation.DatatypeDef;
064import ca.uhn.fhir.model.api.annotation.Description;
065/**
066 * The metadata about a resource. This is content in the resource that is maintained by the infrastructure. Changes to the content may not always be associated with version changes to the resource.
067 */
068@DatatypeDef(name="Meta")
069public class Meta extends Type implements IBaseMetaType {
070
071    /**
072     * The version specific identifier, as it appears in the version portion of the URL. This values changes when the resource is created, updated, or deleted.
073     */
074    @Child(name = "versionId", type = {IdType.class}, order=0, min=0, max=1, modifier=false, summary=true)
075    @Description(shortDefinition="Version specific identifier", formalDefinition="The version specific identifier, as it appears in the version portion of the URL. This values changes when the resource is created, updated, or deleted." )
076    protected IdType versionId;
077
078    /**
079     * When the resource last changed - e.g. when the version changed.
080     */
081    @Child(name = "lastUpdated", type = {InstantType.class}, order=1, min=0, max=1, modifier=false, summary=true)
082    @Description(shortDefinition="When the resource version last changed", formalDefinition="When the resource last changed - e.g. when the version changed." )
083    protected InstantType lastUpdated;
084
085    /**
086     * A list of profiles (references to [[[StructureDefinition]]] resources) that this resource claims to conform to. The URL is a reference to [[[StructureDefinition.url]]].
087     */
088    @Child(name = "profile", type = {UriType.class}, order=2, min=0, max=Child.MAX_UNLIMITED, modifier=false, summary=true)
089    @Description(shortDefinition="Profiles this resource claims to conform to", formalDefinition="A list of profiles (references to [[[StructureDefinition]]] resources) that this resource claims to conform to. The URL is a reference to [[[StructureDefinition.url]]]." )
090    protected List<UriType> profile;
091
092    /**
093     * Security labels applied to this resource. These tags connect specific resources to the overall security policy and infrastructure.
094     */
095    @Child(name = "security", type = {Coding.class}, order=3, min=0, max=Child.MAX_UNLIMITED, modifier=false, summary=true)
096    @Description(shortDefinition="Security Labels applied to this resource", formalDefinition="Security labels applied to this resource. These tags connect specific resources to the overall security policy and infrastructure." )
097    @ca.uhn.fhir.model.api.annotation.Binding(valueSet="http://hl7.org/fhir/ValueSet/security-labels")
098    protected List<Coding> security;
099
100    /**
101     * Tags applied to this resource. Tags are intended to be used to identify and relate resources to process and workflow, and applications are not required to consider the tags when interpreting the meaning of a resource.
102     */
103    @Child(name = "tag", type = {Coding.class}, order=4, min=0, max=Child.MAX_UNLIMITED, modifier=false, summary=true)
104    @Description(shortDefinition="Tags applied to this resource", formalDefinition="Tags applied to this resource. Tags are intended to be used to identify and relate resources to process and workflow, and applications are not required to consider the tags when interpreting the meaning of a resource." )
105    @ca.uhn.fhir.model.api.annotation.Binding(valueSet="http://hl7.org/fhir/ValueSet/common-tags")
106    protected List<Coding> tag;
107
108    private static final long serialVersionUID = 867134915L;
109
110  /**
111   * Constructor
112   */
113    public Meta() {
114      super();
115    }
116
117    /**
118     * @return {@link #versionId} (The version specific identifier, as it appears in the version portion of the URL. This values changes when the resource is created, updated, or deleted.). This is the underlying object with id, value and extensions. The accessor "getVersionId" gives direct access to the value
119     */
120    public IdType getVersionIdElement() { 
121      if (this.versionId == null)
122        if (Configuration.errorOnAutoCreate())
123          throw new Error("Attempt to auto-create Meta.versionId");
124        else if (Configuration.doAutoCreate())
125          this.versionId = new IdType(); // bb
126      return this.versionId;
127    }
128
129    public boolean hasVersionIdElement() { 
130      return this.versionId != null && !this.versionId.isEmpty();
131    }
132
133    public boolean hasVersionId() { 
134      return this.versionId != null && !this.versionId.isEmpty();
135    }
136
137    /**
138     * @param value {@link #versionId} (The version specific identifier, as it appears in the version portion of the URL. This values changes when the resource is created, updated, or deleted.). This is the underlying object with id, value and extensions. The accessor "getVersionId" gives direct access to the value
139     */
140    public Meta setVersionIdElement(IdType value) { 
141      this.versionId = value;
142      return this;
143    }
144
145    /**
146     * @return The version specific identifier, as it appears in the version portion of the URL. This values changes when the resource is created, updated, or deleted.
147     */
148    public String getVersionId() { 
149      return this.versionId == null ? null : this.versionId.getValue();
150    }
151
152    /**
153     * @param value The version specific identifier, as it appears in the version portion of the URL. This values changes when the resource is created, updated, or deleted.
154     */
155    public Meta setVersionId(String value) { 
156      if (Utilities.noString(value))
157        this.versionId = null;
158      else {
159        if (this.versionId == null)
160          this.versionId = new IdType();
161        this.versionId.setValue(value);
162      }
163      return this;
164    }
165
166    /**
167     * @return {@link #lastUpdated} (When the resource last changed - e.g. when the version changed.). This is the underlying object with id, value and extensions. The accessor "getLastUpdated" gives direct access to the value
168     */
169    public InstantType getLastUpdatedElement() { 
170      if (this.lastUpdated == null)
171        if (Configuration.errorOnAutoCreate())
172          throw new Error("Attempt to auto-create Meta.lastUpdated");
173        else if (Configuration.doAutoCreate())
174          this.lastUpdated = new InstantType(); // bb
175      return this.lastUpdated;
176    }
177
178    public boolean hasLastUpdatedElement() { 
179      return this.lastUpdated != null && !this.lastUpdated.isEmpty();
180    }
181
182    public boolean hasLastUpdated() { 
183      return this.lastUpdated != null && !this.lastUpdated.isEmpty();
184    }
185
186    /**
187     * @param value {@link #lastUpdated} (When the resource last changed - e.g. when the version changed.). This is the underlying object with id, value and extensions. The accessor "getLastUpdated" gives direct access to the value
188     */
189    public Meta setLastUpdatedElement(InstantType value) { 
190      this.lastUpdated = value;
191      return this;
192    }
193
194    /**
195     * @return When the resource last changed - e.g. when the version changed.
196     */
197    public Date getLastUpdated() { 
198      return this.lastUpdated == null ? null : this.lastUpdated.getValue();
199    }
200
201    /**
202     * @param value When the resource last changed - e.g. when the version changed.
203     */
204    public Meta setLastUpdated(Date value) { 
205      if (value == null)
206        this.lastUpdated = null;
207      else {
208        if (this.lastUpdated == null)
209          this.lastUpdated = new InstantType();
210        this.lastUpdated.setValue(value);
211      }
212      return this;
213    }
214
215    /**
216     * @return {@link #profile} (A list of profiles (references to [[[StructureDefinition]]] resources) that this resource claims to conform to. The URL is a reference to [[[StructureDefinition.url]]].)
217     */
218    public List<UriType> getProfile() { 
219      if (this.profile == null)
220        this.profile = new ArrayList<UriType>();
221      return this.profile;
222    }
223
224    /**
225     * @return Returns a reference to <code>this</code> for easy method chaining
226     */
227    public Meta setProfile(List<UriType> theProfile) { 
228      this.profile = theProfile;
229      return this;
230    }
231
232    public boolean hasProfile() { 
233      if (this.profile == null)
234        return false;
235      for (UriType item : this.profile)
236        if (!item.isEmpty())
237          return true;
238      return false;
239    }
240
241    /**
242     * @return {@link #profile} (A list of profiles (references to [[[StructureDefinition]]] resources) that this resource claims to conform to. The URL is a reference to [[[StructureDefinition.url]]].)
243     */
244    public UriType addProfileElement() {//2 
245      UriType t = new UriType();
246      if (this.profile == null)
247        this.profile = new ArrayList<UriType>();
248      this.profile.add(t);
249      return t;
250    }
251
252    /**
253     * @param value {@link #profile} (A list of profiles (references to [[[StructureDefinition]]] resources) that this resource claims to conform to. The URL is a reference to [[[StructureDefinition.url]]].)
254     */
255    public Meta addProfile(String value) { //1
256      UriType t = new UriType();
257      t.setValue(value);
258      if (this.profile == null)
259        this.profile = new ArrayList<UriType>();
260      this.profile.add(t);
261      return this;
262    }
263
264    /**
265     * @param value {@link #profile} (A list of profiles (references to [[[StructureDefinition]]] resources) that this resource claims to conform to. The URL is a reference to [[[StructureDefinition.url]]].)
266     */
267    public boolean hasProfile(String value) { 
268      if (this.profile == null)
269        return false;
270      for (UriType v : this.profile)
271        if (v.getValue().equals(value)) // uri
272          return true;
273      return false;
274    }
275
276    /**
277     * @return {@link #security} (Security labels applied to this resource. These tags connect specific resources to the overall security policy and infrastructure.)
278     */
279    public List<Coding> getSecurity() { 
280      if (this.security == null)
281        this.security = new ArrayList<Coding>();
282      return this.security;
283    }
284
285    /**
286     * @return Returns a reference to <code>this</code> for easy method chaining
287     */
288    public Meta setSecurity(List<Coding> theSecurity) { 
289      this.security = theSecurity;
290      return this;
291    }
292
293    public boolean hasSecurity() { 
294      if (this.security == null)
295        return false;
296      for (Coding item : this.security)
297        if (!item.isEmpty())
298          return true;
299      return false;
300    }
301
302    public Coding addSecurity() { //3
303      Coding t = new Coding();
304      if (this.security == null)
305        this.security = new ArrayList<Coding>();
306      this.security.add(t);
307      return t;
308    }
309
310    public Meta addSecurity(Coding t) { //3
311      if (t == null)
312        return this;
313      if (this.security == null)
314        this.security = new ArrayList<Coding>();
315      this.security.add(t);
316      return this;
317    }
318
319    /**
320     * @return The first repetition of repeating field {@link #security}, creating it if it does not already exist
321     */
322    public Coding getSecurityFirstRep() { 
323      if (getSecurity().isEmpty()) {
324        addSecurity();
325      }
326      return getSecurity().get(0);
327    }
328
329    /**
330     * @return {@link #tag} (Tags applied to this resource. Tags are intended to be used to identify and relate resources to process and workflow, and applications are not required to consider the tags when interpreting the meaning of a resource.)
331     */
332    public List<Coding> getTag() { 
333      if (this.tag == null)
334        this.tag = new ArrayList<Coding>();
335      return this.tag;
336    }
337
338    /**
339     * @return Returns a reference to <code>this</code> for easy method chaining
340     */
341    public Meta setTag(List<Coding> theTag) { 
342      this.tag = theTag;
343      return this;
344    }
345
346    public boolean hasTag() { 
347      if (this.tag == null)
348        return false;
349      for (Coding item : this.tag)
350        if (!item.isEmpty())
351          return true;
352      return false;
353    }
354
355    public Coding addTag() { //3
356      Coding t = new Coding();
357      if (this.tag == null)
358        this.tag = new ArrayList<Coding>();
359      this.tag.add(t);
360      return t;
361    }
362
363    public Meta addTag(Coding t) { //3
364      if (t == null)
365        return this;
366      if (this.tag == null)
367        this.tag = new ArrayList<Coding>();
368      this.tag.add(t);
369      return this;
370    }
371
372    /**
373     * @return The first repetition of repeating field {@link #tag}, creating it if it does not already exist
374     */
375    public Coding getTagFirstRep() { 
376      if (getTag().isEmpty()) {
377        addTag();
378      }
379      return getTag().get(0);
380    }
381
382    /**
383     * Convenience method which adds a tag
384     * 
385     * @param theSystem The code system
386     * @param theCode The code
387     * @param theDisplay The display name
388     * @return Returns a reference to <code>this</code> for easy chaining
389     */
390    public Meta addTag(String theSystem, String theCode, String theDisplay) {
391     addTag().setSystem(theSystem).setCode(theCode).setDisplay(theDisplay);
392     return this;
393    }
394    /**
395     * Convenience method which adds a security tag
396     * 
397     * @param theSystem The code system
398     * @param theCode The code
399     * @param theDisplay The display name
400     * @return Returns a reference to <code>this</code> for easy chaining
401     */
402    public Meta addSecurity(String theSystem, String theCode, String theDisplay) {
403     addSecurity().setSystem(theSystem).setCode(theCode).setDisplay(theDisplay);
404     return this;
405    }
406   /**
407   * Returns the first tag (if any) that has the given system and code, or returns
408   * <code>null</code> if none
409   */
410  public Coding getTag(String theSystem, String theCode) {
411    for (Coding next : getTag()) {
412      if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) {
413        return next;
414      }
415    }
416    return null;
417  }
418
419  /**
420   * Returns the first security label (if any) that has the given system and code, or returns
421   * <code>null</code> if none
422   */
423  public Coding getSecurity(String theSystem, String theCode) {
424    for (Coding next : getTag()) {
425      if (ca.uhn.fhir.util.ObjectUtil.equals(next.getSystem(), theSystem) && ca.uhn.fhir.util.ObjectUtil.equals(next.getCode(), theCode)) {
426        return next;
427      }
428    }
429    return null;
430  }
431      protected void listChildren(List<Property> children) {
432        super.listChildren(children);
433        children.add(new Property("versionId", "id", "The version specific identifier, as it appears in the version portion of the URL. This values changes when the resource is created, updated, or deleted.", 0, 1, versionId));
434        children.add(new Property("lastUpdated", "instant", "When the resource last changed - e.g. when the version changed.", 0, 1, lastUpdated));
435        children.add(new Property("profile", "uri", "A list of profiles (references to [[[StructureDefinition]]] resources) that this resource claims to conform to. The URL is a reference to [[[StructureDefinition.url]]].", 0, java.lang.Integer.MAX_VALUE, profile));
436        children.add(new Property("security", "Coding", "Security labels applied to this resource. These tags connect specific resources to the overall security policy and infrastructure.", 0, java.lang.Integer.MAX_VALUE, security));
437        children.add(new Property("tag", "Coding", "Tags applied to this resource. Tags are intended to be used to identify and relate resources to process and workflow, and applications are not required to consider the tags when interpreting the meaning of a resource.", 0, java.lang.Integer.MAX_VALUE, tag));
438      }
439
440      @Override
441      public Property getNamedProperty(int _hash, String _name, boolean _checkValid) throws FHIRException {
442        switch (_hash) {
443        case -1407102957: /*versionId*/  return new Property("versionId", "id", "The version specific identifier, as it appears in the version portion of the URL. This values changes when the resource is created, updated, or deleted.", 0, 1, versionId);
444        case 1649733957: /*lastUpdated*/  return new Property("lastUpdated", "instant", "When the resource last changed - e.g. when the version changed.", 0, 1, lastUpdated);
445        case -309425751: /*profile*/  return new Property("profile", "uri", "A list of profiles (references to [[[StructureDefinition]]] resources) that this resource claims to conform to. The URL is a reference to [[[StructureDefinition.url]]].", 0, java.lang.Integer.MAX_VALUE, profile);
446        case 949122880: /*security*/  return new Property("security", "Coding", "Security labels applied to this resource. These tags connect specific resources to the overall security policy and infrastructure.", 0, java.lang.Integer.MAX_VALUE, security);
447        case 114586: /*tag*/  return new Property("tag", "Coding", "Tags applied to this resource. Tags are intended to be used to identify and relate resources to process and workflow, and applications are not required to consider the tags when interpreting the meaning of a resource.", 0, java.lang.Integer.MAX_VALUE, tag);
448        default: return super.getNamedProperty(_hash, _name, _checkValid);
449        }
450
451      }
452
453      @Override
454      public Base[] getProperty(int hash, String name, boolean checkValid) throws FHIRException {
455        switch (hash) {
456        case -1407102957: /*versionId*/ return this.versionId == null ? new Base[0] : new Base[] {this.versionId}; // IdType
457        case 1649733957: /*lastUpdated*/ return this.lastUpdated == null ? new Base[0] : new Base[] {this.lastUpdated}; // InstantType
458        case -309425751: /*profile*/ return this.profile == null ? new Base[0] : this.profile.toArray(new Base[this.profile.size()]); // UriType
459        case 949122880: /*security*/ return this.security == null ? new Base[0] : this.security.toArray(new Base[this.security.size()]); // Coding
460        case 114586: /*tag*/ return this.tag == null ? new Base[0] : this.tag.toArray(new Base[this.tag.size()]); // Coding
461        default: return super.getProperty(hash, name, checkValid);
462        }
463
464      }
465
466      @Override
467      public Base setProperty(int hash, String name, Base value) throws FHIRException {
468        switch (hash) {
469        case -1407102957: // versionId
470          this.versionId = castToId(value); // IdType
471          return value;
472        case 1649733957: // lastUpdated
473          this.lastUpdated = castToInstant(value); // InstantType
474          return value;
475        case -309425751: // profile
476          this.getProfile().add(castToUri(value)); // UriType
477          return value;
478        case 949122880: // security
479          this.getSecurity().add(castToCoding(value)); // Coding
480          return value;
481        case 114586: // tag
482          this.getTag().add(castToCoding(value)); // Coding
483          return value;
484        default: return super.setProperty(hash, name, value);
485        }
486
487      }
488
489      @Override
490      public Base setProperty(String name, Base value) throws FHIRException {
491        if (name.equals("versionId")) {
492          this.versionId = castToId(value); // IdType
493        } else if (name.equals("lastUpdated")) {
494          this.lastUpdated = castToInstant(value); // InstantType
495        } else if (name.equals("profile")) {
496          this.getProfile().add(castToUri(value));
497        } else if (name.equals("security")) {
498          this.getSecurity().add(castToCoding(value));
499        } else if (name.equals("tag")) {
500          this.getTag().add(castToCoding(value));
501        } else
502          return super.setProperty(name, value);
503        return value;
504      }
505
506      @Override
507      public Base makeProperty(int hash, String name) throws FHIRException {
508        switch (hash) {
509        case -1407102957:  return getVersionIdElement();
510        case 1649733957:  return getLastUpdatedElement();
511        case -309425751:  return addProfileElement();
512        case 949122880:  return addSecurity(); 
513        case 114586:  return addTag(); 
514        default: return super.makeProperty(hash, name);
515        }
516
517      }
518
519      @Override
520      public String[] getTypesForProperty(int hash, String name) throws FHIRException {
521        switch (hash) {
522        case -1407102957: /*versionId*/ return new String[] {"id"};
523        case 1649733957: /*lastUpdated*/ return new String[] {"instant"};
524        case -309425751: /*profile*/ return new String[] {"uri"};
525        case 949122880: /*security*/ return new String[] {"Coding"};
526        case 114586: /*tag*/ return new String[] {"Coding"};
527        default: return super.getTypesForProperty(hash, name);
528        }
529
530      }
531
532      @Override
533      public Base addChild(String name) throws FHIRException {
534        if (name.equals("versionId")) {
535          throw new FHIRException("Cannot call addChild on a primitive type Meta.versionId");
536        }
537        else if (name.equals("lastUpdated")) {
538          throw new FHIRException("Cannot call addChild on a primitive type Meta.lastUpdated");
539        }
540        else if (name.equals("profile")) {
541          throw new FHIRException("Cannot call addChild on a primitive type Meta.profile");
542        }
543        else if (name.equals("security")) {
544          return addSecurity();
545        }
546        else if (name.equals("tag")) {
547          return addTag();
548        }
549        else
550          return super.addChild(name);
551      }
552
553  public String fhirType() {
554    return "Meta";
555
556  }
557
558      public Meta copy() {
559        Meta dst = new Meta();
560        copyValues(dst);
561        dst.versionId = versionId == null ? null : versionId.copy();
562        dst.lastUpdated = lastUpdated == null ? null : lastUpdated.copy();
563        if (profile != null) {
564          dst.profile = new ArrayList<UriType>();
565          for (UriType i : profile)
566            dst.profile.add(i.copy());
567        };
568        if (security != null) {
569          dst.security = new ArrayList<Coding>();
570          for (Coding i : security)
571            dst.security.add(i.copy());
572        };
573        if (tag != null) {
574          dst.tag = new ArrayList<Coding>();
575          for (Coding i : tag)
576            dst.tag.add(i.copy());
577        };
578        return dst;
579      }
580
581      protected Meta typedCopy() {
582        return copy();
583      }
584
585      @Override
586      public boolean equalsDeep(Base other_) {
587        if (!super.equalsDeep(other_))
588          return false;
589        if (!(other_ instanceof Meta))
590          return false;
591        Meta o = (Meta) other_;
592        return compareDeep(versionId, o.versionId, true) && compareDeep(lastUpdated, o.lastUpdated, true)
593           && compareDeep(profile, o.profile, true) && compareDeep(security, o.security, true) && compareDeep(tag, o.tag, true)
594          ;
595      }
596
597      @Override
598      public boolean equalsShallow(Base other_) {
599        if (!super.equalsShallow(other_))
600          return false;
601        if (!(other_ instanceof Meta))
602          return false;
603        Meta o = (Meta) other_;
604        return compareValues(versionId, o.versionId, true) && compareValues(lastUpdated, o.lastUpdated, true)
605           && compareValues(profile, o.profile, true);
606      }
607
608      public boolean isEmpty() {
609        return super.isEmpty() && ca.uhn.fhir.util.ElementUtil.isEmpty(versionId, lastUpdated, profile
610          , security, tag);
611      }
612
613
614}
615