001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *        http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 */
019
020package org.apache.isis.core.metamodel.adapter.oid;
021
022import java.io.IOException;
023import java.io.Serializable;
024
025import com.google.common.base.Objects;
026
027import org.apache.isis.applib.DomainObjectContainer;
028import org.apache.isis.applib.annotation.Aggregated;
029import org.apache.isis.core.commons.encoding.DataInputExtended;
030import org.apache.isis.core.commons.encoding.DataOutputExtended;
031import org.apache.isis.core.commons.ensure.Assert;
032import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
033import org.apache.isis.core.metamodel.spec.ObjectSpecId;
034
035/**
036 * Used as the {@link Oid} for {@link Aggregated} {@link ObjectAdapter}s
037 *
038 * <p>
039 * Aggregated adapters are created explicitly by the application using 
040 * {@link DomainObjectContainer#newAggregatedInstance(Object, Class)}.
041 */
042public final class AggregatedOid extends ParentedOid implements TypedOid, Serializable {
043
044    private static final long serialVersionUID = 1L;
045
046    private final ObjectSpecId objectSpecId;
047    private final String localId;
048
049    private int cachedHashCode;
050
051    // /////////////////////////////////////////////////////////
052    // Constructor
053    // /////////////////////////////////////////////////////////
054
055    public AggregatedOid(ObjectSpecId objectSpecId, final TypedOid parentOid, final String localId) {
056        super(parentOid);
057        Assert.assertNotNull("objectSpecId required", objectSpecId);
058        Assert.assertNotNull("LocalId required", localId);
059        this.objectSpecId = objectSpecId;
060        this.localId = localId;
061        cacheState();
062    }
063
064    // /////////////////////////////////////////////////////////
065    // enString
066    // /////////////////////////////////////////////////////////
067
068    public static AggregatedOid deString(String oidStr, OidMarshaller oidMarshaller) {
069        return oidMarshaller.unmarshal(oidStr, AggregatedOid.class);
070    }
071
072    @Override
073    public String enString(OidMarshaller oidMarshaller) {
074        return oidMarshaller.marshal(this);
075    }
076
077    @Override
078    public String enStringNoVersion(OidMarshaller oidMarshaller) {
079        return oidMarshaller.marshalNoVersion(this);
080    }
081
082
083    // ////////////////////////////////////////////
084    // Encodeable
085    // ////////////////////////////////////////////
086
087
088    public AggregatedOid(final DataInputExtended input) throws IOException {
089        this(deString(input.readUTF(), getEncodingMarshaller()));
090    }
091
092    private AggregatedOid(final AggregatedOid oid) throws IOException {
093        super(oid.getParentOid());
094        this.objectSpecId = oid.objectSpecId;
095        this.localId = oid.localId;
096        cacheState();
097    }
098
099    @Override
100    public void encode(final DataOutputExtended output) throws IOException {
101        output.writeUTF(enString(getEncodingMarshaller()));
102    }
103
104    /**
105     * Cannot be a reference because Oid gets serialized by wicket viewer
106     */
107    private static OidMarshaller getEncodingMarshaller() {
108        return new OidMarshaller();
109    }
110
111
112    
113    // /////////////////////////////////////////////////////////
114    // Properties
115    // /////////////////////////////////////////////////////////
116
117    @Override
118    public ObjectSpecId getObjectSpecId() {
119        return objectSpecId;
120    }
121    
122    public String getLocalId() {
123        return localId;
124    }
125
126    
127    // /////////////////////////////////////////////////////////
128    // Value semantics
129    // /////////////////////////////////////////////////////////
130
131    @Override
132    public boolean equals(final Object other) {
133        if (other == this) {
134            return true;
135        }
136        if (other == null) {
137            return false;
138        }
139        if (getClass() != other.getClass()) {
140            return false;
141        }
142        return equals((AggregatedOid) other);
143    }
144
145    public boolean equals(final AggregatedOid other) {
146        return Objects.equal(other.getParentOid(), getParentOid()) && 
147               Objects.equal(other.objectSpecId, objectSpecId) && 
148               Objects.equal(other.localId, localId);
149    }
150
151    @Override
152    public int hashCode() {
153        return cachedHashCode;
154    }
155
156    private void cacheState() {
157        int hashCode = 17;
158        hashCode = 37 * hashCode + getParentOid().hashCode();
159        hashCode = 37 * hashCode + objectSpecId.hashCode();
160        hashCode = 37 * hashCode + localId.hashCode();
161        cachedHashCode = hashCode;
162    }
163
164    
165    // /////////////////////////////////////////////////////////
166    // asPersistent
167    // /////////////////////////////////////////////////////////
168
169    /**
170     * When the parent Oid is persisted, all its &quot;children&quot;
171     * need updating similarly.
172     */
173    public AggregatedOid asPersistent(TypedOid newParentOid) {
174        return new AggregatedOid(objectSpecId, newParentOid, localId);
175    }
176
177
178
179
180
181}