/* * Copyright (c) 2010-2013 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.evolveum.midpoint.prism.xjc; import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.PrismReference; import com.evolveum.midpoint.prism.PrismReferenceValue; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.exception.SystemException; import org.apache.commons.lang.Validate; import java.io.Serializable; import java.util.AbstractList; import java.util.Collection; import java.util.Iterator; import java.util.List; /** * @author lazyman * * TODO: account for concurrent structural modifications using modCount property */ public abstract class PrismReferenceArrayList<T> extends AbstractList<T> implements Serializable { private PrismReference reference; private PrismContainerValue<?> parent; public PrismReferenceArrayList(PrismReference reference, PrismContainerValue<?> parent) { Validate.notNull(reference, "Prism reference must not be null."); this.reference = reference; this.parent = parent; } protected PrismReference getReference() { return reference; } @Override public T get(int i) { testIndex(i); return createItem(getReference().getValues().get(i)); } @Override public int size() { return reference.getValues().size(); } protected abstract T createItem(PrismReferenceValue value); protected abstract PrismReferenceValue getValueFrom(T t); private void testIndex(int i) { if (i < 0 || i >= getReference().getValues().size()) { throw new IndexOutOfBoundsException("Can't get index '" + i + "', values size is '" + getReference().getValues().size() + "'."); } } @Override public T remove(int i) { testIndex(i); PrismReferenceValue value = reference.getValues().get(i); reference.getValues().remove(i); return createItem(value); } @Override public boolean removeAll(Collection<?> objects) { boolean changed = false; for (Object object : objects) { if (!changed) { changed = remove(object); } else { remove(object); } } return changed; } @Override public boolean remove(Object o) { T t = (T) o; PrismReferenceValue value = getValueFrom(t); return reference.getValues().remove(value); } @Override public boolean add(T t) { PrismReferenceValue value = getValueFrom(t); if (reference.getParent() == null) { try { parent.add(reference); } catch (SchemaException e) { throw new SystemException(e.getMessage(), e); } } return reference.merge(value); } @Override public boolean addAll(Collection<? extends T> ts) { boolean changed = false; for (T t : ts) { if (!changed) { changed = add(t); } else { add(t); } } return changed; } /** * JAXB unmarshaller is calling clear() on lists even though they were just * created. As the references should be visible as two JAXB fields, clearing one * of them will also clear the other. Therefore we need this hack. Calling clear() * will only clear the values that naturally "belong" to the list. */ @Override public void clear() { List<PrismReferenceValue> values = reference.getValues(); if (values == null) { return; } Iterator<PrismReferenceValue> iterator = values.iterator(); while (iterator.hasNext()) { PrismReferenceValue value = iterator.next(); if (willClear(value)) { iterator.remove(); } } } protected abstract boolean willClear(PrismReferenceValue value); @Override public boolean isEmpty() { return size() == 0; } }