/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 org.apache.openjpa.slice; import java.util.List; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.UserException; /** * Utility methods to determine the target slices for a persistence capable * instance by calling back to user-specified distribution policy. * * @author Pinaki Poddar * */ public class SliceImplHelper { private static final Localizer _loc = Localizer.forPackage(SliceImplHelper.class); /** * Gets the target slices by calling user-specified {@link DistributionPolicy} or {@link ReplicationPolicy} * depending on whether the given instance is {@link DistributedConfiguration#isReplicated(Class) replicated}. * The policy is invoked when an instance enters the managed life cycle. However, if the instance * being persisted is distributed to a target slice that is <em>not</em> determinable by its own basic attributes, * but on its associated instance then those association may not have been initialized at the point of entry. * In such case, the policy may return null. However, when a target slice may not be determinable at the * entry to managed life cycle, a target slice must be determinable by the time an instance is flushed. * * @param pc the managed instance whose target slice is to be determined. * @param conf to supply the distribution policy * @param ctx the (opaque) context of invocation. No semantics is currently associated. * * @return information about the target slice for the given instance. Can be null if the policy * can not determine the target slice(s) based on the current state of the instance. */ public static SliceInfo getSlicesByPolicy(Object pc, DistributedConfiguration conf, Object ctx) { List<String> actives = conf.getActiveSliceNames(); Object policy = null; String[] targets = null; boolean replicated = isReplicated(pc, conf); if (replicated) { policy = conf.getReplicationPolicyInstance(); targets = ((ReplicationPolicy)policy).replicate(pc, actives, ctx); assertSlices(targets, pc, conf.getActiveSliceNames(), policy); } else { policy = conf.getDistributionPolicyInstance(); String target = ((DistributionPolicy)policy).distribute(pc, actives, ctx); if (target != null) { targets = new String[]{target}; assertSlices(targets, pc, conf.getActiveSliceNames(), policy); } } return targets != null ? new SliceInfo(replicated, targets) : null; } private static void assertSlices(String[] targets, Object pc, List<String> actives, Object policy) { if (targets == null || targets.length == 0) throw new UserException(_loc.get("no-policy-slice", new Object[] { policy.getClass().getName(), pc, actives})); for (String target : targets) if (!actives.contains(target)) throw new UserException(_loc.get("bad-policy-slice", new Object[] {policy.getClass().getName(), target, pc, actives})); } /** * Gets the target slices for the given StateManager. */ public static SliceInfo getSlicesByPolicy(OpenJPAStateManager sm, DistributedConfiguration conf, Object ctx) { return getSlicesByPolicy(sm.getPersistenceCapable(), conf, ctx); } /** * Affirms if the given instance be replicated to multiple slices. */ public static boolean isReplicated(Object pc, DistributedConfiguration conf) { return pc == null ? false : conf.isReplicated(pc.getClass()); } /** * Affirms if the given StateManager has an assigned slice. */ public static boolean isSliceAssigned(OpenJPAStateManager sm) { return sm != null && sm.getImplData() != null && sm.getImplData() instanceof SliceInfo; } /** * Gets the assigned slice information, if any, from the given StateManager. */ public static SliceInfo getSliceInfo(OpenJPAStateManager sm) { return isSliceAssigned(sm) ? (SliceInfo) sm.getImplData() : null; } }